feat(memory): persistent memory layer with remember/recall CodeAct API

Add a memories table (survives index rebuilds) for agent-written
  conclusions with provenance (session, message range, project). The agent
  writes markdown files via Write tool (user-approved), then registers
  them via a --remember CodeAct script with remember(). Recall via
  memories() in --query scripts, filtered by project/session/time.

  Separates query (read-only, assertReadOnlySql) from remember (write)
  execution contexts in runtime.mjs.
This commit is contained in:
tommy0103
2026-06-10 02:05:27 +08:00
parent dff88bbb37
commit 34f3a164ab
9 changed files with 364 additions and 29 deletions
+20 -4
View File
@@ -7,10 +7,9 @@ const vm = require('node:vm');
import { DB_PATH, openDb } from './db.mjs';
import { buildIndex } from './indexer.mjs';
import { createQueryApi } from './query.mjs';
import { createQueryApi, createRememberApi } from './query.mjs';
function executeQuery(db, scriptContent) {
const api = createQueryApi(db);
function executeScript(api, scriptContent) {
const sandbox = {
...api, JSON, Math, Array, Object, Set, Map, Date, RegExp,
parseInt, parseFloat, String, Number, Boolean, Error, Promise, console, setTimeout,
@@ -19,6 +18,14 @@ function executeQuery(db, scriptContent) {
return vm.runInNewContext(`(async()=>{${scriptContent}})()`, ctx, { timeout: 30000 });
}
function executeQuery(db, scriptContent) {
return executeScript(createQueryApi(db), scriptContent);
}
function executeRemember(db, scriptContent) {
return executeScript(createRememberApi(db), scriptContent);
}
function main() {
const args = process.argv.slice(2);
if (args[0] === '--build') {
@@ -42,7 +49,16 @@ function main() {
.catch(e => { process.stdout.write(JSON.stringify({ error: e.message, stack: e.stack }) + '\n'); db.close(); process.exitCode = 1; });
return;
}
process.stderr.write('Usage:\n node runtime.mjs --build\n node runtime.mjs --search "text"\n node runtime.mjs --query <file.js>\n');
if (args[0] === '--remember' && args[1]) {
buildIndex();
const db = openDb();
const script = fs.readFileSync(path.resolve(args[1]), 'utf8');
executeRemember(db, script)
.then(r => { process.stdout.write(JSON.stringify(r, null, 2) + '\n'); db.close(); })
.catch(e => { process.stdout.write(JSON.stringify({ error: e.message, stack: e.stack }) + '\n'); db.close(); process.exitCode = 1; });
return;
}
process.stderr.write('Usage:\n node runtime.mjs --build\n node runtime.mjs --search "text"\n node runtime.mjs --query <file.js>\n node runtime.mjs --remember <file.js>\n');
process.exitCode = 1;
}