agent-working-memory 0.16.1 → 0.18.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 (170) hide show
  1. package/README.md +321 -318
  2. package/dist/adapters/common.d.ts +34 -0
  3. package/dist/adapters/common.d.ts.map +1 -1
  4. package/dist/adapters/common.js +528 -444
  5. package/dist/adapters/common.js.map +1 -1
  6. package/dist/api/routes.d.ts.map +1 -1
  7. package/dist/api/routes.js +19 -0
  8. package/dist/api/routes.js.map +1 -1
  9. package/dist/cli/migrate.d.ts.map +1 -1
  10. package/dist/cli/migrate.js +31 -29
  11. package/dist/cli/migrate.js.map +1 -1
  12. package/dist/core/asked-value.d.ts +37 -0
  13. package/dist/core/asked-value.d.ts.map +1 -0
  14. package/dist/core/asked-value.js +77 -0
  15. package/dist/core/asked-value.js.map +1 -0
  16. package/dist/core/conflicts.d.ts +89 -0
  17. package/dist/core/conflicts.d.ts.map +1 -0
  18. package/dist/core/conflicts.js +267 -0
  19. package/dist/core/conflicts.js.map +1 -0
  20. package/dist/core/embeddings.d.ts +14 -2
  21. package/dist/core/embeddings.d.ts.map +1 -1
  22. package/dist/core/embeddings.js +32 -10
  23. package/dist/core/embeddings.js.map +1 -1
  24. package/dist/core/format-recall.d.ts +21 -1
  25. package/dist/core/format-recall.d.ts.map +1 -1
  26. package/dist/core/format-recall.js +60 -5
  27. package/dist/core/format-recall.js.map +1 -1
  28. package/dist/core/ml-worker.d.ts +24 -1
  29. package/dist/core/ml-worker.d.ts.map +1 -1
  30. package/dist/core/ml-worker.js +165 -4
  31. package/dist/core/ml-worker.js.map +1 -1
  32. package/dist/core/model-daemon-client.d.ts +77 -0
  33. package/dist/core/model-daemon-client.d.ts.map +1 -0
  34. package/dist/core/model-daemon-client.js +383 -0
  35. package/dist/core/model-daemon-client.js.map +1 -0
  36. package/dist/core/model-daemon-server.d.ts +71 -0
  37. package/dist/core/model-daemon-server.d.ts.map +1 -0
  38. package/dist/core/model-daemon-server.js +363 -0
  39. package/dist/core/model-daemon-server.js.map +1 -0
  40. package/dist/core/model-daemon.d.ts +137 -0
  41. package/dist/core/model-daemon.d.ts.map +1 -0
  42. package/dist/core/model-daemon.js +231 -0
  43. package/dist/core/model-daemon.js.map +1 -0
  44. package/dist/core/query-expander.d.ts +5 -0
  45. package/dist/core/query-expander.d.ts.map +1 -1
  46. package/dist/core/query-expander.js +3 -2
  47. package/dist/core/query-expander.js.map +1 -1
  48. package/dist/core/recall-config.d.ts +1 -1
  49. package/dist/core/recall-config.d.ts.map +1 -1
  50. package/dist/core/recall-config.js +5 -0
  51. package/dist/core/recall-config.js.map +1 -1
  52. package/dist/core/rerank-window.d.ts +7 -2
  53. package/dist/core/rerank-window.d.ts.map +1 -1
  54. package/dist/core/rerank-window.js +9 -4
  55. package/dist/core/rerank-window.js.map +1 -1
  56. package/dist/core/rerank2.d.ts +52 -2
  57. package/dist/core/rerank2.d.ts.map +1 -1
  58. package/dist/core/rerank2.js +60 -3
  59. package/dist/core/rerank2.js.map +1 -1
  60. package/dist/core/reranker.d.ts +19 -0
  61. package/dist/core/reranker.d.ts.map +1 -1
  62. package/dist/core/reranker.js +76 -12
  63. package/dist/core/reranker.js.map +1 -1
  64. package/dist/core/salience.d.ts +2 -0
  65. package/dist/core/salience.d.ts.map +1 -1
  66. package/dist/core/salience.js +45 -18
  67. package/dist/core/salience.js.map +1 -1
  68. package/dist/core/trust.d.ts +32 -0
  69. package/dist/core/trust.d.ts.map +1 -0
  70. package/dist/core/trust.js +66 -0
  71. package/dist/core/trust.js.map +1 -0
  72. package/dist/core/validity.d.ts +21 -0
  73. package/dist/core/validity.d.ts.map +1 -0
  74. package/dist/core/validity.js +41 -0
  75. package/dist/core/validity.js.map +1 -0
  76. package/dist/core/whoami.d.ts +3 -0
  77. package/dist/core/whoami.d.ts.map +1 -1
  78. package/dist/core/whoami.js +14 -0
  79. package/dist/core/whoami.js.map +1 -1
  80. package/dist/core/write-pipeline.d.ts +48 -0
  81. package/dist/core/write-pipeline.d.ts.map +1 -1
  82. package/dist/core/write-pipeline.js +104 -4
  83. package/dist/core/write-pipeline.js.map +1 -1
  84. package/dist/engine/activation.d.ts.map +1 -1
  85. package/dist/engine/activation.js +27 -4
  86. package/dist/engine/activation.js.map +1 -1
  87. package/dist/engine/consolidation.d.ts.map +1 -1
  88. package/dist/engine/consolidation.js +67 -5
  89. package/dist/engine/consolidation.js.map +1 -1
  90. package/dist/hooks/prime-query.d.ts +57 -0
  91. package/dist/hooks/prime-query.d.ts.map +1 -0
  92. package/dist/hooks/prime-query.js +388 -0
  93. package/dist/hooks/prime-query.js.map +1 -0
  94. package/dist/hooks/prime.d.ts +8 -0
  95. package/dist/hooks/prime.d.ts.map +1 -1
  96. package/dist/hooks/prime.js +21 -2
  97. package/dist/hooks/prime.js.map +1 -1
  98. package/dist/hooks/sidecar.d.ts +7 -0
  99. package/dist/hooks/sidecar.d.ts.map +1 -1
  100. package/dist/hooks/sidecar.js +10 -2
  101. package/dist/hooks/sidecar.js.map +1 -1
  102. package/dist/index.js +11 -3
  103. package/dist/index.js.map +1 -1
  104. package/dist/mcp.js +148 -103
  105. package/dist/mcp.js.map +1 -1
  106. package/dist/model-daemon.d.ts +8 -0
  107. package/dist/model-daemon.d.ts.map +1 -0
  108. package/dist/model-daemon.js +45 -0
  109. package/dist/model-daemon.js.map +1 -0
  110. package/dist/storage/factory.d.ts.map +1 -1
  111. package/dist/storage/factory.js +5 -0
  112. package/dist/storage/factory.js.map +1 -1
  113. package/dist/storage/pglite-schema.d.ts.map +1 -1
  114. package/dist/storage/pglite-schema.js +176 -170
  115. package/dist/storage/pglite-schema.js.map +1 -1
  116. package/dist/storage/pglite.d.ts +5 -0
  117. package/dist/storage/pglite.d.ts.map +1 -1
  118. package/dist/storage/pglite.js +165 -153
  119. package/dist/storage/pglite.js.map +1 -1
  120. package/dist/storage/postgres.d.ts +5 -0
  121. package/dist/storage/postgres.d.ts.map +1 -1
  122. package/dist/storage/postgres.js +165 -153
  123. package/dist/storage/postgres.js.map +1 -1
  124. package/dist/storage/sqlite.d.ts +22 -0
  125. package/dist/storage/sqlite.d.ts.map +1 -1
  126. package/dist/storage/sqlite.js +400 -363
  127. package/dist/storage/sqlite.js.map +1 -1
  128. package/dist/types/engram.d.ts +33 -0
  129. package/dist/types/engram.d.ts.map +1 -1
  130. package/dist/types/engram.js.map +1 -1
  131. package/package.json +106 -106
  132. package/plugin/.claude-plugin/plugin.json +1 -1
  133. package/plugin/README.md +1 -1
  134. package/plugin/bin/awm-mcp-launcher.cjs +2 -2
  135. package/plugin/skills/awm-memory/SKILL.md +16 -5
  136. package/src/adapters/common.ts +881 -800
  137. package/src/api/routes.ts +20 -0
  138. package/src/cli/migrate.ts +309 -307
  139. package/src/core/asked-value.ts +74 -0
  140. package/src/core/conflicts.ts +280 -0
  141. package/src/core/embeddings.ts +35 -10
  142. package/src/core/format-recall.ts +83 -25
  143. package/src/core/ml-worker.ts +458 -281
  144. package/src/core/model-daemon-client.ts +374 -0
  145. package/src/core/model-daemon-server.ts +344 -0
  146. package/src/core/model-daemon.ts +243 -0
  147. package/src/core/query-expander.ts +127 -126
  148. package/src/core/recall-config.ts +5 -0
  149. package/src/core/rerank-window.ts +164 -159
  150. package/src/core/rerank2.ts +143 -82
  151. package/src/core/reranker.ts +78 -11
  152. package/src/core/salience.ts +45 -18
  153. package/src/core/trust.ts +65 -0
  154. package/src/core/validity.ts +47 -0
  155. package/src/core/whoami.ts +136 -120
  156. package/src/core/write-pipeline.ts +143 -4
  157. package/src/engine/activation.ts +27 -4
  158. package/src/engine/consolidation.ts +950 -887
  159. package/src/hooks/prime-query.ts +375 -0
  160. package/src/hooks/prime.ts +25 -2
  161. package/src/hooks/sidecar.ts +13 -3
  162. package/src/index.ts +255 -248
  163. package/src/mcp.ts +1521 -1475
  164. package/src/model-daemon.ts +48 -0
  165. package/src/storage/factory.ts +25 -19
  166. package/src/storage/pglite-schema.ts +199 -193
  167. package/src/storage/pglite.ts +1513 -1498
  168. package/src/storage/postgres.ts +1613 -1598
  169. package/src/storage/sqlite.ts +2056 -2019
  170. package/src/types/engram.ts +30 -0
