agim-cli 1.1.11 → 1.2.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/dist/cli.js +78 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/core/approval-bus.d.ts +18 -0
  5. package/dist/core/approval-bus.d.ts.map +1 -1
  6. package/dist/core/approval-bus.js +111 -0
  7. package/dist/core/approval-bus.js.map +1 -1
  8. package/dist/core/approval-router.d.ts.map +1 -1
  9. package/dist/core/approval-router.js +12 -0
  10. package/dist/core/approval-router.js.map +1 -1
  11. package/dist/core/audit-log.d.ts +39 -0
  12. package/dist/core/audit-log.d.ts.map +1 -1
  13. package/dist/core/audit-log.js +124 -0
  14. package/dist/core/audit-log.js.map +1 -1
  15. package/dist/core/boot-state.d.ts +17 -0
  16. package/dist/core/boot-state.d.ts.map +1 -0
  17. package/dist/core/boot-state.js +77 -0
  18. package/dist/core/boot-state.js.map +1 -0
  19. package/dist/core/job-recovery.d.ts +41 -1
  20. package/dist/core/job-recovery.d.ts.map +1 -1
  21. package/dist/core/job-recovery.js +216 -4
  22. package/dist/core/job-recovery.js.map +1 -1
  23. package/dist/core/memory-consolidate.d.ts +12 -0
  24. package/dist/core/memory-consolidate.d.ts.map +1 -0
  25. package/dist/core/memory-consolidate.js +242 -0
  26. package/dist/core/memory-consolidate.js.map +1 -0
  27. package/dist/core/memory-distill.d.ts +30 -0
  28. package/dist/core/memory-distill.d.ts.map +1 -0
  29. package/dist/core/memory-distill.js +213 -0
  30. package/dist/core/memory-distill.js.map +1 -0
  31. package/dist/core/memory-rpc.d.ts +11 -0
  32. package/dist/core/memory-rpc.d.ts.map +1 -0
  33. package/dist/core/memory-rpc.js +94 -0
  34. package/dist/core/memory-rpc.js.map +1 -0
  35. package/dist/core/memory-vector.d.ts +47 -0
  36. package/dist/core/memory-vector.d.ts.map +1 -0
  37. package/dist/core/memory-vector.js +386 -0
  38. package/dist/core/memory-vector.js.map +1 -0
  39. package/dist/core/memory.d.ts +140 -0
  40. package/dist/core/memory.d.ts.map +1 -0
  41. package/dist/core/memory.js +714 -0
  42. package/dist/core/memory.js.map +1 -0
  43. package/dist/core/persona.d.ts +24 -0
  44. package/dist/core/persona.d.ts.map +1 -0
  45. package/dist/core/persona.js +80 -0
  46. package/dist/core/persona.js.map +1 -0
  47. package/dist/core/push-rpc.d.ts +26 -0
  48. package/dist/core/push-rpc.d.ts.map +1 -0
  49. package/dist/core/push-rpc.js +123 -0
  50. package/dist/core/push-rpc.js.map +1 -0
  51. package/dist/core/router.d.ts.map +1 -1
  52. package/dist/core/router.js +26 -1
  53. package/dist/core/router.js.map +1 -1
  54. package/dist/core/types.d.ts +41 -0
  55. package/dist/core/types.d.ts.map +1 -1
  56. package/dist/plugins/agents/claude-code/index.d.ts +9 -0
  57. package/dist/plugins/agents/claude-code/index.d.ts.map +1 -1
  58. package/dist/plugins/agents/claude-code/index.js +37 -0
  59. package/dist/plugins/agents/claude-code/index.js.map +1 -1
  60. package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts +8 -0
  61. package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts.map +1 -1
  62. package/dist/plugins/agents/claude-code/mcp-approval-server.js +181 -0
  63. package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -1
  64. package/dist/plugins/messengers/telegram/telegram-adapter.d.ts +5 -1
  65. package/dist/plugins/messengers/telegram/telegram-adapter.d.ts.map +1 -1
  66. package/dist/plugins/messengers/telegram/telegram-adapter.js +85 -0
  67. package/dist/plugins/messengers/telegram/telegram-adapter.js.map +1 -1
  68. package/dist/web/public/settings.html +106 -10
  69. package/dist/web/public/tasks.html +992 -1
  70. package/dist/web/server.d.ts.map +1 -1
  71. package/dist/web/server.js +433 -6
  72. package/dist/web/server.js.map +1 -1
  73. package/package.json +4 -1
