|
|
|
|
@ -211,11 +211,12 @@ async function handle(req, res, pathname, body) {
@@ -211,11 +211,12 @@ async function handle(req, res, pathname, body) {
|
|
|
|
|
if (req.method === 'PUT') { |
|
|
|
|
const b = body || {}; |
|
|
|
|
const memOk = b.memories && typeof b.memories === 'object' && !Array.isArray(b.memories); |
|
|
|
|
const next = { |
|
|
|
|
let existingChats = {}; try { const cur = JSON.parse(fs.readFileSync(stateFile, 'utf8')); if (cur && cur.chats && typeof cur.chats === 'object') existingChats = cur.chats; } catch (e) { } const chatsOk = b.chats && typeof b.chats === 'object'; const next = { |
|
|
|
|
version: 1, |
|
|
|
|
updatedAt: new Date().toISOString(), |
|
|
|
|
memories: memOk ? b.memories : {}, |
|
|
|
|
skills: Array.isArray(b.skills) ? b.skills : [], |
|
|
|
|
chats: chatsOk ? b.chats : existingChats, |
|
|
|
|
}; |
|
|
|
|
fs.mkdirSync(memDir, { recursive: true }); |
|
|
|
|
const tmp = stateFile + '.tmp'; |
|
|
|
|
@ -225,6 +226,40 @@ async function handle(req, res, pathname, body) {
@@ -225,6 +226,40 @@ async function handle(req, res, pathname, body) {
|
|
|
|
|
} |
|
|
|
|
throw new ToolError('E_ARGS_INVALID', 'GET or PUT only'); |
|
|
|
|
} |
|
|
|
|
case '/memory/chats': { |
|
|
|
|
const memDir = resolveMemoryDir(config, BRIDGE_DIR); |
|
|
|
|
const stateFile = path.join(memDir, 'state.json'); |
|
|
|
|
let st = {}; |
|
|
|
|
try { st = JSON.parse(fs.readFileSync(stateFile, 'utf8')); } catch (e) { st = {}; } |
|
|
|
|
if (!st.chats || typeof st.chats !== 'object') st.chats = {}; |
|
|
|
|
if (req.method === 'GET') { |
|
|
|
|
const id = (body && body.chatId) ? String(body.chatId) : ''; |
|
|
|
|
if (id) return { ok: true, data: st.chats[id] || null }; |
|
|
|
|
return { ok: true, data: st.chats }; |
|
|
|
|
} |
|
|
|
|
if (req.method === 'POST') { |
|
|
|
|
const b = body || {}; |
|
|
|
|
const id = b.chatId ? String(b.chatId) : ''; |
|
|
|
|
if (!id || id.length > 64 || id.indexOf('/') !== -1) throw new ToolError('E_ARGS_INVALID', 'bad chatId'); |
|
|
|
|
const entry = (b.entry && typeof b.entry === 'object') ? b.entry : {}; |
|
|
|
|
entry.updatedAt = Date.now(); |
|
|
|
|
st.chats[id] = entry; |
|
|
|
|
const ids = Object.keys(st.chats); |
|
|
|
|
if (ids.length > 20) { |
|
|
|
|
ids.sort(function (x, y) { return (st.chats[x].updatedAt || 0) - (st.chats[y].updatedAt || 0); }); |
|
|
|
|
const drop = ids.length - 20; |
|
|
|
|
for (let i = 0; i < drop; i++) delete st.chats[ids[i]]; |
|
|
|
|
} |
|
|
|
|
st.version = st.version || 1; |
|
|
|
|
st.updatedAt = new Date().toISOString(); |
|
|
|
|
fs.mkdirSync(memDir, { recursive: true }); |
|
|
|
|
const tmp = stateFile + '.tmp'; |
|
|
|
|
fs.writeFileSync(tmp, JSON.stringify(st, null, 2), 'utf8'); |
|
|
|
|
fs.renameSync(tmp, stateFile); |
|
|
|
|
return { ok: true, data: st.chats[id] }; |
|
|
|
|
} |
|
|
|
|
throw new ToolError('E_ARGS_INVALID', 'GET or POST only'); |
|
|
|
|
} |
|
|
|
|
case '/log/append': { |
|
|
|
|
if (req.method !== 'POST') throw new ToolError('E_ARGS_INVALID', 'only POST'); |
|
|
|
|
const file = body && body.file; |
|
|
|
|
|