ahok-skill 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +8 -0
- package/Dockerfile +59 -0
- package/RAW_SKILL.md +219 -0
- package/README.md +277 -0
- package/SKILL.md +58 -0
- package/bin/opm.js +268 -0
- package/data/openmemory.sqlite +0 -0
- package/data/openmemory.sqlite-shm +0 -0
- package/data/openmemory.sqlite-wal +0 -0
- package/dist/ai/graph.js +293 -0
- package/dist/ai/mcp.js +397 -0
- package/dist/cli.js +78 -0
- package/dist/core/cfg.js +87 -0
- package/dist/core/db.js +636 -0
- package/dist/core/memory.js +116 -0
- package/dist/core/migrate.js +227 -0
- package/dist/core/models.js +105 -0
- package/dist/core/telemetry.js +57 -0
- package/dist/core/types.js +2 -0
- package/dist/core/vector/postgres.js +52 -0
- package/dist/core/vector/valkey.js +246 -0
- package/dist/core/vector_store.js +2 -0
- package/dist/index.js +44 -0
- package/dist/memory/decay.js +301 -0
- package/dist/memory/embed.js +675 -0
- package/dist/memory/hsg.js +959 -0
- package/dist/memory/reflect.js +131 -0
- package/dist/memory/user_summary.js +99 -0
- package/dist/migrate.js +9 -0
- package/dist/ops/compress.js +255 -0
- package/dist/ops/dynamics.js +189 -0
- package/dist/ops/extract.js +333 -0
- package/dist/ops/ingest.js +214 -0
- package/dist/server/index.js +109 -0
- package/dist/server/middleware/auth.js +137 -0
- package/dist/server/routes/auth.js +186 -0
- package/dist/server/routes/compression.js +108 -0
- package/dist/server/routes/dashboard.js +399 -0
- package/dist/server/routes/docs.js +241 -0
- package/dist/server/routes/dynamics.js +312 -0
- package/dist/server/routes/ide.js +280 -0
- package/dist/server/routes/index.js +33 -0
- package/dist/server/routes/keys.js +132 -0
- package/dist/server/routes/langgraph.js +61 -0
- package/dist/server/routes/memory.js +213 -0
- package/dist/server/routes/sources.js +140 -0
- package/dist/server/routes/system.js +63 -0
- package/dist/server/routes/temporal.js +293 -0
- package/dist/server/routes/users.js +101 -0
- package/dist/server/routes/vercel.js +57 -0
- package/dist/server/server.js +211 -0
- package/dist/server.js +3 -0
- package/dist/sources/base.js +223 -0
- package/dist/sources/github.js +171 -0
- package/dist/sources/google_drive.js +166 -0
- package/dist/sources/google_sheets.js +112 -0
- package/dist/sources/google_slides.js +139 -0
- package/dist/sources/index.js +34 -0
- package/dist/sources/notion.js +165 -0
- package/dist/sources/onedrive.js +143 -0
- package/dist/sources/web_crawler.js +166 -0
- package/dist/temporal_graph/index.js +20 -0
- package/dist/temporal_graph/query.js +240 -0
- package/dist/temporal_graph/store.js +116 -0
- package/dist/temporal_graph/timeline.js +241 -0
- package/dist/temporal_graph/types.js +2 -0
- package/dist/utils/chunking.js +60 -0
- package/dist/utils/index.js +31 -0
- package/dist/utils/keyword.js +94 -0
- package/dist/utils/text.js +120 -0
- package/nodemon.json +7 -0
- package/package.json +50 -0
- package/references/api_reference.md +66 -0
- package/references/examples.md +45 -0
- package/src/ai/graph.ts +363 -0
- package/src/ai/mcp.ts +494 -0
- package/src/cli.ts +94 -0
- package/src/core/cfg.ts +110 -0
- package/src/core/db.ts +1052 -0
- package/src/core/memory.ts +99 -0
- package/src/core/migrate.ts +302 -0
- package/src/core/models.ts +107 -0
- package/src/core/telemetry.ts +47 -0
- package/src/core/types.ts +130 -0
- package/src/core/vector/postgres.ts +61 -0
- package/src/core/vector/valkey.ts +261 -0
- package/src/core/vector_store.ts +9 -0
- package/src/index.ts +5 -0
- package/src/memory/decay.ts +427 -0
- package/src/memory/embed.ts +707 -0
- package/src/memory/hsg.ts +1245 -0
- package/src/memory/reflect.ts +158 -0
- package/src/memory/user_summary.ts +110 -0
- package/src/migrate.ts +8 -0
- package/src/ops/compress.ts +296 -0
- package/src/ops/dynamics.ts +272 -0
- package/src/ops/extract.ts +360 -0
- package/src/ops/ingest.ts +286 -0
- package/src/server/index.ts +159 -0
- package/src/server/middleware/auth.ts +156 -0
- package/src/server/routes/auth.ts +223 -0
- package/src/server/routes/compression.ts +106 -0
- package/src/server/routes/dashboard.ts +420 -0
- package/src/server/routes/docs.ts +380 -0
- package/src/server/routes/dynamics.ts +516 -0
- package/src/server/routes/ide.ts +283 -0
- package/src/server/routes/index.ts +32 -0
- package/src/server/routes/keys.ts +131 -0
- package/src/server/routes/langgraph.ts +71 -0
- package/src/server/routes/memory.ts +440 -0
- package/src/server/routes/sources.ts +111 -0
- package/src/server/routes/system.ts +68 -0
- package/src/server/routes/temporal.ts +335 -0
- package/src/server/routes/users.ts +111 -0
- package/src/server/routes/vercel.ts +55 -0
- package/src/server/server.js +215 -0
- package/src/server.ts +1 -0
- package/src/sources/base.ts +257 -0
- package/src/sources/github.ts +156 -0
- package/src/sources/google_drive.ts +144 -0
- package/src/sources/google_sheets.ts +85 -0
- package/src/sources/google_slides.ts +115 -0
- package/src/sources/index.ts +19 -0
- package/src/sources/notion.ts +148 -0
- package/src/sources/onedrive.ts +131 -0
- package/src/sources/web_crawler.ts +161 -0
- package/src/temporal_graph/index.ts +4 -0
- package/src/temporal_graph/query.ts +299 -0
- package/src/temporal_graph/store.ts +156 -0
- package/src/temporal_graph/timeline.ts +319 -0
- package/src/temporal_graph/types.ts +41 -0
- package/src/utils/chunking.ts +66 -0
- package/src/utils/index.ts +25 -0
- package/src/utils/keyword.ts +137 -0
- package/src/utils/text.ts +115 -0
- package/tests/test_api_workspace_management.ts +413 -0
- package/tests/test_bulk_delete.ts +267 -0
- package/tests/test_omnibus.ts +166 -0
- package/tests/test_workspace_management.ts +278 -0
- package/tests/verify.ts +104 -0
- package/tsconfig.json +15 -0
package/bin/opm.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// load .env from root
|
|
7
|
+
const loadenv = () => {
|
|
8
|
+
const envp = path.join(__dirname, '..', '..', '.env');
|
|
9
|
+
if (!fs.existsSync(envp)) return;
|
|
10
|
+
const lns = fs.readFileSync(envp, 'utf8').split('\n');
|
|
11
|
+
for (const ln of lns) {
|
|
12
|
+
const trim = ln.trim();
|
|
13
|
+
if (!trim || trim.startsWith('#')) continue;
|
|
14
|
+
const m = trim.match(/^([A-Z_]+)=(.*)$/);
|
|
15
|
+
if (m && !process.env[m[1]]) {
|
|
16
|
+
process.env[m[1]] = m[2].replace(/^["']|["']$/g, '');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
loadenv();
|
|
21
|
+
|
|
22
|
+
const port = process.env.OM_PORT || '8080';
|
|
23
|
+
const url = process.env.OPENMEMORY_URL || `http://localhost:${port}`;
|
|
24
|
+
const key = process.env.OPENMEMORY_API_KEY || process.env.OM_API_KEY || '';
|
|
25
|
+
|
|
26
|
+
const helptext = `
|
|
27
|
+
openmemory cli (opm)
|
|
28
|
+
|
|
29
|
+
usage: opm <command> [options]
|
|
30
|
+
|
|
31
|
+
commands:
|
|
32
|
+
add <text> add memory
|
|
33
|
+
query <text> search memories
|
|
34
|
+
list show all memories
|
|
35
|
+
delete <id> delete memory
|
|
36
|
+
stats show stats
|
|
37
|
+
users list users
|
|
38
|
+
user <id> get user summary
|
|
39
|
+
health ping server
|
|
40
|
+
mcp start mcp server (stdio)
|
|
41
|
+
|
|
42
|
+
options:
|
|
43
|
+
--user <id> user id
|
|
44
|
+
--tags <t1,t2> comma tags
|
|
45
|
+
--limit <n> result limit (default: 10)
|
|
46
|
+
-h, --help show help
|
|
47
|
+
|
|
48
|
+
env vars:
|
|
49
|
+
OPENMEMORY_URL api url (default: http://localhost:8080)
|
|
50
|
+
OPENMEMORY_API_KEY auth key
|
|
51
|
+
OM_API_KEY alt auth key
|
|
52
|
+
|
|
53
|
+
examples:
|
|
54
|
+
opm add "user likes dark mode" --user u123 --tags prefs
|
|
55
|
+
opm query "preferences" --user u123
|
|
56
|
+
opm list --limit 5
|
|
57
|
+
opm user u123
|
|
58
|
+
opm stats
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
const hdrs = {
|
|
62
|
+
'content-type': 'application/json',
|
|
63
|
+
...(key && { authorization: `Bearer ${key}` }),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const req = async (pth, opts = {}) => {
|
|
67
|
+
const target = `${url}${pth}`;
|
|
68
|
+
try {
|
|
69
|
+
const res = await fetch(target, {
|
|
70
|
+
...opts,
|
|
71
|
+
headers: { ...hdrs, ...opts.headers },
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
const txt = await res.text().catch(() => 'no response');
|
|
75
|
+
throw new Error(`http ${res.status}: ${txt}`);
|
|
76
|
+
}
|
|
77
|
+
return await res.json();
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error(`[error] ${e.message}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const addmem = async (txt, opts) => {
|
|
85
|
+
const body = { content: txt };
|
|
86
|
+
if (opts.usr) body.user_id = opts.usr;
|
|
87
|
+
if (opts.tags) body.tags = opts.tags.split(',');
|
|
88
|
+
const r = await req('/memory/add', {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
body: JSON.stringify(body),
|
|
91
|
+
});
|
|
92
|
+
console.log('[ok] memory added');
|
|
93
|
+
console.log(`id: ${r.id}`);
|
|
94
|
+
console.log(`sector: ${r.primary_sector}`);
|
|
95
|
+
console.log(`salience: ${r.salience?.toFixed(3) || 'n/a'}`);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const querymem = async (txt, opts) => {
|
|
99
|
+
const body = { query: txt, k: opts.lim || 10 };
|
|
100
|
+
if (opts.usr) body.filters = { user_id: opts.usr };
|
|
101
|
+
const r = await req('/memory/query', {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
body: JSON.stringify(body),
|
|
104
|
+
});
|
|
105
|
+
console.log(`[results] ${r.memories.length} found\n`);
|
|
106
|
+
r.memories.forEach((m, i) => {
|
|
107
|
+
console.log(`${i + 1}. [${m.primary_sector}] ${m.content}`);
|
|
108
|
+
console.log(` id: ${m.id}`);
|
|
109
|
+
console.log(
|
|
110
|
+
` score: ${m.score?.toFixed(3) || 'n/a'} | sal: ${m.salience.toFixed(
|
|
111
|
+
3,
|
|
112
|
+
)}`,
|
|
113
|
+
);
|
|
114
|
+
if (m.tags) console.log(` tags: ${m.tags}`);
|
|
115
|
+
console.log();
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const listmem = async (opts) => {
|
|
120
|
+
const lim = opts.lim || 10;
|
|
121
|
+
const off = 0;
|
|
122
|
+
let r;
|
|
123
|
+
if (opts.usr) {
|
|
124
|
+
r = await req(`/users/${opts.usr}/memories?l=${lim}&u=${off}`);
|
|
125
|
+
} else {
|
|
126
|
+
r = await req(`/memory/all?limit=${lim}&offset=${off}`);
|
|
127
|
+
}
|
|
128
|
+
const items = r.items || r.memories || [];
|
|
129
|
+
console.log(`[memories] showing ${items.length}\n`);
|
|
130
|
+
items.forEach((m, i) => {
|
|
131
|
+
console.log(`${i + 1}. [${m.primary_sector}] ${m.content}`);
|
|
132
|
+
console.log(` id: ${m.id} | user: ${opts.usr || 'system'}`);
|
|
133
|
+
console.log(` sal: ${m.salience.toFixed(3)}`);
|
|
134
|
+
if (m.tags) console.log(` tags: ${m.tags}`);
|
|
135
|
+
console.log();
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const delmem = async (id) => {
|
|
140
|
+
await req(`/memory/${id}`, { method: 'DELETE' });
|
|
141
|
+
console.log(`[ok] memory ${id} deleted`);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const getstats = async () => {
|
|
145
|
+
const r = await req('/dashboard/stats');
|
|
146
|
+
console.log('[stats]\n');
|
|
147
|
+
console.log(`total memories: ${r.totalMemories || 0}`);
|
|
148
|
+
console.log(`recent memories (24h): ${r.recentMemories || 0}`);
|
|
149
|
+
console.log(`avg salience: ${r.avgSalience || 'n/a'}`);
|
|
150
|
+
console.log(`\nmemories by sector:`);
|
|
151
|
+
Object.entries(r.sectorCounts || {}).forEach(([sec, cnt]) => {
|
|
152
|
+
console.log(` ${sec}: ${cnt}`);
|
|
153
|
+
});
|
|
154
|
+
if (r.decayStats) {
|
|
155
|
+
console.log(`\ndecay stats:`);
|
|
156
|
+
console.log(` avg lambda: ${r.decayStats.avgLambda}`);
|
|
157
|
+
console.log(` min salience: ${r.decayStats.minSalience}`);
|
|
158
|
+
console.log(` max salience: ${r.decayStats.maxSalience}`);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const listusers = async () => {
|
|
163
|
+
const r = await req('/users');
|
|
164
|
+
console.log(`[users] ${r.users.length} found\n`);
|
|
165
|
+
r.users.forEach((u, i) => {
|
|
166
|
+
console.log(`${i + 1}. ${u.user_id}`);
|
|
167
|
+
console.log(` memories: ${u.memory_count || 0}`);
|
|
168
|
+
console.log(` reflections: ${u.reflection_count || 0}`);
|
|
169
|
+
if (u.summary) console.log(` summary: ${u.summary.substring(0, 100)}...`);
|
|
170
|
+
console.log();
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const getuser = async (uid) => {
|
|
175
|
+
const r = await req(`/users/${uid}/summary`);
|
|
176
|
+
console.log(`[user] ${uid}\n`);
|
|
177
|
+
console.log(`summary:\n${r.summary || 'no summary'}\n`);
|
|
178
|
+
console.log(`memories: ${r.memory_count || 0}`);
|
|
179
|
+
console.log(`reflections: ${r.reflection_count || 0}`);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const health = async () => {
|
|
183
|
+
const r = await req('/health');
|
|
184
|
+
console.log(`[health] ${r.status}`);
|
|
185
|
+
if (r.version) console.log(`version: ${r.version}`);
|
|
186
|
+
if (r.uptime) console.log(`uptime: ${Math.floor(r.uptime / 1000)}s`);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// parse args
|
|
190
|
+
const argv = process.argv.slice(2);
|
|
191
|
+
const cmd = argv[0];
|
|
192
|
+
|
|
193
|
+
if (!cmd || cmd === '--help' || cmd === '-h') {
|
|
194
|
+
console.log(helptext);
|
|
195
|
+
process.exit(0);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const opts = {};
|
|
199
|
+
for (let i = 1; i < argv.length; i++) {
|
|
200
|
+
if (argv[i] === '--user') opts.usr = argv[++i];
|
|
201
|
+
else if (argv[i] === '--tags') opts.tags = argv[++i];
|
|
202
|
+
else if (argv[i] === '--limit') opts.lim = parseInt(argv[++i]);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// run command
|
|
206
|
+
(async () => {
|
|
207
|
+
try {
|
|
208
|
+
switch (cmd) {
|
|
209
|
+
case 'add':
|
|
210
|
+
if (!argv[1]) throw new Error('content required: opm add "text"');
|
|
211
|
+
await addmem(
|
|
212
|
+
argv.slice(1, argv.indexOf('--')).join(' ') || argv[1],
|
|
213
|
+
opts,
|
|
214
|
+
);
|
|
215
|
+
break;
|
|
216
|
+
case 'query':
|
|
217
|
+
if (!argv[1]) throw new Error('query text required: opm query "text"');
|
|
218
|
+
await querymem(
|
|
219
|
+
argv.slice(1, argv.indexOf('--')).join(' ') || argv[1],
|
|
220
|
+
opts,
|
|
221
|
+
);
|
|
222
|
+
break;
|
|
223
|
+
case 'list':
|
|
224
|
+
await listmem(opts);
|
|
225
|
+
break;
|
|
226
|
+
case 'delete':
|
|
227
|
+
if (!argv[1]) throw new Error('id required: opm delete <id>');
|
|
228
|
+
await delmem(argv[1]);
|
|
229
|
+
break;
|
|
230
|
+
case 'stats':
|
|
231
|
+
await getstats();
|
|
232
|
+
break;
|
|
233
|
+
case 'users':
|
|
234
|
+
await listusers();
|
|
235
|
+
break;
|
|
236
|
+
case 'user':
|
|
237
|
+
if (!argv[1]) throw new Error('user id required: opm user <id>');
|
|
238
|
+
await getuser(argv[1]);
|
|
239
|
+
break;
|
|
240
|
+
case 'health':
|
|
241
|
+
await health();
|
|
242
|
+
break;
|
|
243
|
+
case 'mcp':
|
|
244
|
+
// Start MCP server (requires build)
|
|
245
|
+
try {
|
|
246
|
+
const mcp = require('../dist/ai/mcp.js');
|
|
247
|
+
if (mcp && mcp.start_mcp_stdio) {
|
|
248
|
+
await mcp.start_mcp_stdio();
|
|
249
|
+
} else {
|
|
250
|
+
console.error('[error] mcp module missing start_mcp_stdio export');
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
} catch (e) {
|
|
254
|
+
console.error('[error] failed to start mcp server. ensure project is built (npm run build).');
|
|
255
|
+
console.error(e.message);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
break;
|
|
259
|
+
default:
|
|
260
|
+
console.error(`[error] unknown command: ${cmd}`);
|
|
261
|
+
console.log(helptext);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
} catch (e) {
|
|
265
|
+
console.error(`[error] ${e.message}`);
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
})();
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/ai/graph.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.get_lg_cfg = exports.node_sector_map = void 0;
|
|
4
|
+
exports.store_node_mem = store_node_mem;
|
|
5
|
+
exports.retrieve_node_mems = retrieve_node_mems;
|
|
6
|
+
exports.get_graph_ctx = get_graph_ctx;
|
|
7
|
+
exports.create_refl = create_refl;
|
|
8
|
+
const cfg_1 = require("../core/cfg");
|
|
9
|
+
const hsg_1 = require("../memory/hsg");
|
|
10
|
+
const db_1 = require("../core/db");
|
|
11
|
+
const utils_1 = require("../utils");
|
|
12
|
+
exports.node_sector_map = {
|
|
13
|
+
observe: "episodic",
|
|
14
|
+
plan: "semantic",
|
|
15
|
+
reflect: "reflective",
|
|
16
|
+
act: "procedural",
|
|
17
|
+
emotion: "emotional",
|
|
18
|
+
};
|
|
19
|
+
const default_sector = "semantic";
|
|
20
|
+
const summary_line_limit = 160;
|
|
21
|
+
const trunc = (txt, max = 320) => txt.length <= max ? txt : `${txt.slice(0, max).trimEnd()}...`;
|
|
22
|
+
const safe_parse = (val, fb) => {
|
|
23
|
+
if (!val)
|
|
24
|
+
return fb;
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(val);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return fb;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const resolve_sector = (node) => exports.node_sector_map[node.toLowerCase()] ?? default_sector;
|
|
33
|
+
const resolve_ns = (ns) => ns || cfg_1.env.lg_namespace;
|
|
34
|
+
const build_tags = (tags, node, ns, gid) => {
|
|
35
|
+
const ts = new Set(tags || []);
|
|
36
|
+
ts.add(`lgm:node:${node.toLowerCase()}`);
|
|
37
|
+
ts.add(`lgm:namespace:${ns}`);
|
|
38
|
+
if (gid)
|
|
39
|
+
ts.add(`lgm:graph:${gid}`);
|
|
40
|
+
return Array.from(ts);
|
|
41
|
+
};
|
|
42
|
+
const build_meta = (p, sec, ns, ext) => {
|
|
43
|
+
const base = { ...(p.metadata || {}) };
|
|
44
|
+
const ex_lgm = typeof base.lgm === "object" && base.lgm !== null
|
|
45
|
+
? base.lgm
|
|
46
|
+
: {};
|
|
47
|
+
base.lgm = {
|
|
48
|
+
...ex_lgm,
|
|
49
|
+
node: p.node.toLowerCase(),
|
|
50
|
+
sector: sec,
|
|
51
|
+
namespace: ns,
|
|
52
|
+
graph_id: p.graph_id ?? null,
|
|
53
|
+
stored_at: (0, utils_1.now)(),
|
|
54
|
+
mode: "langgraph",
|
|
55
|
+
...ext,
|
|
56
|
+
};
|
|
57
|
+
return base;
|
|
58
|
+
};
|
|
59
|
+
const matches_ns = (meta, ns, gid) => {
|
|
60
|
+
const lgm = meta?.lgm;
|
|
61
|
+
if (!lgm)
|
|
62
|
+
return false;
|
|
63
|
+
if (lgm.namespace !== ns)
|
|
64
|
+
return false;
|
|
65
|
+
if (gid && lgm.graph_id !== gid)
|
|
66
|
+
return false;
|
|
67
|
+
return true;
|
|
68
|
+
};
|
|
69
|
+
const hydrate_mem_row = async (row, meta, inc_meta, score, path) => {
|
|
70
|
+
const tags = safe_parse(row.tags, []);
|
|
71
|
+
const vecs = await db_1.vector_store.getVectorsById(row.id);
|
|
72
|
+
const secs = vecs.map((v) => v.sector);
|
|
73
|
+
const mem = {
|
|
74
|
+
id: row.id,
|
|
75
|
+
node: meta?.lgm
|
|
76
|
+
?.node || row.primary_sector,
|
|
77
|
+
content: row.content,
|
|
78
|
+
primary_sector: row.primary_sector,
|
|
79
|
+
sectors: secs,
|
|
80
|
+
tags,
|
|
81
|
+
created_at: row.created_at,
|
|
82
|
+
updated_at: row.updated_at,
|
|
83
|
+
last_seen_at: row.last_seen_at,
|
|
84
|
+
salience: row.salience,
|
|
85
|
+
decay_lambda: row.decay_lambda,
|
|
86
|
+
version: row.version,
|
|
87
|
+
};
|
|
88
|
+
if (typeof score === "number")
|
|
89
|
+
mem.score = score;
|
|
90
|
+
if (path)
|
|
91
|
+
mem.path = path;
|
|
92
|
+
if (inc_meta)
|
|
93
|
+
mem.metadata = meta;
|
|
94
|
+
return mem;
|
|
95
|
+
};
|
|
96
|
+
const build_refl_content = (p, ns) => {
|
|
97
|
+
const parts = [
|
|
98
|
+
`LangGraph reflection for node "${p.node}"`,
|
|
99
|
+
`namespace=${ns}`,
|
|
100
|
+
];
|
|
101
|
+
if (p.graph_id)
|
|
102
|
+
parts.push(`graph=${p.graph_id}`);
|
|
103
|
+
return `${parts.join(" | ")}\n\n${trunc(p.content, 480)}`;
|
|
104
|
+
};
|
|
105
|
+
const create_auto_refl = async (p, stored) => {
|
|
106
|
+
const refl_tags = build_tags([`lgm:auto:reflection`, `lgm:source:${stored.id}`], "reflect", stored.namespace, stored.graph_id ?? undefined);
|
|
107
|
+
const refl_meta = {
|
|
108
|
+
lgm: {
|
|
109
|
+
node: "reflect",
|
|
110
|
+
sector: "reflective",
|
|
111
|
+
namespace: stored.namespace,
|
|
112
|
+
graph_id: stored.graph_id,
|
|
113
|
+
stored_at: (0, utils_1.now)(),
|
|
114
|
+
mode: "langgraph",
|
|
115
|
+
source_memory: stored.id,
|
|
116
|
+
source_node: p.node.toLowerCase(),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const res = await (0, hsg_1.add_hsg_memory)(build_refl_content(p, stored.namespace), (0, utils_1.j)(refl_tags), refl_meta, p.user_id);
|
|
120
|
+
return {
|
|
121
|
+
id: res.id,
|
|
122
|
+
node: "reflect",
|
|
123
|
+
primary_sector: res.primary_sector,
|
|
124
|
+
sectors: res.sectors,
|
|
125
|
+
namespace: stored.namespace,
|
|
126
|
+
graph_id: stored.graph_id,
|
|
127
|
+
tags: refl_tags,
|
|
128
|
+
chunks: res.chunks ?? 1,
|
|
129
|
+
metadata: refl_meta,
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
async function store_node_mem(p) {
|
|
133
|
+
if (!p?.node || !p?.content)
|
|
134
|
+
throw new Error("node and content are required");
|
|
135
|
+
const ns = resolve_ns(p.namespace);
|
|
136
|
+
const node = p.node.toLowerCase();
|
|
137
|
+
const sec = resolve_sector(node);
|
|
138
|
+
const tag_list = build_tags(p.tags, node, ns, p.graph_id);
|
|
139
|
+
const meta = build_meta(p, sec, ns);
|
|
140
|
+
const res = await (0, hsg_1.add_hsg_memory)(p.content, (0, utils_1.j)(tag_list), meta, p.user_id);
|
|
141
|
+
const stored = {
|
|
142
|
+
id: res.id,
|
|
143
|
+
node,
|
|
144
|
+
primary_sector: res.primary_sector,
|
|
145
|
+
sectors: res.sectors,
|
|
146
|
+
namespace: ns,
|
|
147
|
+
graph_id: p.graph_id ?? null,
|
|
148
|
+
tags: tag_list,
|
|
149
|
+
chunks: res.chunks ?? 1,
|
|
150
|
+
metadata: meta,
|
|
151
|
+
};
|
|
152
|
+
const refl_set = p.reflective ?? cfg_1.env.lg_reflective;
|
|
153
|
+
const refl = refl_set && node !== "reflect"
|
|
154
|
+
? await create_auto_refl(p, stored)
|
|
155
|
+
: null;
|
|
156
|
+
return { memory: stored, reflection: refl };
|
|
157
|
+
}
|
|
158
|
+
async function retrieve_node_mems(p) {
|
|
159
|
+
if (!p?.node)
|
|
160
|
+
throw new Error("node is required");
|
|
161
|
+
const ns = resolve_ns(p.namespace);
|
|
162
|
+
const node = p.node.toLowerCase();
|
|
163
|
+
const sec = resolve_sector(node);
|
|
164
|
+
const lim = p.limit || cfg_1.env.lg_max_context;
|
|
165
|
+
const inc_meta = p.include_metadata ?? false;
|
|
166
|
+
const gid = p.graph_id;
|
|
167
|
+
const items = [];
|
|
168
|
+
if (p.query) {
|
|
169
|
+
const matches = await (0, hsg_1.hsg_query)(p.query, Math.max(lim * 2, lim), {
|
|
170
|
+
sectors: [sec],
|
|
171
|
+
});
|
|
172
|
+
for (const match of matches) {
|
|
173
|
+
const row = (await db_1.q.get_mem.get(match.id));
|
|
174
|
+
if (!row)
|
|
175
|
+
continue;
|
|
176
|
+
const meta = safe_parse(row.meta, {});
|
|
177
|
+
if (!matches_ns(meta, ns, gid))
|
|
178
|
+
continue;
|
|
179
|
+
const hyd = await hydrate_mem_row(row, meta, inc_meta, match.score, match.path);
|
|
180
|
+
items.push(hyd);
|
|
181
|
+
if (items.length >= lim)
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const raw_rows = (await db_1.q.all_mem_by_sector.all(sec, lim * 4, 0));
|
|
187
|
+
for (const row of raw_rows) {
|
|
188
|
+
const meta = safe_parse(row.meta, {});
|
|
189
|
+
if (!matches_ns(meta, ns, gid))
|
|
190
|
+
continue;
|
|
191
|
+
const hyd = await hydrate_mem_row(row, meta, inc_meta);
|
|
192
|
+
items.push(hyd);
|
|
193
|
+
if (items.length >= lim)
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
items.sort((a, b) => b.last_seen_at - a.last_seen_at);
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
node,
|
|
200
|
+
sector: sec,
|
|
201
|
+
namespace: ns,
|
|
202
|
+
graph_id: gid ?? null,
|
|
203
|
+
query: p.query || null,
|
|
204
|
+
count: items.length,
|
|
205
|
+
items,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async function get_graph_ctx(p) {
|
|
209
|
+
const ns = resolve_ns(p.namespace);
|
|
210
|
+
const gid = p.graph_id;
|
|
211
|
+
const lim = p.limit || cfg_1.env.lg_max_context;
|
|
212
|
+
const nodes = Object.keys(exports.node_sector_map);
|
|
213
|
+
const per_node_lim = Math.max(1, Math.floor(lim / nodes.length) || 1);
|
|
214
|
+
const node_ctxs = [];
|
|
215
|
+
for (const node of nodes) {
|
|
216
|
+
const res = await retrieve_node_mems({
|
|
217
|
+
node,
|
|
218
|
+
namespace: ns,
|
|
219
|
+
graph_id: gid,
|
|
220
|
+
limit: per_node_lim,
|
|
221
|
+
include_metadata: true,
|
|
222
|
+
});
|
|
223
|
+
node_ctxs.push({ node, sector: res.sector, items: res.items });
|
|
224
|
+
}
|
|
225
|
+
const flat = node_ctxs.flatMap((e) => e.items.map((i) => ({
|
|
226
|
+
node: e.node,
|
|
227
|
+
content: trunc(i.content, summary_line_limit),
|
|
228
|
+
})));
|
|
229
|
+
const summ = flat.length
|
|
230
|
+
? flat
|
|
231
|
+
.slice(0, lim)
|
|
232
|
+
.map((ln) => `- [${ln.node}] ${ln.content}`)
|
|
233
|
+
.join("\n")
|
|
234
|
+
: "";
|
|
235
|
+
return {
|
|
236
|
+
namespace: ns,
|
|
237
|
+
graph_id: gid ?? null,
|
|
238
|
+
limit: lim,
|
|
239
|
+
nodes: node_ctxs,
|
|
240
|
+
summary: summ,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const build_ctx_refl = async (ns, gid) => {
|
|
244
|
+
const ctx = await get_graph_ctx({
|
|
245
|
+
namespace: ns,
|
|
246
|
+
graph_id: gid,
|
|
247
|
+
limit: cfg_1.env.lg_max_context,
|
|
248
|
+
});
|
|
249
|
+
const lns = ctx.nodes.flatMap((e) => e.items.map((i) => ({
|
|
250
|
+
node: e.node,
|
|
251
|
+
content: trunc(i.content, summary_line_limit),
|
|
252
|
+
})));
|
|
253
|
+
if (!lns.length)
|
|
254
|
+
return null;
|
|
255
|
+
const hdr = `Reflection synthesized from LangGraph context (namespace=${ns}${gid ? `, graph=${gid}` : ""})`;
|
|
256
|
+
const body = lns
|
|
257
|
+
.slice(0, cfg_1.env.lg_max_context)
|
|
258
|
+
.map((ln, idx) => `${idx + 1}. [${ln.node}] ${ln.content}`)
|
|
259
|
+
.join("\n");
|
|
260
|
+
return `${hdr}\n\n${body}`;
|
|
261
|
+
};
|
|
262
|
+
async function create_refl(p) {
|
|
263
|
+
const ns = resolve_ns(p.namespace);
|
|
264
|
+
const node = (p.node || "reflect").toLowerCase();
|
|
265
|
+
const base_content = p.content || (await build_ctx_refl(ns, p.graph_id));
|
|
266
|
+
if (!base_content)
|
|
267
|
+
throw new Error("reflection content could not be derived");
|
|
268
|
+
const tags = [
|
|
269
|
+
`lgm:manual:reflection`,
|
|
270
|
+
...(p.context_ids?.map((id) => `lgm:context:${id}`) || []),
|
|
271
|
+
];
|
|
272
|
+
const meta = {
|
|
273
|
+
lgm_context_ids: p.context_ids || [],
|
|
274
|
+
};
|
|
275
|
+
const res = await store_node_mem({
|
|
276
|
+
node,
|
|
277
|
+
content: base_content,
|
|
278
|
+
namespace: ns,
|
|
279
|
+
graph_id: p.graph_id,
|
|
280
|
+
tags,
|
|
281
|
+
metadata: meta,
|
|
282
|
+
reflective: false,
|
|
283
|
+
});
|
|
284
|
+
return res;
|
|
285
|
+
}
|
|
286
|
+
const get_lg_cfg = () => ({
|
|
287
|
+
mode: cfg_1.env.mode,
|
|
288
|
+
namespace_default: cfg_1.env.lg_namespace,
|
|
289
|
+
max_context: cfg_1.env.lg_max_context,
|
|
290
|
+
reflective: cfg_1.env.lg_reflective,
|
|
291
|
+
node_sector_map: exports.node_sector_map,
|
|
292
|
+
});
|
|
293
|
+
exports.get_lg_cfg = get_lg_cfg;
|