@@ -0,0 +1,47 @@
1
+ export type BackendName = 'off' | 'local' | 'openai';
2
+ export interface EmbeddingBackend {
3
+ readonly name: BackendName;
4
+ readonly ready: boolean;
5
+ readonly dims: number;
6
+ readonly modelId: string;
7
+ /** Generate embeddings for a batch of texts. Returns same-length array. */
8
+ embed(texts: string[]): Promise<Float32Array[]>;
9
+ /** Describe current state for the status endpoint. */
10
+ describe(): BackendStatus;
11
+ }
12
+ export interface BackendStatus {
13
+ backend: BackendName;
14
+ ready: boolean;
15
+ dims: number;
16
+ modelId: string;
17
+ lastError: string | null;
18
+ /** Local-only: model files present on disk. ready may still be false if
19
+ * the in-process pipeline hasn't loaded them yet (post-restart warmup). */
20
+ downloaded?: boolean;
21
+ /** Backend-specific extra info (model file size, baseUrl, etc.) */
22
+ detail: Record<string, unknown>;
23
+ }
24
+ export declare function getActiveBackend(): EmbeddingBackend;
25
+ /** Reset all backend singletons. Used by tests + when env changes via /api/env. */
26
+ export declare function _resetVectorBackendsForTests(): void;
27
+ export declare function getHybridWeight(): number;
28
+ export declare function getBatchSize(): number;
29
+ /** Triggers local-backend download. No-op for off / openai. */
30
+ export declare function triggerLocalDownload(): Promise<{
31
+ ok: boolean;
32
+ error?: string;
33
+ }>;
34
+ /** Calls test() for openai; ensureReady() for local. */
35
+ export declare function testActiveBackend(): Promise<{
36
+ ok: boolean;
37
+ dims?: number;
38
+ latencyMs?: number;
39
+ error?: string;
40
+ }>;
41
+ /** Float32Array <-> Buffer round-trip helpers for SQLite BLOB columns. */
42
+ export declare function float32ToBuffer(arr: Float32Array): Buffer;
43
+ export declare function bufferToFloat32(buf: Buffer): Float32Array;
44
+ /** Cosine similarity for two normalized (unit-length) Float32Arrays.
45
+ * All our backends normalize by default; this is just a dot product. */
46
+ export declare function cosineSim(a: Float32Array, b: Float32Array): number;
47
+ //# sourceMappingURL=memory-vector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-vector.d.ts","sourceRoot":"","sources":["../../src/core/memory-vector.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,2EAA2E;IAC3E,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC/C,sDAAsD;IACtD,QAAQ,IAAI,aAAa,CAAA;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB,KAAK,EAAE,OAAO,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;gFAC4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAgSD,wBAAgB,gBAAgB,IAAI,gBAAgB,CAqBnD;AAED,mFAAmF;AACnF,wBAAgB,4BAA4B,IAAI,IAAI,CAGnD;AAED,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAIrC;AAID,+DAA+D;AAC/D,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CASrF;AAED,wDAAwD;AACxD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAerH;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAEzD;AACD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAOzD;AAED;yEACyE;AACzE,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAKlE"}
@@ -0,0 +1,386 @@
1
+ // memory-vector — embedding backend abstraction for the long-term memory
2
+ // hybrid retrieval pipeline.
3
+ //
4
+ // Three backends, all behind one tiny interface:
5
+ //
6
+ // OffBackend — default. `ready=false`, every call no-ops. Zero
7
+ // import cost; @xenova/transformers stays unloaded.
8
+ // LocalBgeBackend — lazy-loads @xenova/transformers + a Hugging Face
9
+ // model (default Xenova/bge-base-zh-v1.5). First use
10
+ // triggers a ~250MB CDN download; afterwards stays in
11
+ // memory + CPU inference (~50ms/batch).
12
+ // OpenAIBackend — POSTs to {baseUrl}/embeddings; compatible with any
13
+ // OpenAI-format service (Azure, Ollama, 智谱, etc).
14
+ // All requests wrapped in AbortSignal.timeout to never
15
+ // block the page when the network is bad.
16
+ //
17
+ // The active backend is selected by IMHUB_MEMORY_VECTOR_BACKEND
18
+ // (off | local | openai). Status / download / test endpoints in
19
+ // web/server.ts read from `getActiveBackend()` to drive the UI.
20
+ import { existsSync } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { logger as rootLogger } from './logger.js';
23
+ import { AGIM_HOME } from './agim-paths.js';
24
+ const log = rootLogger.child({ component: 'memory-vector' });
25
+ const HTTP_TIMEOUT_MS = 10_000;
26
+ const BATCH_TIMEOUT_MS = 30_000;
27
+ // ─── OffBackend ──────────────────────────────────────────────────────
28
+ class OffBackend {
29
+ name = 'off';
30
+ ready = false;
31
+ dims = 0;
32
+ modelId = '';
33
+ async embed() { return []; }
34
+ describe() {
35
+ return {
36
+ backend: 'off', ready: false, dims: 0, modelId: '',
37
+ lastError: null,
38
+ detail: { hint: 'set IMHUB_MEMORY_VECTOR_BACKEND=local|openai to enable' },
39
+ };
40
+ }
41
+ }
42
+ class LocalBgeBackend {
43
+ name = 'local';
44
+ modelId;
45
+ dims = 0;
46
+ // populated after first successful pipeline load
47
+ extractor = null;
48
+ loadPromise = null;
49
+ lastError = null;
50
+ // Per-process download progress (UI polls /api/memory/vector/status).
51
+ progress = {
52
+ phase: 'idle', filesDone: 0, filesTotal: 0, bytesDone: 0, bytesTotal: 0,
53
+ startedAt: null, finishedAt: null, error: null,
54
+ };
55
+ constructor(modelId) {
56
+ this.modelId = modelId;
57
+ // Auto-warm: if the model is already on disk from a previous run,
58
+ // load it in the background so `ready` flips to true within seconds.
59
+ // Without this, the backend stays "not ready" after every restart
60
+ // until the user clicks 📥 download / 🧪 test, AND saveFact silently
61
+ // skips embedding writes in the meantime.
62
+ if (this.isDownloaded()) {
63
+ void this.ensureReady().catch((err) => {
64
+ log.warn({
65
+ event: 'vector.local.autowarm_failed', modelId: this.modelId,
66
+ err: err instanceof Error ? err.message : String(err),
67
+ });
68
+ });
69
+ }
70
+ }
71
+ /** Cheap check: are model files on disk? Used to flip the UI's
72
+ * "downloaded but loading" hint and to gate auto-warm. */
73
+ isDownloaded() {
74
+ try {
75
+ const onnx = join(AGIM_HOME, 'cache', 'transformers', this.modelId, 'onnx', 'model_quantized.onnx');
76
+ return existsSync(onnx);
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
82
+ get ready() {
83
+ return this.extractor !== null && this.dims > 0;
84
+ }
85
+ /**
86
+ * Idempotent: returns the same promise on concurrent calls. Triggers the
87
+ * @xenova/transformers dynamic import + model download (CDN) + pipeline
88
+ * load. UI calls /api/memory/vector/download which calls this with
89
+ * forceDownload=true on the very first run.
90
+ */
91
+ async ensureReady() {
92
+ if (this.ready)
93
+ return;
94
+ if (this.loadPromise)
95
+ return this.loadPromise;
96
+ this.loadPromise = this._load().catch((err) => {
97
+ this.lastError = err instanceof Error ? err.message : String(err);
98
+ this.progress.phase = 'failed';
99
+ this.progress.error = this.lastError;
100
+ this.progress.finishedAt = Date.now();
101
+ // Reset so a follow-up download attempt can retry.
102
+ this.loadPromise = null;
103
+ throw err;
104
+ });
105
+ return this.loadPromise;
106
+ }
107
+ async _load() {
108
+ log.info({ event: 'vector.local.load_start', modelId: this.modelId });
109
+ this.progress.phase = 'downloading';
110
+ this.progress.startedAt = Date.now();
111
+ this.progress.error = null;
112
+ // Dynamic import so the runtime cost is only paid when the backend is on.
113
+ // @xenova/transformers is in optionalDependencies (skipped on CI install
114
+ // to avoid a large ONNX postinstall hang); ts-ignore needed so tsc
115
+ // doesn't error when the module isn't on disk at build time.
116
+ // @ts-ignore -- optional dep, may not be installed at build time
117
+ const tf = await import('@xenova/transformers');
118
+ // Cache to ~/.agim/cache/transformers so we don't sprinkle files all
119
+ // over $HOME. allowLocalModels stays default (true) — cached models
120
+ // load offline after first download.
121
+ try {
122
+ tf.env.cacheDir = join(AGIM_HOME, 'cache', 'transformers');
123
+ }
124
+ catch (e) {
125
+ log.debug({ event: 'vector.local.cachedir_set_failed', err: String(e) });
126
+ }
127
+ // progress_callback fires for each file: { status, name, file, loaded, total, progress }
128
+ const progressCallback = (info) => {
129
+ try {
130
+ if (info.status === 'progress') {
131
+ this.progress.bytesTotal = Math.max(this.progress.bytesTotal, Number(info.total) || 0);
132
+ this.progress.bytesDone = Number(info.loaded) || this.progress.bytesDone;
133
+ }
134
+ else if (info.status === 'done') {
135
+ this.progress.filesDone += 1;
136
+ }
137
+ else if (info.status === 'initiate') {
138
+ this.progress.filesTotal += 1;
139
+ }
140
+ }
141
+ catch { /* noop */ }
142
+ };
143
+ const extractor = await tf.pipeline('feature-extraction', this.modelId, {
144
+ quantized: true,
145
+ progress_callback: progressCallback,
146
+ });
147
+ // Probe dims with a 1-char input.
148
+ const probeOutput = await extractor('hi', { pooling: 'mean', normalize: true });
149
+ const data = probeOutput.data;
150
+ if (!data || data.length === 0)
151
+ throw new Error('embedding model returned empty output');
152
+ this.dims = data.length;
153
+ this.extractor = extractor;
154
+ this.progress.phase = 'ready';
155
+ this.progress.finishedAt = Date.now();
156
+ log.info({ event: 'vector.local.ready', dims: this.dims, modelId: this.modelId });
157
+ }
158
+ async embed(texts) {
159
+ if (!this.ready) {
160
+ // Don't auto-trigger download from embed() — user has to opt in via
161
+ // /api/memory/vector/download. Silent no-op keeps writes fast.
162
+ return texts.map(() => new Float32Array(0));
163
+ }
164
+ const out = [];
165
+ for (const t of texts) {
166
+ const trimmed = t.length > 4000 ? t.slice(0, 4000) : t;
167
+ const result = await this.extractor(trimmed, { pooling: 'mean', normalize: true });
168
+ out.push(new Float32Array(result.data));
169
+ }
170
+ return out;
171
+ }
172
+ getProgress() { return { ...this.progress }; }
173
+ describe() {
174
+ return {
175
+ backend: 'local', ready: this.ready, dims: this.dims,
176
+ modelId: this.modelId,
177
+ lastError: this.lastError,
178
+ downloaded: this.isDownloaded(),
179
+ detail: { progress: this.getProgress() },
180
+ };
181
+ }
182
+ }
183
+ // ─── OpenAIBackend ───────────────────────────────────────────────────
184
+ class OpenAIBackend {
185
+ name = 'openai';
186
+ modelId;
187
+ baseUrl;
188
+ apiKey;
189
+ dims = 0; // probed on first successful embed; 0 until then
190
+ ready = false; // becomes true after first successful embed (key + URL work)
191
+ lastError = null;
192
+ constructor(baseUrl, modelId, apiKey) {
193
+ this.baseUrl = baseUrl.replace(/\/$/, '');
194
+ this.modelId = modelId;
195
+ this.apiKey = apiKey;
196
+ }
197
+ async embed(texts) {
198
+ if (!this.apiKey) {
199
+ this.lastError = 'API key not configured';
200
+ return texts.map(() => new Float32Array(0));
201
+ }
202
+ if (texts.length === 0)
203
+ return [];
204
+ try {
205
+ const ctrl = new AbortController();
206
+ const t = setTimeout(() => ctrl.abort(), BATCH_TIMEOUT_MS);
207
+ const res = await fetch(`${this.baseUrl}/embeddings`, {
208
+ method: 'POST',
209
+ headers: {
210
+ 'Content-Type': 'application/json',
211
+ 'Authorization': `Bearer ${this.apiKey}`,
212
+ },
213
+ body: JSON.stringify({ model: this.modelId, input: texts }),
214
+ signal: ctrl.signal,
215
+ }).finally(() => clearTimeout(t));
216
+ if (!res.ok) {
217
+ const body = await res.text().catch(() => '');
218
+ throw new Error(`HTTP ${res.status}: ${body.slice(0, 200)}`);
219
+ }
220
+ const json = await res.json();
221
+ if (!Array.isArray(json.data))
222
+ throw new Error('response missing data[]');
223
+ const out = json.data.map((d) => new Float32Array(d.embedding));
224
+ if (out.length > 0 && out[0].length > 0) {
225
+ this.dims = out[0].length;
226
+ this.ready = true;
227
+ this.lastError = null;
228
+ }
229
+ return out;
230
+ }
231
+ catch (err) {
232
+ this.lastError = err instanceof Error ? err.message : String(err);
233
+ this.ready = false;
234
+ log.warn({ event: 'vector.openai.embed_failed', err: this.lastError });
235
+ return texts.map(() => new Float32Array(0));
236
+ }
237
+ }
238
+ /** Lightweight probe used by /api/memory/vector/test. */
239
+ async test() {
240
+ const start = Date.now();
241
+ try {
242
+ const ctrl = new AbortController();
243
+ const t = setTimeout(() => ctrl.abort(), HTTP_TIMEOUT_MS);
244
+ const res = await fetch(`${this.baseUrl}/embeddings`, {
245
+ method: 'POST',
246
+ headers: {
247
+ 'Content-Type': 'application/json',
248
+ 'Authorization': `Bearer ${this.apiKey}`,
249
+ },
250
+ body: JSON.stringify({ model: this.modelId, input: ['ping'] }),
251
+ signal: ctrl.signal,
252
+ }).finally(() => clearTimeout(t));
253
+ const latencyMs = Date.now() - start;
254
+ if (!res.ok) {
255
+ const body = await res.text().catch(() => '');
256
+ return { ok: false, error: `HTTP ${res.status}: ${body.slice(0, 200)}`, latencyMs };
257
+ }
258
+ const json = await res.json();
259
+ const emb = json.data?.[0]?.embedding;
260
+ if (!Array.isArray(emb))
261
+ return { ok: false, error: 'response missing embedding', latencyMs };
262
+ this.dims = emb.length;
263
+ this.ready = true;
264
+ this.lastError = null;
265
+ return { ok: true, dims: emb.length, latencyMs };
266
+ }
267
+ catch (err) {
268
+ const msg = err instanceof Error ? err.message : String(err);
269
+ const isTimeout = /aborted|timeout/i.test(msg);
270
+ return { ok: false, error: isTimeout ? `timed out after ${HTTP_TIMEOUT_MS}ms` : msg, latencyMs: Date.now() - start };
271
+ }
272
+ }
273
+ describe() {
274
+ return {
275
+ backend: 'openai', ready: this.ready, dims: this.dims,
276
+ modelId: this.modelId, lastError: this.lastError,
277
+ detail: { baseUrl: this.baseUrl, hasKey: !!this.apiKey },
278
+ };
279
+ }
280
+ }
281
+ // ─── factory + singletons ────────────────────────────────────────────
282
+ const off = new OffBackend();
283
+ let localSingleton = null;
284
+ let openaiSingleton = null;
285
+ function readBackendName() {
286
+ const v = (process.env.IMHUB_MEMORY_VECTOR_BACKEND || 'off').toLowerCase();
287
+ return v === 'local' || v === 'openai' ? v : 'off';
288
+ }
289
+ export function getActiveBackend() {
290
+ const which = readBackendName();
291
+ if (which === 'off')
292
+ return off;
293
+ if (which === 'local') {
294
+ const modelId = process.env.IMHUB_MEMORY_VECTOR_LOCAL_MODEL || 'Xenova/bge-base-zh-v1.5';
295
+ if (!localSingleton || localSingleton.modelId !== modelId) {
296
+ localSingleton = new LocalBgeBackend(modelId);
297
+ }
298
+ return localSingleton;
299
+ }
300
+ // openai
301
+ const baseUrl = process.env.IMHUB_MEMORY_VECTOR_OPENAI_BASE_URL || 'https://api.openai.com/v1';
302
+ const modelId = process.env.IMHUB_MEMORY_VECTOR_OPENAI_MODEL || 'text-embedding-3-small';
303
+ const apiKey = process.env.IMHUB_MEMORY_VECTOR_OPENAI_API_KEY || '';
304
+ if (!openaiSingleton
305
+ || openaiSingleton.baseUrl !== baseUrl.replace(/\/$/, '')
306
+ || openaiSingleton.modelId !== modelId
307
+ || openaiSingleton.apiKey !== apiKey) {
308
+ openaiSingleton = new OpenAIBackend(baseUrl, modelId, apiKey);
309
+ }
310
+ return openaiSingleton;
311
+ }
312
+ /** Reset all backend singletons. Used by tests + when env changes via /api/env. */
313
+ export function _resetVectorBackendsForTests() {
314
+ localSingleton = null;
315
+ openaiSingleton = null;
316
+ }
317
+ export function getHybridWeight() {
318
+ const raw = parseFloat(process.env.IMHUB_MEMORY_VECTOR_HYBRID_WEIGHT || '0.5');
319
+ if (!Number.isFinite(raw))
320
+ return 0.5;
321
+ return Math.max(0, Math.min(1, raw));
322
+ }
323
+ export function getBatchSize() {
324
+ const raw = parseInt(process.env.IMHUB_MEMORY_VECTOR_BATCH_SIZE || '32', 10);
325
+ if (!Number.isFinite(raw) || raw < 1)
326
+ return 32;
327
+ return Math.min(raw, 128);
328
+ }
329
+ // ─── helpers exposed for memory.ts + endpoints ───────────────────────
330
+ /** Triggers local-backend download. No-op for off / openai. */
331
+ export async function triggerLocalDownload() {
332
+ const b = getActiveBackend();
333
+ if (b.name !== 'local')
334
+ return { ok: false, error: `backend is ${b.name}, not local` };
335
+ try {
336
+ await b.ensureReady();
337
+ return { ok: true };
338
+ }
339
+ catch (err) {
340
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
341
+ }
342
+ }
343
+ /** Calls test() for openai; ensureReady() for local. */
344
+ export async function testActiveBackend() {
345
+ const b = getActiveBackend();
346
+ if (b.name === 'off')
347
+ return { ok: false, error: 'backend is off' };
348
+ if (b.name === 'openai')
349
+ return b.test();
350
+ // local
351
+ try {
352
+ const start = Date.now();
353
+ await b.ensureReady();
354
+ const vec = await b.embed(['ping']);
355
+ const latencyMs = Date.now() - start;
356
+ if (vec[0]?.length > 0)
357
+ return { ok: true, dims: vec[0].length, latencyMs };
358
+ return { ok: false, error: 'embed returned empty vector', latencyMs };
359
+ }
360
+ catch (err) {
361
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
362
+ }
363
+ }
364
+ /** Float32Array <-> Buffer round-trip helpers for SQLite BLOB columns. */
365
+ export function float32ToBuffer(arr) {
366
+ return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);
367
+ }
368
+ export function bufferToFloat32(buf) {
369
+ // Float32Array requires the underlying ArrayBuffer offset to be 4-byte
370
+ // aligned. better-sqlite3 returns BLOBs from a shared pool with arbitrary
371
+ // byteOffset, so we copy into a fresh ArrayBuffer first.
372
+ const copy = new ArrayBuffer(buf.byteLength);
373
+ new Uint8Array(copy).set(buf);
374
+ return new Float32Array(copy);
375
+ }
376
+ /** Cosine similarity for two normalized (unit-length) Float32Arrays.
377
+ * All our backends normalize by default; this is just a dot product. */
378
+ export function cosineSim(a, b) {
379
+ if (a.length !== b.length || a.length === 0)
380
+ return 0;
381
+ let s = 0;
382
+ for (let i = 0; i < a.length; i++)
383
+ s += a[i] * b[i];
384
+ return s;
385
+ }
386
+ //# sourceMappingURL=memory-vector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-vector.js","sourceRoot":"","sources":["../../src/core/memory-vector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ export type FactCategory = 'fact' | 'preference' | 'goal' | 'history' | 'profile';
2
+ export interface Fact {
3
+ id: number;
4
+ user_key: string;
5
+ what: string;
6
+ who: string;
7
+ when_text: string;
8
+ where_label: string;
9
+ why: string;
10
+ category: FactCategory;
11
+ confidence: number;
12
+ last_referenced_at: number;
13
+ source: string;
14
+ created_at: number;
15
+ }
16
+ export interface SaveFactInput {
17
+ user_key: string;
18
+ what: string;
19
+ who?: string;
20
+ when_text?: string;
21
+ where_label?: string;
22
+ why?: string;
23
+ category?: FactCategory;
24
+ confidence?: number;
25
+ source?: string;
26
+ }
27
+ export declare function userKey(platform: string, userId: string): string;
28
+ export declare function saveFact(input: SaveFactInput): number | null;
29
+ export declare function deleteFact(id: number, user_key: string): boolean;
30
+ export interface QueryOpts {
31
+ user_key: string;
32
+ query?: string;
33
+ category?: FactCategory;
34
+ k?: number;
35
+ }
36
+ export interface QueryResult {
37
+ facts: Fact[];
38
+ matched: number;
39
+ }
40
+ /**
41
+ * Hybrid retrieval. v1.5 first cut uses FTS5 + recency boost; v1.6 will
42
+ * layer in sqlite-vss dense vectors and rerank.
43
+ *
44
+ * - Empty query → most-recent N facts.
45
+ * - With query → FTS5 MATCH, sorted by FTS5's bm25() with a recency tie-
46
+ * breaker (newer first).
47
+ *
48
+ * Side effect: bumps `last_referenced_at` for returned rows so weak /
49
+ * unused facts can be retired by future consolidation.
50
+ */
51
+ export declare function queryFacts(opts: QueryOpts): QueryResult;
52
+ /**
53
+ * v1.6 — async hybrid retrieval. When a vector backend is ready, run FTS5
54
+ * + vector top-K in parallel, fuse with reciprocal-rank-fusion, and return
55
+ * the merged top-K. Falls back to plain queryFacts when backend is off or
56
+ * the embedding model isn't loaded.
57
+ *
58
+ * Use this from memory-rpc.handleMemoryOp('query') so MCP callers get
59
+ * better recall automatically without changing the call site.
60
+ */
61
+ export declare function queryFactsHybrid(opts: QueryOpts): Promise<QueryResult>;
62
+ /** v1.6 — backfill embeddings for facts that don't have one (e.g. existed
63
+ * before vector backend was enabled). Returns counts; safe to call again.
64
+ * Stops early on backend errors (returns partial). */
65
+ export declare function backfillEmbeddings(opts: {
66
+ user_key?: string;
67
+ batchSize?: number;
68
+ maxRows?: number;
69
+ }): Promise<{
70
+ processed: number;
71
+ succeeded: number;
72
+ failed: number;
73
+ errored?: string;
74
+ }>;
75
+ export interface VectorCoverage {
76
+ total: number;
77
+ withEmbedding: number;
78
+ withDifferentModel: number;
79
+ }
80
+ export declare function getVectorCoverage(user_key?: string): VectorCoverage;
81
+ /** Clear all embedding fields for a user (or all). Useful when switching
82
+ * backends — embeddings from different models can't be compared. */
83
+ export declare function clearEmbeddings(user_key?: string): number;
84
+ export declare function listRecentFacts(user_key: string, limit?: number): Fact[];
85
+ export declare function countFacts(user_key: string): number;
86
+ export interface PersonaProfile {
87
+ user_key: string;
88
+ summary: string;
89
+ updated_at: number;
90
+ }
91
+ export declare function getPersona(user_key: string): PersonaProfile | null;
92
+ export declare function upsertPersona(user_key: string, summary: string): boolean;
93
+ export interface UserSummary {
94
+ user_key: string;
95
+ fact_count: number;
96
+ oldest_fact_at: number | null;
97
+ newest_fact_at: number | null;
98
+ has_persona: boolean;
99
+ persona_updated_at: number | null;
100
+ }
101
+ /** Enumerate every user_key the memory system has touched, with quick stats.
102
+ * Used by /api/memory/users to populate the admin selector. */
103
+ export declare function listUsers(): UserSummary[];
104
+ export interface FactPage {
105
+ total: number;
106
+ limit: number;
107
+ offset: number;
108
+ facts: Fact[];
109
+ }
110
+ /** Paged fact listing with optional filters. Mirrors queryFacts but adds
111
+ * offset + total count for table pagination. */
112
+ export declare function listFacts(opts: {
113
+ user_key: string;
114
+ query?: string;
115
+ category?: FactCategory;
116
+ limit?: number;
117
+ offset?: number;
118
+ }): FactPage;
119
+ /** Bulk delete by user + optional filters. Returns row count actually deleted.
120
+ * Defaults are intentionally inert ({user_key} alone deletes ALL facts for
121
+ * that user) — caller must explicitly opt in to clear-all by passing
122
+ * confirm_clear: true. Otherwise needs at least one filter. */
123
+ export declare function bulkDeleteFacts(opts: {
124
+ user_key: string;
125
+ ids?: number[];
126
+ category?: FactCategory;
127
+ max_confidence?: number;
128
+ confirm_clear?: boolean;
129
+ }): number;
130
+ export declare function deletePersona(user_key: string): boolean;
131
+ /** Full export: persona + all facts for one user, JSON-safe shape. */
132
+ export declare function exportUserMemory(user_key: string): {
133
+ user_key: string;
134
+ persona: PersonaProfile | null;
135
+ facts: Fact[];
136
+ exported_at: string;
137
+ };
138
+ export declare function closeMemoryDb(): void;
139
+ export declare const MEMORY_DB_PATH: string;
140
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/core/memory.ts"],"names":[],"mappings":"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"}