@@ -0,0 +1,363 @@
1
+ // Copyright 2026 Robert Winter / Complete Ideas
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * The shared model daemon process (see model-daemon.ts for the design).
5
+ *
6
+ * It runs ONE inference at a time. onnxruntime-node's CPU arena grows to the largest
7
+ * tensor a session has run, so concurrent runs on the same session would multiply the
8
+ * high-water mark this daemon exists to bound. One at a time costs no speed: four
9
+ * processes recalling at once on one machine finished in 12.3 min with their own models
10
+ * and 11.6 min through one daemon, because they compete for the same cores anyway.
11
+ *
12
+ * Scheduling: interactive requests run before background ones. An embed is run one
13
+ * chunk at a time; an unfinished interactive embed goes to the back of its lane, so
14
+ * sessions take turns and one session's 100-memory write-batch cannot hold up another
15
+ * session's recall; an unfinished background embed goes to the front of its lane, so
16
+ * its chunks stay in order. A request whose connection has closed is dropped unrun.
17
+ * Each step reports `started` when it begins, and a job sent back to the queue between
18
+ * chunks reports `requeued`, so a client's run timer covers only time the daemon spends
19
+ * on its job: its timeout measures a stuck daemon, never a busy one. A step that runs
20
+ * longer than AWM_MODEL_DAEMON_STUCK_MS (default: the client's step timeout, 2 min; for
21
+ * a warm, which may download the models, the client's 10 min) means the daemon is wedged
22
+ * on a promise that will never settle: it exits, and the next client starts a fresh one.
23
+ * The two limits are the same so that a client that gave up on a step is never left
24
+ * reconnecting to the daemon still stuck on it.
25
+ *
26
+ * The daemon exits when no authenticated client has been connected for
27
+ * AWM_MODEL_DAEMON_IDLE_MS (default 5 min). Clients hold one connection each for the
28
+ * life of their process.
29
+ */
30
+ import { createServer, connect } from 'node:net';
31
+ import { randomBytes } from 'node:crypto';
32
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
33
+ import { setTimeout as delay } from 'node:timers/promises';
34
+ import { PROTOCOL_VERSION, HELLO_MAX_BYTES, MAX_FRAME_BYTES, addressProblem, encodeFrame, envInt, FrameReader, modelDaemonPaths, proof, proofMatches, runDirProblem, REQUEST_TIMEOUT_MS, WARM_TIMEOUT_MS, } from './model-daemon.js';
35
+ import { VERSION } from '../version.js';
36
+ const HELLO_TIMEOUT_MS = 5_000;
37
+ /** Windows refuses a rename over a file another process has open; clients open it briefly. */
38
+ async function replaceFile(tmp, target) {
39
+ for (let attempt = 0;; attempt++) {
40
+ try {
41
+ renameSync(tmp, target);
42
+ return;
43
+ }
44
+ catch (err) {
45
+ const code = err.code;
46
+ if ((code !== 'EPERM' && code !== 'EBUSY' && code !== 'EACCES') || attempt >= 40) {
47
+ try {
48
+ unlinkSync(tmp);
49
+ }
50
+ catch { /* nothing to clean */ }
51
+ throw err;
52
+ }
53
+ await delay(25);
54
+ }
55
+ }
56
+ }
57
+ /** A unix socket file left by a crashed daemon refuses connections; a live one accepts. */
58
+ function removeStaleSocket(address) {
59
+ if (process.platform === 'win32' || !existsSync(address))
60
+ return Promise.resolve();
61
+ return new Promise(resolve => {
62
+ const probe = connect(address);
63
+ probe.once('connect', () => { probe.destroy(); resolve(); });
64
+ probe.once('error', () => { try {
65
+ unlinkSync(address);
66
+ }
67
+ catch { /* raced */ } resolve(); });
68
+ });
69
+ }
70
+ export async function startModelDaemon(opts) {
71
+ const { fingerprint } = opts;
72
+ const paths = modelDaemonPaths(fingerprint, opts.runDir);
73
+ const idleMs = opts.idleMs ?? envInt('AWM_MODEL_DAEMON_IDLE_MS', 300_000);
74
+ const log = opts.log ?? ((m) => console.error(`[model-daemon ${new Date().toISOString()}] ${m}`));
75
+ const h = opts.handlers;
76
+ const problem = addressProblem(paths);
77
+ if (problem)
78
+ throw new Error(problem);
79
+ mkdirSync(paths.runDir, { recursive: true, mode: 0o700 });
80
+ try {
81
+ chmodSync(paths.runDir, 0o700);
82
+ }
83
+ catch { /* not ours to change, or Windows */ }
84
+ const unsafe = runDirProblem(paths.runDir);
85
+ if (unsafe)
86
+ throw new Error(unsafe);
87
+ const stuckMs = opts.stuckMs ?? envInt('AWM_MODEL_DAEMON_STUCK_MS', envInt('AWM_MODEL_DAEMON_TIMEOUT_MS', REQUEST_TIMEOUT_MS));
88
+ await removeStaleSocket(paths.address);
89
+ const token = randomBytes(32).toString('hex');
90
+ const sockets = new Set(); // every connection, authenticated or not
91
+ /** Requests a client gave up on, per connection: never started, or never continued. */
92
+ const cancelled = new WeakMap();
93
+ const isCancelled = (job) => cancelled.get(job.socket)?.has(job.id) ?? false;
94
+ /** Until the token file is ours, a hello is told to retry, not proved with a token the
95
+ * file does not hold yet (the rename may be retried on Windows). */
96
+ let tokenReady = false;
97
+ const clients = new Set(); // authenticated ones: these hold the lease
98
+ const interactive = [];
99
+ const background = [];
100
+ const served = {};
101
+ const startedAt = Date.now();
102
+ let busy = false;
103
+ let current = null;
104
+ let idleTimer = null;
105
+ let closing = null;
106
+ const send = (socket, frame) => {
107
+ if (!socket.destroyed)
108
+ socket.write(encodeFrame(frame));
109
+ };
110
+ const armIdle = () => {
111
+ if (idleTimer || clients.size > 0 || idleMs <= 0 || closing)
112
+ return;
113
+ idleTimer = setTimeout(() => {
114
+ idleTimer = null;
115
+ if (clients.size > 0)
116
+ return;
117
+ // A step still running (a first-run warm downloading the models) finishes first.
118
+ if (current || interactive.length || background.length) {
119
+ armIdle();
120
+ return;
121
+ }
122
+ log(`no clients for ${idleMs} ms, exiting`);
123
+ void running.close().then(() => (opts.onIdle ?? (() => process.exit(0)))());
124
+ }, idleMs);
125
+ idleTimer.unref?.();
126
+ };
127
+ /** Runs one step of a job. Returns true when the job is finished. */
128
+ async function step(job) {
129
+ send(job.socket, { id: job.id, started: true });
130
+ if (job.vectors) {
131
+ const texts = job.args.texts;
132
+ const size = h.embedChunk > 0 ? h.embedChunk : texts.length;
133
+ const slice = texts.slice(job.offset, job.offset + size);
134
+ job.vectors.push(...await h.embed({ ...job.args, texts: slice }));
135
+ job.offset += slice.length;
136
+ if (job.offset < texts.length)
137
+ return false;
138
+ send(job.socket, { id: job.id, ok: true, result: job.vectors });
139
+ return true;
140
+ }
141
+ let result;
142
+ switch (job.op) {
143
+ case 'embed':
144
+ result = await h.embed(job.args);
145
+ break;
146
+ case 'rerank':
147
+ result = await h.rerank(job.args);
148
+ break;
149
+ case 'expand':
150
+ result = await h.expand(job.args);
151
+ break;
152
+ case 'warm':
153
+ await h.warm();
154
+ result = true;
155
+ break;
156
+ default: throw new Error(`unknown op ${String(job.op)}`);
157
+ }
158
+ send(job.socket, { id: job.id, ok: true, result });
159
+ return true;
160
+ }
161
+ async function pump() {
162
+ if (busy)
163
+ return;
164
+ busy = true;
165
+ try {
166
+ for (;;) {
167
+ const job = interactive.shift() ?? background.shift();
168
+ if (!job)
169
+ break;
170
+ if (job.socket.destroyed || isCancelled(job))
171
+ continue;
172
+ let done = true;
173
+ current = { op: job.op, since: Date.now() };
174
+ try {
175
+ done = await step(job);
176
+ }
177
+ catch (err) {
178
+ send(job.socket, { id: job.id, ok: false, error: err?.message ?? String(err) });
179
+ }
180
+ finally {
181
+ current = null;
182
+ }
183
+ if (done) {
184
+ served[job.op] = (served[job.op] ?? 0) + 1;
185
+ continue;
186
+ }
187
+ // Back in the queue between chunks: the client's run timer stops until the next
188
+ // step starts, because waiting here is the daemon being busy, not stuck.
189
+ if (isCancelled(job))
190
+ continue;
191
+ send(job.socket, { id: job.id, requeued: true });
192
+ if (job.lane === 'interactive')
193
+ interactive.push(job);
194
+ else
195
+ background.unshift(job);
196
+ }
197
+ }
198
+ finally {
199
+ busy = false;
200
+ }
201
+ }
202
+ const onRequest = (socket, frame) => {
203
+ if (typeof frame?.id !== 'number')
204
+ return;
205
+ if (frame.op === 'cancel') {
206
+ // The client gave up waiting: drop the job, or stop it after its running step.
207
+ const id = frame.args?.id;
208
+ if (typeof id !== 'number')
209
+ return;
210
+ let set = cancelled.get(socket);
211
+ if (!set)
212
+ cancelled.set(socket, (set = new Set()));
213
+ if (set.size >= 10_000)
214
+ set.clear();
215
+ set.add(id);
216
+ for (const q of [interactive, background]) {
217
+ const i = q.findIndex(j => j.socket === socket && j.id === id);
218
+ if (i >= 0)
219
+ q.splice(i, 1);
220
+ }
221
+ return;
222
+ }
223
+ if (frame.op === 'stats') {
224
+ send(socket, {
225
+ id: frame.id, ok: true, result: {
226
+ pid: process.pid, fingerprint, version: VERSION, uptimeMs: Date.now() - startedAt,
227
+ clients: clients.size, queued: { interactive: interactive.length, background: background.length },
228
+ served, rssBytes: process.memoryUsage().rss,
229
+ current: current ? { op: current.op, runningMs: Date.now() - current.since } : null,
230
+ },
231
+ });
232
+ return;
233
+ }
234
+ const lane = frame.lane === 'background' ? 'background' : 'interactive';
235
+ const job = { socket, id: frame.id, op: frame.op, lane, args: frame.args };
236
+ if (frame.op === 'embed' && Array.isArray(frame.args?.texts)) {
237
+ job.offset = 0;
238
+ job.vectors = [];
239
+ }
240
+ (lane === 'background' ? background : interactive).push(job);
241
+ void pump();
242
+ };
243
+ const server = createServer(socket => {
244
+ sockets.add(socket);
245
+ socket.setEncoding('utf8');
246
+ let stage = 'hello';
247
+ let clientNonce = '';
248
+ let daemonNonce = '';
249
+ const helloTimer = setTimeout(() => socket.destroy(), HELLO_TIMEOUT_MS);
250
+ const refuse = (error) => { clearTimeout(helloTimer); socket.end(encodeFrame({ t: 'hello', ok: false, error })); };
251
+ const reader = new FrameReader(frame => {
252
+ if (stage === 'ready')
253
+ return onRequest(socket, frame);
254
+ if (closing)
255
+ return refuse('closing');
256
+ if (!tokenReady)
257
+ return refuse('starting');
258
+ if (stage === 'hello') {
259
+ const hello = frame;
260
+ if (hello?.t !== 'hello')
261
+ return refuse('expected hello');
262
+ if (hello.protocol !== PROTOCOL_VERSION)
263
+ return refuse(`protocol ${hello.protocol} != ${PROTOCOL_VERSION}`);
264
+ if (hello.fingerprint !== fingerprint)
265
+ return refuse('fingerprint mismatch');
266
+ if (typeof hello.nonce !== 'string' || hello.nonce.length < 32)
267
+ return refuse('bad nonce');
268
+ clientNonce = hello.nonce;
269
+ daemonNonce = randomBytes(16).toString('hex');
270
+ stage = 'auth';
271
+ socket.write(encodeFrame({
272
+ t: 'challenge', nonce: daemonNonce, pid: process.pid, version: VERSION,
273
+ proof: proof(token, 'daemon', clientNonce, daemonNonce, fingerprint),
274
+ }));
275
+ return;
276
+ }
277
+ const auth = frame;
278
+ if (auth?.t !== 'auth' || !proofMatches(proof(token, 'client', clientNonce, daemonNonce, fingerprint), auth.proof)) {
279
+ return refuse('bad token');
280
+ }
281
+ clearTimeout(helloTimer);
282
+ stage = 'ready';
283
+ reader.limit = MAX_FRAME_BYTES;
284
+ clients.add(socket);
285
+ if (idleTimer) {
286
+ clearTimeout(idleTimer);
287
+ idleTimer = null;
288
+ }
289
+ socket.write(encodeFrame({ t: 'hello', ok: true }));
290
+ }, HELLO_MAX_BYTES);
291
+ socket.on('data', (chunk) => { if (!reader.push(chunk))
292
+ socket.destroy(); });
293
+ socket.on('error', () => { });
294
+ socket.on('close', () => {
295
+ clearTimeout(helloTimer);
296
+ sockets.delete(socket);
297
+ if (clients.delete(socket))
298
+ armIdle();
299
+ });
300
+ });
301
+ await new Promise((resolve, reject) => {
302
+ server.once('error', reject);
303
+ server.listen(paths.address, () => { server.off('error', reject); resolve(); });
304
+ });
305
+ if (process.platform !== 'win32') {
306
+ try {
307
+ chmodSync(paths.address, 0o600);
308
+ }
309
+ catch { /* best effort */ }
310
+ }
311
+ // The token is written only once this daemon owns the address. A second daemon that
312
+ // lost the race (EADDRINUSE above) must not overwrite the live one's token. A client
313
+ // that connected in the gap read no token or an old one; it is refused and retries.
314
+ const tmp = `${paths.token}.${process.pid}`;
315
+ writeFileSync(tmp, token, { mode: 0o600 });
316
+ try {
317
+ await replaceFile(tmp, paths.token);
318
+ }
319
+ catch (err) {
320
+ server.close();
321
+ throw err;
322
+ }
323
+ tokenReady = true;
324
+ log(`listening on ${paths.address} (pid ${process.pid}, AWM ${VERSION}, fingerprint ${fingerprint})`);
325
+ armIdle();
326
+ const watchdog = stuckMs > 0 ? setInterval(() => {
327
+ if (!current)
328
+ return;
329
+ const limit = current.op === 'warm' ? Math.max(stuckMs, WARM_TIMEOUT_MS) : stuckMs;
330
+ if (Date.now() - current.since <= limit)
331
+ return;
332
+ log(`${current.op} has run for ${Date.now() - current.since} ms: wedged, exiting so a fresh daemon can start`);
333
+ if (watchdog)
334
+ clearInterval(watchdog);
335
+ void running.close().then(() => (opts.onStuck ?? (() => process.exit(1)))());
336
+ }, Math.min(5_000, Math.max(50, Math.floor(stuckMs / 4)))) : null;
337
+ watchdog?.unref?.();
338
+ const running = {
339
+ server, address: paths.address, fingerprint,
340
+ close: () => (closing ??= new Promise(resolve => {
341
+ if (idleTimer) {
342
+ clearTimeout(idleTimer);
343
+ idleTimer = null;
344
+ }
345
+ if (watchdog)
346
+ clearInterval(watchdog);
347
+ // Every connection, including one still in its handshake: server.close() waits for
348
+ // all of them, and a late hello must not authenticate against a closing daemon.
349
+ for (const s of sockets)
350
+ s.destroy();
351
+ server.close(() => {
352
+ try {
353
+ if (readFileSync(paths.token, 'utf8') === token)
354
+ unlinkSync(paths.token);
355
+ }
356
+ catch { /* already gone */ }
357
+ resolve();
358
+ });
359
+ })),
360
+ };
361
+ return running;
362
+ }
363
+ //# sourceMappingURL=model-daemon-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-daemon-server.js","sourceRoot":"","sources":["../../src/core/model-daemon-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Shared model daemon: what the client and the daemon agree on.
3
+ *
4
+ * Every AWM MCP process used to load its own three ONNX models (embedder, cross-encoder,
5
+ * query expander): about 1.1 GB per process even with the input-shape caps, so six
6
+ * Claude Code sessions held 6+ GB of identical weights and arenas. With
7
+ * AWM_MODEL_DAEMON=1, one per-user process holds the models and every AWM process on the
8
+ * machine sends inference to it over a local socket. Store, engine and recall stay in
9
+ * each process; only the three dispatch calls in ml-worker.ts cross the socket.
10
+ *
11
+ * This module has no model imports, so a client that only talks to the daemon never
12
+ * loads @huggingface/transformers' models itself.
13
+ *
14
+ * - The daemon is keyed by a FINGERPRINT of the inference config the model modules
15
+ * actually captured (model ids, dtype, dimensions, pooling, shape caps), the model
16
+ * cache dir, the AWM version and package root, the user and the run dir. Two installs,
17
+ * two versions or two configs get separate daemons and can never mix vectors. The
18
+ * spawned daemon is given the client's captured config as env, so a value applied
19
+ * after the modules loaded (a .env file) cannot make the two disagree; the handshake
20
+ * checks the fingerprint again.
21
+ * - Transport: a named pipe on Windows, a unix socket in ~/.awm/run (0700) elsewhere.
22
+ * - Authentication is mutual, by HMAC over two nonces with the token the daemon wrote to
23
+ * the run dir (0600). The token itself never crosses the socket, so a process that
24
+ * took the pipe name first learns nothing and is refused by the client.
25
+ * - Frames are newline-delimited JSON. JSON.stringify escapes every newline inside a
26
+ * value, so a newline only ever ends a frame. Before authentication a connection may
27
+ * send HELLO_MAX_BYTES; after it, MAX_FRAME_BYTES.
28
+ */
29
+ export declare const PROTOCOL_VERSION = 2;
30
+ export declare const MAX_FRAME_BYTES: number;
31
+ export declare const HELLO_MAX_BYTES: number;
32
+ /** A step must finish within this (client run timer and daemon watchdog both). */
33
+ export declare const REQUEST_TIMEOUT_MS = 120000;
34
+ /** The first warm can include a first-run model download (client and daemon both). */
35
+ export declare const WARM_TIMEOUT_MS: number;
36
+ /** Exit code of a daemon whose own fingerprint is not the one its spawner expected. */
37
+ export declare const EXIT_FINGERPRINT_DRIFT = 3;
38
+ export type ModelOp = 'embed' | 'rerank' | 'expand' | 'warm' | 'stats' | 'cancel';
39
+ /** Interactive work (prime hook, recall, writes) runs ahead of background backfill. */
40
+ export type Lane = 'interactive' | 'background';
41
+ /** What the model modules captured at import; registered with ml-worker. */
42
+ export type InferenceConfig = Record<string, string | number>;
43
+ /** Client → daemon, first frame. */
44
+ export interface HelloFrame {
45
+ t: 'hello';
46
+ protocol: number;
47
+ fingerprint: string;
48
+ nonce: string;
49
+ }
50
+ /** Daemon → client: its proof, and a refusal carries `error`. */
51
+ export interface ChallengeFrame {
52
+ t: 'challenge';
53
+ nonce: string;
54
+ proof: string;
55
+ pid: number;
56
+ version: string;
57
+ }
58
+ /** Client → daemon: the client's proof. */
59
+ export interface AuthFrame {
60
+ t: 'auth';
61
+ proof: string;
62
+ }
63
+ export interface HelloResult {
64
+ t: 'hello';
65
+ ok: boolean;
66
+ error?: string;
67
+ }
68
+ export interface RequestFrame {
69
+ id: number;
70
+ op: ModelOp;
71
+ lane?: Lane;
72
+ args?: unknown;
73
+ }
74
+ /** `started` starts the client's run timer and `requeued` stops it; the final frame has `ok`. */
75
+ export interface ResponseFrame {
76
+ id: number;
77
+ ok?: boolean;
78
+ started?: true;
79
+ requeued?: true;
80
+ result?: unknown;
81
+ error?: string;
82
+ }
83
+ export declare function configEnv(config: InferenceConfig): Record<string, string>;
84
+ export declare function packageRoot(): string;
85
+ export declare function defaultRunDir(env?: NodeJS.ProcessEnv): string;
86
+ /**
87
+ * Size and mtime of the modules whose code decides what inference returns. A rebuild or
88
+ * a dev edit without a version bump is a different daemon, not the old one serving old
89
+ * code to new clients. The client and the daemon run from the same files, so they agree.
90
+ */
91
+ export declare function codeStamp(): string;
92
+ /** 16 hex chars. Everything is a parameter so tests can compare configs in one process. */
93
+ export declare function modelDaemonFingerprint(config: InferenceConfig, o?: {
94
+ env?: NodeJS.ProcessEnv;
95
+ version?: string;
96
+ root?: string;
97
+ code?: string;
98
+ }): string;
99
+ export interface DaemonPaths {
100
+ runDir: string;
101
+ /** Pipe name on Windows, socket path elsewhere. */
102
+ address: string;
103
+ token: string;
104
+ lock: string;
105
+ log: string;
106
+ }
107
+ export declare function modelDaemonPaths(fingerprint: string, runDir?: string): DaemonPaths;
108
+ /** A unix socket path the OS will refuse, or null. */
109
+ export declare function addressProblem(paths: DaemonPaths): string | null;
110
+ /**
111
+ * A run dir another user can write to, or that this user does not own, is refused off
112
+ * Windows: the token and the log are written there, and another user could plant a
113
+ * symlink in their place. (On Windows the dir sits under the user's profile, whose ACL
114
+ * already excludes other users.)
115
+ */
116
+ export declare function runDirProblem(runDir: string): string | null;
117
+ export declare function proof(token: string, role: 'daemon' | 'client', clientNonce: string, daemonNonce: string, fingerprint: string): string;
118
+ export declare function proofMatches(expected: string, got: unknown): boolean;
119
+ /**
120
+ * Splits a byte stream into frames. push() returns false when the unterminated tail is
121
+ * over `limit`. Chunks without a newline are kept as a list and only the new chunk is
122
+ * searched, so a long frame arriving in many chunks costs linear time: appending to one
123
+ * string and searching it again would copy the whole buffer on every chunk.
124
+ */
125
+ export declare class FrameReader {
126
+ private readonly onFrame;
127
+ limit: number;
128
+ private parts;
129
+ private size;
130
+ constructor(onFrame: (frame: unknown) => void, limit?: number);
131
+ push(chunk: string): boolean;
132
+ }
133
+ export declare function encodeFrame(frame: unknown): string;
134
+ export declare function isModelDaemonEnabled(): boolean;
135
+ /** Non-negative integer env var; anything else falls back (an explicit 0 is kept). */
136
+ export declare function envInt(name: string, fallback: number): number;
137
+ //# sourceMappingURL=model-daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-daemon.d.ts","sourceRoot":"","sources":["../../src/core/model-daemon.ts"],"names":[],"mappings":"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"}