@nxgt/ai-memory 0.0.0-stage → 0.1.0

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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +173 -2
  3. package/dist/actions.d.ts +9 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/chunks/index-082dnty9.js +188 -0
  6. package/dist/chunks/index-082dnty9.js.map +14 -0
  7. package/dist/chunks/index-vj24rcgc.js +119 -0
  8. package/dist/chunks/index-vj24rcgc.js.map +13 -0
  9. package/dist/compact.d.ts +38 -0
  10. package/dist/compact.d.ts.map +1 -0
  11. package/dist/contract-actions.d.ts +3 -0
  12. package/dist/contract-actions.d.ts.map +1 -0
  13. package/dist/contract-messages.d.ts +3 -0
  14. package/dist/contract-messages.d.ts.map +1 -0
  15. package/dist/contract-owner.d.ts +3 -0
  16. package/dist/contract-owner.d.ts.map +1 -0
  17. package/dist/contract-samples.d.ts +6 -0
  18. package/dist/contract-samples.d.ts.map +1 -0
  19. package/dist/contract-threads.d.ts +3 -0
  20. package/dist/contract-threads.d.ts.map +1 -0
  21. package/dist/contract.d.ts +9 -0
  22. package/dist/contract.d.ts.map +1 -0
  23. package/dist/errors.d.ts +11 -0
  24. package/dist/errors.d.ts.map +1 -0
  25. package/dist/guards.d.ts +5 -0
  26. package/dist/guards.d.ts.map +1 -0
  27. package/dist/in-process.d.ts +8 -0
  28. package/dist/in-process.d.ts.map +1 -0
  29. package/dist/index.d.ts +8 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +167 -0
  32. package/dist/index.js.map +13 -0
  33. package/dist/messages.d.ts +7 -0
  34. package/dist/messages.d.ts.map +1 -0
  35. package/dist/mongo-actions.d.ts +8 -0
  36. package/dist/mongo-actions.d.ts.map +1 -0
  37. package/dist/mongo-collection.d.ts +32 -0
  38. package/dist/mongo-collection.d.ts.map +1 -0
  39. package/dist/mongo-ctx.d.ts +12 -0
  40. package/dist/mongo-ctx.d.ts.map +1 -0
  41. package/dist/mongo-fields.d.ts +41 -0
  42. package/dist/mongo-fields.d.ts.map +1 -0
  43. package/dist/mongo-map.d.ts +8 -0
  44. package/dist/mongo-map.d.ts.map +1 -0
  45. package/dist/mongo-messages.d.ts +7 -0
  46. package/dist/mongo-messages.d.ts.map +1 -0
  47. package/dist/mongo-store.d.ts +16 -0
  48. package/dist/mongo-store.d.ts.map +1 -0
  49. package/dist/mongo-threads.d.ts +13 -0
  50. package/dist/mongo-threads.d.ts.map +1 -0
  51. package/dist/mongo.d.ts +4 -0
  52. package/dist/mongo.d.ts.map +1 -0
  53. package/dist/mongo.js +271 -0
  54. package/dist/mongo.js.map +16 -0
  55. package/dist/paging.d.ts +8 -0
  56. package/dist/paging.d.ts.map +1 -0
  57. package/dist/pairs.d.ts +14 -0
  58. package/dist/pairs.d.ts.map +1 -0
  59. package/dist/redis-actions.d.ts +8 -0
  60. package/dist/redis-actions.d.ts.map +1 -0
  61. package/dist/redis-ctx.d.ts +37 -0
  62. package/dist/redis-ctx.d.ts.map +1 -0
  63. package/dist/redis-map.d.ts +13 -0
  64. package/dist/redis-map.d.ts.map +1 -0
  65. package/dist/redis-messages.d.ts +7 -0
  66. package/dist/redis-messages.d.ts.map +1 -0
  67. package/dist/redis-scripts.d.ts +40 -0
  68. package/dist/redis-scripts.d.ts.map +1 -0
  69. package/dist/redis-store.d.ts +21 -0
  70. package/dist/redis-store.d.ts.map +1 -0
  71. package/dist/redis-threads.d.ts +16 -0
  72. package/dist/redis-threads.d.ts.map +1 -0
  73. package/dist/redis.d.ts +3 -0
  74. package/dist/redis.d.ts.map +1 -0
  75. package/dist/redis.js +373 -0
  76. package/dist/redis.js.map +16 -0
  77. package/dist/schemas.d.ts +124 -0
  78. package/dist/schemas.d.ts.map +1 -0
  79. package/dist/state.d.ts +28 -0
  80. package/dist/state.d.ts.map +1 -0
  81. package/dist/summarize.d.ts +11 -0
  82. package/dist/summarize.d.ts.map +1 -0
  83. package/dist/testing.d.ts +3 -0
  84. package/dist/testing.d.ts.map +1 -0
  85. package/dist/testing.js +264 -0
  86. package/dist/testing.js.map +15 -0
  87. package/dist/threads.d.ts +7 -0
  88. package/dist/threads.d.ts.map +1 -0
  89. package/dist/truncate.d.ts +17 -0
  90. package/dist/truncate.d.ts.map +1 -0
  91. package/dist/types.d.ts +92 -0
  92. package/dist/types.d.ts.map +1 -0
  93. package/docs/README.md +9 -0
  94. package/docs/guide/memory.md +327 -0
  95. package/docs/roadmap.md +31 -0
  96. package/docs/troubleshooting.md +171 -0
  97. package/package.json +85 -5
package/dist/redis.js ADDED
@@ -0,0 +1,373 @@
1
+ import {
2
+ MemoryError2,
3
+ assertOwner,
4
+ notFound,
5
+ messageSchema2,
6
+ pageLimit,
7
+ assertUuidCursor
8
+ } from "./chunks/index-vj24rcgc.js";
9
+
10
+ // src/redis-actions.ts
11
+ import {
12
+ toProposedAction
13
+ } from "@nxgt/ai-core";
14
+
15
+ // src/redis-ctx.ts
16
+ var keys = {
17
+ thread: (c, id) => `${c.prefix}:thread:${id}`,
18
+ messages: (c, id) => `${c.prefix}:messages:${id}`,
19
+ ids: (c, id) => `${c.prefix}:ids:${id}`,
20
+ actionIndex: (c, id) => `${c.prefix}:actions:${id}`,
21
+ owner: (c, ownerId) => `${c.prefix}:owner:${ownerId}`,
22
+ actionPrefix: (c, ownerId) => `${c.prefix}:action:${ownerId.length}:${ownerId}:`
23
+ };
24
+ function evalLua(c, script, scriptKeys, args) {
25
+ return c.redis.send("EVAL", [
26
+ script,
27
+ String(scriptKeys.length),
28
+ ...scriptKeys,
29
+ ...args
30
+ ]);
31
+ }
32
+ async function readThreadHash(c, id) {
33
+ const raw = await c.redis.send("HGETALL", [keys.thread(c, id)]);
34
+ if (raw === null || raw === undefined)
35
+ return;
36
+ if (Array.isArray(raw)) {
37
+ const out = {};
38
+ for (let i = 0;i + 1 < raw.length; i += 2) {
39
+ out[raw[i]] = raw[i + 1];
40
+ }
41
+ return Object.keys(out).length > 0 ? out : undefined;
42
+ }
43
+ return Object.keys(raw).length > 0 ? { ...raw } : undefined;
44
+ }
45
+ async function ownThread(c, id, ownerId) {
46
+ assertOwner(ownerId);
47
+ const hash = await readThreadHash(c, id);
48
+ return hash && hash["ownerId"] === ownerId ? hash : undefined;
49
+ }
50
+
51
+ // src/redis-map.ts
52
+ function toThread(id, hash) {
53
+ return {
54
+ id,
55
+ ownerId: hash["ownerId"],
56
+ ...hash["title"] === undefined ? {} : { title: hash["title"] },
57
+ ...hash["meta"] === undefined ? {} : { meta: JSON.parse(hash["meta"]) },
58
+ messageCount: Number(hash["messageCount"]),
59
+ ...hash["summary"] === undefined ? {} : { summary: JSON.parse(hash["summary"]) },
60
+ createdAt: Number(hash["createdAt"]),
61
+ updatedAt: Number(hash["updatedAt"])
62
+ };
63
+ }
64
+ function toStoredMessage(threadId, seq, member) {
65
+ return {
66
+ id: member.id,
67
+ threadId,
68
+ seq,
69
+ message: member.message,
70
+ createdAt: member.createdAt
71
+ };
72
+ }
73
+ function parseAction(raw) {
74
+ return typeof raw === "string" ? JSON.parse(raw) : undefined;
75
+ }
76
+
77
+ // src/redis-scripts.ts
78
+ var SLIDE = `
79
+ local function slide(key, at)
80
+ if at ~= '0' then redis.call('PEXPIREAT', key, at) end
81
+ end
82
+ local function slideThread(keys, at)
83
+ for j = 1, 4 do slide(keys[j], at) end
84
+ for _, key in ipairs(redis.call('SMEMBERS', keys[4])) do slide(key, at) end
85
+ end
86
+ `;
87
+ var CREATE_THREAD = `${SLIDE}
88
+ local fields = {'ownerId', ARGV[2], 'messageCount', '0', 'createdAt', ARGV[3], 'updatedAt', ARGV[3]}
89
+ for i = 5, #ARGV do fields[#fields + 1] = ARGV[i] end
90
+ redis.call('HSET', KEYS[1], unpack(fields))
91
+ redis.call('ZADD', KEYS[2], 0, ARGV[1])
92
+ slide(KEYS[1], ARGV[4])
93
+ return 1
94
+ `;
95
+ var APPEND = `${SLIDE}
96
+ if redis.call('HGET', KEYS[1], 'ownerId') ~= ARGV[1] then return false end
97
+ local n = tonumber(ARGV[6])
98
+ local first = redis.call('HINCRBY', KEYS[1], 'messageCount', n) - n + 1
99
+ redis.call('HSET', KEYS[1], 'updatedAt', ARGV[2])
100
+ local i = 7
101
+ for k = 0, n - 1 do
102
+ local id, json, count = ARGV[i], ARGV[i + 1], tonumber(ARGV[i + 2])
103
+ i = i + 3
104
+ redis.call('ZADD', KEYS[2], first + k, json)
105
+ redis.call('HSET', KEYS[3], id, first + k)
106
+ for _ = 1, count do
107
+ local key = ARGV[4] .. ARGV[i]
108
+ if redis.call('HSETNX', key, 'status', 'pending') == 1 then
109
+ redis.call('HSET', key, 'body', ARGV[i + 1], 'thread', ARGV[5])
110
+ redis.call('SADD', KEYS[4], key)
111
+ end
112
+ i = i + 2
113
+ end
114
+ end
115
+ slideThread(KEYS, ARGV[3])
116
+ return first
117
+ `;
118
+ var SET_SUMMARY = `${SLIDE}
119
+ if redis.call('HGET', KEYS[1], 'ownerId') ~= ARGV[1] then return false end
120
+ redis.call('HSET', KEYS[1], 'summary', ARGV[2], 'updatedAt', ARGV[3])
121
+ slideThread(KEYS, ARGV[4])
122
+ return 1
123
+ `;
124
+ var UPDATE_ACTION = `${SLIDE}
125
+ if redis.call('HGET', KEYS[1], 'status') ~= 'pending' then return false end
126
+ redis.call('HSET', KEYS[1], 'status', ARGV[1])
127
+ if ARGV[2] == '1' then redis.call('HSET', KEYS[1], 'result', ARGV[3]) end
128
+ if ARGV[4] ~= '0' then
129
+ local id = redis.call('HGET', KEYS[1], 'thread')
130
+ local base = ARGV[5] .. ':'
131
+ slideThread({base .. 'thread:' .. id, base .. 'messages:' .. id, base .. 'ids:' .. id, base .. 'actions:' .. id}, ARGV[4])
132
+ end
133
+ return 1
134
+ `;
135
+ var DELETE_THREAD = `
136
+ if redis.call('HGET', KEYS[1], 'ownerId') ~= ARGV[1] then return false end
137
+ for _, key in ipairs(redis.call('SMEMBERS', KEYS[4])) do redis.call('DEL', key) end
138
+ redis.call('DEL', KEYS[2], KEYS[3], KEYS[4], KEYS[1])
139
+ redis.call('ZREM', KEYS[5], ARGV[2])
140
+ return 1
141
+ `;
142
+
143
+ // src/redis-actions.ts
144
+ function proposedIn(list) {
145
+ const seen = new Set;
146
+ return list.map((message) => {
147
+ const fresh = [];
148
+ for (const part of message.parts) {
149
+ if (part.type !== "proposed-action" || seen.has(part.id))
150
+ continue;
151
+ seen.add(part.id);
152
+ fresh.push(toProposedAction(part));
153
+ }
154
+ return fresh;
155
+ });
156
+ }
157
+ async function findAction(c, actionId, ownerId) {
158
+ assertOwner(ownerId);
159
+ const key = `${keys.actionPrefix(c, ownerId)}${actionId}`;
160
+ const [body, status, result] = await c.redis.send("HMGET", [
161
+ key,
162
+ "body",
163
+ "status",
164
+ "result"
165
+ ]);
166
+ const action = parseAction(body);
167
+ if (!action || status === null)
168
+ return;
169
+ return {
170
+ ...action,
171
+ status,
172
+ ...result === null ? {} : { result: JSON.parse(result) }
173
+ };
174
+ }
175
+ async function updateAction(c, actionId, ownerId, patch) {
176
+ assertOwner(ownerId);
177
+ const done = await evalLua(c, UPDATE_ACTION, [`${keys.actionPrefix(c, ownerId)}${actionId}`], [
178
+ patch.status,
179
+ patch.result === undefined ? "0" : "1",
180
+ patch.result === undefined ? "" : JSON.stringify(patch.result),
181
+ c.expireAt(c.now()),
182
+ c.prefix
183
+ ]);
184
+ return done === null || done === undefined ? undefined : findAction(c, actionId, ownerId);
185
+ }
186
+
187
+ // src/redis-messages.ts
188
+ var threadKeys = (c, id) => [
189
+ keys.thread(c, id),
190
+ keys.messages(c, id),
191
+ keys.ids(c, id),
192
+ keys.actionIndex(c, id)
193
+ ];
194
+ async function append(c, threadId, ownerId, list) {
195
+ assertOwner(ownerId);
196
+ const parsed = list.map((m) => messageSchema2.parse(m));
197
+ if (parsed.length === 0) {
198
+ if (!await ownThread(c, threadId, ownerId))
199
+ throw notFound(threadId);
200
+ return [];
201
+ }
202
+ const at = c.now();
203
+ const actions = proposedIn(parsed);
204
+ const members = parsed.map((message) => ({
205
+ id: Bun.randomUUIDv7(),
206
+ message,
207
+ createdAt: at
208
+ }));
209
+ const args = members.flatMap((m, i) => [
210
+ m.id,
211
+ JSON.stringify(m),
212
+ String(actions[i]?.length ?? 0),
213
+ ...(actions[i] ?? []).flatMap((a) => [a.id, JSON.stringify(a)])
214
+ ]);
215
+ const first = await evalLua(c, APPEND, threadKeys(c, threadId), [
216
+ ownerId,
217
+ String(at),
218
+ c.expireAt(at),
219
+ keys.actionPrefix(c, ownerId),
220
+ threadId,
221
+ String(parsed.length),
222
+ ...args
223
+ ]);
224
+ if (typeof first !== "number")
225
+ throw notFound(threadId);
226
+ return members.map((m, i) => toStoredMessage(threadId, first + i, m));
227
+ }
228
+ async function load(c, threadId, ownerId, opts) {
229
+ const hash = await ownThread(c, threadId, ownerId);
230
+ if (!hash)
231
+ return;
232
+ const thread = toThread(threadId, hash);
233
+ let after = 0;
234
+ if (opts.sinceSummary && thread.summary) {
235
+ const seq = await c.redis.send("HGET", [
236
+ keys.ids(c, threadId),
237
+ thread.summary.throughMessageId
238
+ ]);
239
+ after = seq === null ? 0 : Number(seq);
240
+ }
241
+ const members = await c.redis.send("ZRANGEBYSCORE", [
242
+ keys.messages(c, threadId),
243
+ `(${after}`,
244
+ "+inf"
245
+ ]);
246
+ return {
247
+ thread,
248
+ ...thread.summary ? { summary: thread.summary } : {},
249
+ messages: members.map((raw, i) => toStoredMessage(threadId, after + i + 1, JSON.parse(raw)))
250
+ };
251
+ }
252
+ async function setSummary(c, threadId, ownerId, input) {
253
+ if (!await ownThread(c, threadId, ownerId))
254
+ throw notFound(threadId);
255
+ const known = await c.redis.send("HEXISTS", [
256
+ keys.ids(c, threadId),
257
+ input.throughMessageId
258
+ ]);
259
+ if (!known) {
260
+ throw new MemoryError2("MESSAGE_NOT_FOUND", `Message "${input.throughMessageId}" is not in thread "${threadId}".`);
261
+ }
262
+ const at = c.now();
263
+ const summary = {
264
+ text: input.text,
265
+ throughMessageId: input.throughMessageId,
266
+ tokens: input.tokens,
267
+ createdAt: at
268
+ };
269
+ const done = await evalLua(c, SET_SUMMARY, threadKeys(c, threadId), [
270
+ ownerId,
271
+ JSON.stringify(summary),
272
+ String(at),
273
+ c.expireAt(at)
274
+ ]);
275
+ if (done === null || done === undefined)
276
+ throw notFound(threadId);
277
+ return summary;
278
+ }
279
+
280
+ // src/redis-threads.ts
281
+ async function createThread(c, input) {
282
+ assertOwner(input.ownerId);
283
+ const id = Bun.randomUUIDv7();
284
+ const at = c.now();
285
+ await evalLua(c, CREATE_THREAD, [keys.thread(c, id), keys.owner(c, input.ownerId)], [
286
+ id,
287
+ input.ownerId,
288
+ String(at),
289
+ c.expireAt(at),
290
+ ...input.title === undefined ? [] : ["title", input.title],
291
+ ...input.meta === undefined ? [] : ["meta", JSON.stringify(input.meta)]
292
+ ]);
293
+ const hash = await readThreadHash(c, id);
294
+ return toThread(id, hash ?? {});
295
+ }
296
+ async function getThread(c, id, ownerId) {
297
+ const hash = await ownThread(c, id, ownerId);
298
+ return hash ? toThread(id, hash) : undefined;
299
+ }
300
+ async function listThreads(c, ownerId, page) {
301
+ assertOwner(ownerId);
302
+ const limit = pageLimit(page);
303
+ assertUuidCursor(page.cursor);
304
+ const items = [];
305
+ let from = page.cursor === undefined ? "+" : `(${page.cursor}`;
306
+ while (items.length <= limit) {
307
+ const ids = await c.redis.send("ZRANGE", [
308
+ keys.owner(c, ownerId),
309
+ from,
310
+ "-",
311
+ "BYLEX",
312
+ "REV",
313
+ "LIMIT",
314
+ "0",
315
+ String(limit + 1 - items.length)
316
+ ]);
317
+ if (ids.length === 0)
318
+ break;
319
+ for (const id of ids) {
320
+ const hash = await readThreadHash(c, id);
321
+ if (hash && hash["ownerId"] === ownerId)
322
+ items.push(toThread(id, hash));
323
+ else
324
+ await c.redis.send("ZREM", [keys.owner(c, ownerId), id]);
325
+ }
326
+ from = `(${ids[ids.length - 1]}`;
327
+ }
328
+ const shown = items.slice(0, limit);
329
+ const last = shown[shown.length - 1];
330
+ return {
331
+ items: shown,
332
+ ...items.length > limit && last ? { nextCursor: last.id } : {}
333
+ };
334
+ }
335
+ async function deleteThread(c, id, ownerId) {
336
+ assertOwner(ownerId);
337
+ const done = await evalLua(c, DELETE_THREAD, [
338
+ keys.thread(c, id),
339
+ keys.messages(c, id),
340
+ keys.ids(c, id),
341
+ keys.actionIndex(c, id),
342
+ keys.owner(c, ownerId)
343
+ ], [ownerId, id]);
344
+ return done !== null && done !== undefined;
345
+ }
346
+
347
+ // src/redis-store.ts
348
+ function redisMemory(options) {
349
+ const ttl = options.expireAfterSeconds;
350
+ const c = {
351
+ redis: options.client,
352
+ prefix: options.prefix ?? "ai-memory",
353
+ now: options.now ?? Date.now,
354
+ expireAt: (at) => ttl === undefined ? "0" : String(at + ttl * 1000)
355
+ };
356
+ return {
357
+ createThread: (input) => createThread(c, input),
358
+ getThread: (id, ownerId) => getThread(c, id, ownerId),
359
+ listThreads: (ownerId, page = {}) => listThreads(c, ownerId, page),
360
+ append: (id, ownerId, list) => append(c, id, ownerId, list),
361
+ load: (id, ownerId, opts) => load(c, id, ownerId, opts),
362
+ setSummary: (id, ownerId, input) => setSummary(c, id, ownerId, input),
363
+ findAction: (id, ownerId) => findAction(c, id, ownerId),
364
+ updateAction: (id, ownerId, patch) => updateAction(c, id, ownerId, patch),
365
+ deleteThread: (id, ownerId) => deleteThread(c, id, ownerId)
366
+ };
367
+ }
368
+ export {
369
+ redisMemory
370
+ };
371
+
372
+ //# debugId=A3B506BC8403B42A64756E2164756E21
373
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1,16 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/redis-actions.ts", "../src/redis-ctx.ts", "../src/redis-map.ts", "../src/redis-scripts.ts", "../src/redis-messages.ts", "../src/redis-threads.ts", "../src/redis-store.ts"],
4
+ "sourcesContent": [
5
+ "import {\n\ttype Message,\n\ttype ProposedAction,\n\ttoProposedAction,\n} from '@nxgt/ai-core';\nimport { assertOwner, type Ctx, evalLua, keys } from './redis-ctx';\nimport { parseAction } from './redis-map';\nimport { UPDATE_ACTION } from './redis-scripts';\nimport type { ActionPatch } from './types';\n\n/** Per message, the actions it proposes, once each within the batch. */\nexport function proposedIn(list: readonly Message[]): ProposedAction[][] {\n\tconst seen = new Set<string>();\n\treturn list.map((message) => {\n\t\tconst fresh: ProposedAction[] = [];\n\t\tfor (const part of message.parts) {\n\t\t\tif (part.type !== 'proposed-action' || seen.has(part.id)) continue;\n\t\t\tseen.add(part.id);\n\t\t\tfresh.push(toProposedAction(part));\n\t\t}\n\t\treturn fresh;\n\t});\n}\n\nexport async function findAction(\n\tc: Ctx,\n\tactionId: string,\n\townerId: string,\n): Promise<ProposedAction | undefined> {\n\tassertOwner(ownerId);\n\tconst key = `${keys.actionPrefix(c, ownerId)}${actionId}`;\n\tconst [body, status, result] = (await c.redis.send('HMGET', [\n\t\tkey,\n\t\t'body',\n\t\t'status',\n\t\t'result',\n\t])) as (string | null)[];\n\tconst action = parseAction(body);\n\tif (!action || status === null) return undefined;\n\treturn {\n\t\t...action,\n\t\tstatus,\n\t\t...(result === null ? {} : { result: JSON.parse(result as string) }),\n\t} as ProposedAction;\n}\n\nexport async function updateAction(\n\tc: Ctx,\n\tactionId: string,\n\townerId: string,\n\tpatch: ActionPatch,\n) {\n\tassertOwner(ownerId);\n\t// One script: it matches only while the action is still pending.\n\tconst done = await evalLua(\n\t\tc,\n\t\tUPDATE_ACTION,\n\t\t[`${keys.actionPrefix(c, ownerId)}${actionId}`],\n\t\t[\n\t\t\tpatch.status,\n\t\t\tpatch.result === undefined ? '0' : '1',\n\t\t\tpatch.result === undefined ? '' : JSON.stringify(patch.result),\n\t\t\tc.expireAt(c.now()),\n\t\t\tc.prefix,\n\t\t],\n\t);\n\treturn done === null || done === undefined\n\t\t? undefined\n\t\t: findAction(c, actionId, ownerId);\n}\n",
6
+ "import { assertOwner, notFound } from './guards';\n\nexport { assertOwner, notFound };\n\n/**\n * The one method the store calls: `RedisClient.send` of Bun, the client that\n * `connectRedis` and `openRedis` of `@nxgt/redis` hand out.\n */\nexport interface RedisCommands {\n\tsend(command: string, args: string[]): Promise<unknown>;\n}\n\n/** What the functions of the sibling files share. */\nexport interface Ctx {\n\tredis: RedisCommands;\n\tprefix: string;\n\tnow: () => number;\n\t/** The expiry as an epoch ms for a write at `at`, or `'0'` without a TTL. */\n\texpireAt: (at: number) => string;\n}\n\n/** The keys of one thread and of one owner. */\nexport const keys = {\n\tthread: (c: Ctx, id: string) => `${c.prefix}:thread:${id}`,\n\tmessages: (c: Ctx, id: string) => `${c.prefix}:messages:${id}`,\n\tids: (c: Ctx, id: string) => `${c.prefix}:ids:${id}`,\n\tactionIndex: (c: Ctx, id: string) => `${c.prefix}:actions:${id}`,\n\towner: (c: Ctx, ownerId: string) => `${c.prefix}:owner:${ownerId}`,\n\t/**\n\t * The prefix of an owner's action keys; the action id follows it. The\n\t * owner's length comes first, so `a:b` + `c` never meets `a` + `b:c`.\n\t */\n\tactionPrefix: (c: Ctx, ownerId: string) =>\n\t\t`${c.prefix}:action:${ownerId.length}:${ownerId}:`,\n};\n\n/** Runs a Lua script atomically. */\nexport function evalLua(\n\tc: Ctx,\n\tscript: string,\n\tscriptKeys: readonly string[],\n\targs: readonly string[],\n): Promise<unknown> {\n\treturn c.redis.send('EVAL', [\n\t\tscript,\n\t\tString(scriptKeys.length),\n\t\t...scriptKeys,\n\t\t...args,\n\t]);\n}\n\n/** The thread's fields as a Redis hash holds them, or `undefined` when absent. */\nexport async function readThreadHash(\n\tc: Ctx,\n\tid: string,\n): Promise<Record<string, string> | undefined> {\n\tconst raw = (await c.redis.send('HGETALL', [keys.thread(c, id)])) as\n\t\t| Record<string, string>\n\t\t| string[]\n\t\t| null;\n\tif (raw === null || raw === undefined) return undefined;\n\tif (Array.isArray(raw)) {\n\t\tconst out: Record<string, string> = {};\n\t\tfor (let i = 0; i + 1 < raw.length; i += 2) {\n\t\t\tout[raw[i] as string] = raw[i + 1] as string;\n\t\t}\n\t\treturn Object.keys(out).length > 0 ? out : undefined;\n\t}\n\treturn Object.keys(raw).length > 0 ? { ...raw } : undefined;\n}\n\n/** The owner's thread hash, or `undefined` when absent or another owner's. */\nexport async function ownThread(c: Ctx, id: string, ownerId: string) {\n\tassertOwner(ownerId);\n\tconst hash = await readThreadHash(c, id);\n\treturn hash && hash['ownerId'] === ownerId ? hash : undefined;\n}\n",
7
+ "import type { Message, ProposedAction } from '@nxgt/ai-core';\nimport type { StoredMessage, Thread, ThreadSummary } from './types';\n\n/** A thread hash as the application reads it. */\nexport function toThread(id: string, hash: Record<string, string>): Thread {\n\treturn {\n\t\tid,\n\t\townerId: hash['ownerId'] as string,\n\t\t...(hash['title'] === undefined ? {} : { title: hash['title'] }),\n\t\t...(hash['meta'] === undefined ? {} : { meta: JSON.parse(hash['meta']) }),\n\t\tmessageCount: Number(hash['messageCount']),\n\t\t...(hash['summary'] === undefined\n\t\t\t? {}\n\t\t\t: { summary: JSON.parse(hash['summary']) as ThreadSummary }),\n\t\tcreatedAt: Number(hash['createdAt']),\n\t\tupdatedAt: Number(hash['updatedAt']),\n\t};\n}\n\n/** What a sorted-set member holds; the seq is its position, not stored. */\nexport interface MessageMember {\n\tid: string;\n\tmessage: Message;\n\tcreatedAt: number;\n}\n\nexport function toStoredMessage(\n\tthreadId: string,\n\tseq: number,\n\tmember: MessageMember,\n): StoredMessage {\n\treturn {\n\t\tid: member.id,\n\t\tthreadId,\n\t\tseq,\n\t\tmessage: member.message,\n\t\tcreatedAt: member.createdAt,\n\t};\n}\n\nexport function parseAction(raw: unknown): ProposedAction | undefined {\n\treturn typeof raw === 'string'\n\t\t? (JSON.parse(raw) as ProposedAction)\n\t\t: undefined;\n}\n",
8
+ "/**\n * The Lua scripts of the store. A script runs as one command, so each\n * read-then-write below is atomic: no other client sees it half done.\n *\n * `ARGV` values that are an expiry hold an epoch ms, or `'0'` for no TTL.\n */\n\nconst SLIDE = `\nlocal function slide(key, at)\n\tif at ~= '0' then redis.call('PEXPIREAT', key, at) end\nend\nlocal function slideThread(keys, at)\n\tfor j = 1, 4 do slide(keys[j], at) end\n\tfor _, key in ipairs(redis.call('SMEMBERS', keys[4])) do slide(key, at) end\nend\n`;\n\n/**\n * KEYS: thread hash, owner index. ARGV: id, ownerId, at, expireAt, then\n * field/value pairs (`title`, `meta`). Writes the thread and indexes it.\n */\nexport const CREATE_THREAD = `${SLIDE}\nlocal fields = {'ownerId', ARGV[2], 'messageCount', '0', 'createdAt', ARGV[3], 'updatedAt', ARGV[3]}\nfor i = 5, #ARGV do fields[#fields + 1] = ARGV[i] end\nredis.call('HSET', KEYS[1], unpack(fields))\nredis.call('ZADD', KEYS[2], 0, ARGV[1])\nslide(KEYS[1], ARGV[4])\nreturn 1\n`;\n\n/**\n * KEYS: thread hash, messages sorted set, id index, action index. ARGV:\n * ownerId, updatedAt, expireAt, action key prefix, thread id, count, then per message\n * its id, its JSON, its action count and per action its id and its body.\n * Returns the first seq of the range it reserved, or nil when the thread is\n * absent or another owner's. The seq range, the messages and the actions are\n * written in the same step, so a reader never sees a gap.\n */\nexport const APPEND = `${SLIDE}\nif redis.call('HGET', KEYS[1], 'ownerId') ~= ARGV[1] then return false end\nlocal n = tonumber(ARGV[6])\nlocal first = redis.call('HINCRBY', KEYS[1], 'messageCount', n) - n + 1\nredis.call('HSET', KEYS[1], 'updatedAt', ARGV[2])\nlocal i = 7\nfor k = 0, n - 1 do\n\tlocal id, json, count = ARGV[i], ARGV[i + 1], tonumber(ARGV[i + 2])\n\ti = i + 3\n\tredis.call('ZADD', KEYS[2], first + k, json)\n\tredis.call('HSET', KEYS[3], id, first + k)\n\tfor _ = 1, count do\n\t\tlocal key = ARGV[4] .. ARGV[i]\n\t\tif redis.call('HSETNX', key, 'status', 'pending') == 1 then\n\t\t\tredis.call('HSET', key, 'body', ARGV[i + 1], 'thread', ARGV[5])\n\t\t\tredis.call('SADD', KEYS[4], key)\n\t\tend\n\t\ti = i + 2\n\tend\nend\nslideThread(KEYS, ARGV[3])\nreturn first\n`;\n\n/**\n * KEYS: thread hash, messages, id index, action index. ARGV: ownerId,\n * summary JSON, updatedAt, expireAt. Returns 1, or nil when the thread is\n * absent or another owner's.\n */\nexport const SET_SUMMARY = `${SLIDE}\nif redis.call('HGET', KEYS[1], 'ownerId') ~= ARGV[1] then return false end\nredis.call('HSET', KEYS[1], 'summary', ARGV[2], 'updatedAt', ARGV[3])\nslideThread(KEYS, ARGV[4])\nreturn 1\n`;\n\n/**\n * KEYS: action hash. ARGV: status, '1' when a result follows, the result\n * JSON, expireAt, key prefix. Moves a pending action on and slides the\n * thread's keys and actions with it; returns 1, or nil when it is absent or\n * no longer pending.\n */\nexport const UPDATE_ACTION = `${SLIDE}\nif redis.call('HGET', KEYS[1], 'status') ~= 'pending' then return false end\nredis.call('HSET', KEYS[1], 'status', ARGV[1])\nif ARGV[2] == '1' then redis.call('HSET', KEYS[1], 'result', ARGV[3]) end\nif ARGV[4] ~= '0' then\n\tlocal id = redis.call('HGET', KEYS[1], 'thread')\n\tlocal base = ARGV[5] .. ':'\n\tslideThread({base .. 'thread:' .. id, base .. 'messages:' .. id, base .. 'ids:' .. id, base .. 'actions:' .. id}, ARGV[4])\nend\nreturn 1\n`;\n\n/**\n * KEYS: thread hash, messages, id index, action index, owner index. ARGV:\n * ownerId, thread id. Removes the thread, its messages and its actions in\n * one step; returns 1, or nil when the thread is absent or another owner's.\n */\nexport const DELETE_THREAD = `\nif redis.call('HGET', KEYS[1], 'ownerId') ~= ARGV[1] then return false end\nfor _, key in ipairs(redis.call('SMEMBERS', KEYS[4])) do redis.call('DEL', key) end\nredis.call('DEL', KEYS[2], KEYS[3], KEYS[4], KEYS[1])\nredis.call('ZREM', KEYS[5], ARGV[2])\nreturn 1\n`;\n",
9
+ "import type { Message } from '@nxgt/ai-core';\nimport { MemoryError } from './errors';\nimport { proposedIn } from './redis-actions';\nimport {\n\tassertOwner,\n\ttype Ctx,\n\tevalLua,\n\tkeys,\n\tnotFound,\n\townThread,\n} from './redis-ctx';\nimport { type MessageMember, toStoredMessage, toThread } from './redis-map';\nimport { APPEND, SET_SUMMARY } from './redis-scripts';\nimport { messageSchema } from './schemas';\nimport type {\n\tLoadedThread,\n\tLoadOptions,\n\tStoredMessage,\n\tSummaryInput,\n\tThreadSummary,\n} from './types';\n\n/** The four keys a thread owns besides its hash, in the order scripts take them. */\nconst threadKeys = (c: Ctx, id: string) => [\n\tkeys.thread(c, id),\n\tkeys.messages(c, id),\n\tkeys.ids(c, id),\n\tkeys.actionIndex(c, id),\n];\n\nexport async function append(\n\tc: Ctx,\n\tthreadId: string,\n\townerId: string,\n\tlist: readonly Message[],\n): Promise<StoredMessage[]> {\n\tassertOwner(ownerId);\n\t// Parsing strips unknown keys; schemas.types.spec.ts guards the cast.\n\tconst parsed = list.map((m) => messageSchema.parse(m) as Message);\n\tif (parsed.length === 0) {\n\t\tif (!(await ownThread(c, threadId, ownerId))) throw notFound(threadId);\n\t\treturn [];\n\t}\n\tconst at = c.now();\n\tconst actions = proposedIn(parsed);\n\tconst members: MessageMember[] = parsed.map((message) => ({\n\t\tid: Bun.randomUUIDv7(),\n\t\tmessage,\n\t\tcreatedAt: at,\n\t}));\n\tconst args = members.flatMap((m, i) => [\n\t\tm.id,\n\t\tJSON.stringify(m),\n\t\tString(actions[i]?.length ?? 0),\n\t\t...(actions[i] ?? []).flatMap((a) => [a.id, JSON.stringify(a)]),\n\t]);\n\t// The script reserves the seq range and writes in one step.\n\tconst first = await evalLua(c, APPEND, threadKeys(c, threadId), [\n\t\townerId,\n\t\tString(at),\n\t\tc.expireAt(at),\n\t\tkeys.actionPrefix(c, ownerId),\n\t\tthreadId,\n\t\tString(parsed.length),\n\t\t...args,\n\t]);\n\tif (typeof first !== 'number') throw notFound(threadId);\n\treturn members.map((m, i) => toStoredMessage(threadId, first + i, m));\n}\n\nexport async function load(\n\tc: Ctx,\n\tthreadId: string,\n\townerId: string,\n\topts: LoadOptions,\n): Promise<LoadedThread | undefined> {\n\tconst hash = await ownThread(c, threadId, ownerId);\n\tif (!hash) return undefined;\n\tconst thread = toThread(threadId, hash);\n\tlet after = 0;\n\tif (opts.sinceSummary && thread.summary) {\n\t\tconst seq = await c.redis.send('HGET', [\n\t\t\tkeys.ids(c, threadId),\n\t\t\tthread.summary.throughMessageId,\n\t\t]);\n\t\tafter = seq === null ? 0 : Number(seq);\n\t}\n\t// Seqs are gapless, so the members after `after` are seq `after + 1`, …\n\tconst members = (await c.redis.send('ZRANGEBYSCORE', [\n\t\tkeys.messages(c, threadId),\n\t\t`(${after}`,\n\t\t'+inf',\n\t])) as string[];\n\treturn {\n\t\tthread,\n\t\t...(thread.summary ? { summary: thread.summary } : {}),\n\t\tmessages: members.map((raw, i) =>\n\t\t\ttoStoredMessage(\n\t\t\t\tthreadId,\n\t\t\t\tafter + i + 1,\n\t\t\t\tJSON.parse(raw) as MessageMember,\n\t\t\t),\n\t\t),\n\t};\n}\n\nexport async function setSummary(\n\tc: Ctx,\n\tthreadId: string,\n\townerId: string,\n\tinput: SummaryInput,\n): Promise<ThreadSummary> {\n\tif (!(await ownThread(c, threadId, ownerId))) throw notFound(threadId);\n\tconst known = await c.redis.send('HEXISTS', [\n\t\tkeys.ids(c, threadId),\n\t\tinput.throughMessageId,\n\t]);\n\tif (!known) {\n\t\tthrow new MemoryError(\n\t\t\t'MESSAGE_NOT_FOUND',\n\t\t\t`Message \"${input.throughMessageId}\" is not in thread \"${threadId}\".`,\n\t\t);\n\t}\n\tconst at = c.now();\n\tconst summary: ThreadSummary = {\n\t\ttext: input.text,\n\t\tthroughMessageId: input.throughMessageId,\n\t\ttokens: input.tokens,\n\t\tcreatedAt: at,\n\t};\n\tconst done = await evalLua(c, SET_SUMMARY, threadKeys(c, threadId), [\n\t\townerId,\n\t\tJSON.stringify(summary),\n\t\tString(at),\n\t\tc.expireAt(at),\n\t]);\n\tif (done === null || done === undefined) throw notFound(threadId);\n\treturn summary;\n}\n",
10
+ "import { assertUuidCursor, pageLimit } from './paging';\nimport {\n\tassertOwner,\n\ttype Ctx,\n\tevalLua,\n\tkeys,\n\townThread,\n\treadThreadHash,\n} from './redis-ctx';\nimport { toThread } from './redis-map';\nimport { CREATE_THREAD, DELETE_THREAD } from './redis-scripts';\nimport type { CreateThreadInput, Page, Thread, ThreadPage } from './types';\n\nexport async function createThread(\n\tc: Ctx,\n\tinput: CreateThreadInput,\n): Promise<Thread> {\n\tassertOwner(input.ownerId);\n\tconst id = Bun.randomUUIDv7();\n\tconst at = c.now();\n\tawait evalLua(\n\t\tc,\n\t\tCREATE_THREAD,\n\t\t[keys.thread(c, id), keys.owner(c, input.ownerId)],\n\t\t[\n\t\t\tid,\n\t\t\tinput.ownerId,\n\t\t\tString(at),\n\t\t\tc.expireAt(at),\n\t\t\t...(input.title === undefined ? [] : ['title', input.title]),\n\t\t\t...(input.meta === undefined ? [] : ['meta', JSON.stringify(input.meta)]),\n\t\t],\n\t);\n\tconst hash = await readThreadHash(c, id);\n\treturn toThread(id, hash ?? {});\n}\n\nexport async function getThread(c: Ctx, id: string, ownerId: string) {\n\tconst hash = await ownThread(c, id, ownerId);\n\treturn hash ? toThread(id, hash) : undefined;\n}\n\n/**\n * Newest first, by id. The owner index can name a thread that has expired:\n * it is skipped and removed, and the page is filled from the ones after it.\n */\nexport async function listThreads(\n\tc: Ctx,\n\townerId: string,\n\tpage: Page,\n): Promise<ThreadPage> {\n\tassertOwner(ownerId);\n\tconst limit = pageLimit(page);\n\tassertUuidCursor(page.cursor);\n\tconst items: Thread[] = [];\n\tlet from = page.cursor === undefined ? '+' : `(${page.cursor}`;\n\twhile (items.length <= limit) {\n\t\tconst ids = (await c.redis.send('ZRANGE', [\n\t\t\tkeys.owner(c, ownerId),\n\t\t\tfrom,\n\t\t\t'-',\n\t\t\t'BYLEX',\n\t\t\t'REV',\n\t\t\t'LIMIT',\n\t\t\t'0',\n\t\t\tString(limit + 1 - items.length),\n\t\t])) as string[];\n\t\tif (ids.length === 0) break;\n\t\tfor (const id of ids) {\n\t\t\tconst hash = await readThreadHash(c, id);\n\t\t\tif (hash && hash['ownerId'] === ownerId) items.push(toThread(id, hash));\n\t\t\telse await c.redis.send('ZREM', [keys.owner(c, ownerId), id]);\n\t\t}\n\t\tfrom = `(${ids[ids.length - 1]}`;\n\t}\n\tconst shown = items.slice(0, limit);\n\tconst last = shown[shown.length - 1];\n\treturn {\n\t\titems: shown,\n\t\t...(items.length > limit && last ? { nextCursor: last.id } : {}),\n\t};\n}\n\n/**\n * One script removes the messages, the actions, the thread and its owner\n * index entry, so a crash or a racing `append` never leaves keys nobody can\n * reach: the append finds the thread gone.\n */\nexport async function deleteThread(c: Ctx, id: string, ownerId: string) {\n\tassertOwner(ownerId);\n\tconst done = await evalLua(\n\t\tc,\n\t\tDELETE_THREAD,\n\t\t[\n\t\t\tkeys.thread(c, id),\n\t\t\tkeys.messages(c, id),\n\t\t\tkeys.ids(c, id),\n\t\t\tkeys.actionIndex(c, id),\n\t\t\tkeys.owner(c, ownerId),\n\t\t],\n\t\t[ownerId, id],\n\t);\n\treturn done !== null && done !== undefined;\n}\n",
11
+ "import * as actions from './redis-actions';\nimport type { Ctx, RedisCommands } from './redis-ctx';\nimport * as messages from './redis-messages';\nimport * as threads from './redis-threads';\nimport type { MemoryStore } from './types';\n\nexport interface RedisMemoryOptions {\n\t/**\n\t * The client: `connection.client` of `connectRedis`, or the `client` of an\n\t * instance of `openRedis`, both from `@nxgt/redis`.\n\t */\n\tclient: RedisCommands;\n\t/** What every key starts with; default `ai-memory`. */\n\tprefix?: string;\n\t/**\n\t * Keys expire this long after the thread's last write, so the whole thread\n\t * goes together.\n\t */\n\texpireAfterSeconds?: number;\n\t/** The clock, in epoch ms; default `Date.now`. */\n\tnow?: () => number;\n}\n\n/** A store over Redis keys; see the guide for the layout, expiry and limits. */\nexport function redisMemory(options: RedisMemoryOptions): MemoryStore {\n\tconst ttl = options.expireAfterSeconds;\n\tconst c: Ctx = {\n\t\tredis: options.client,\n\t\tprefix: options.prefix ?? 'ai-memory',\n\t\tnow: options.now ?? Date.now,\n\t\texpireAt: (at) => (ttl === undefined ? '0' : String(at + ttl * 1000)),\n\t};\n\treturn {\n\t\tcreateThread: (input) => threads.createThread(c, input),\n\t\tgetThread: (id, ownerId) => threads.getThread(c, id, ownerId),\n\t\tlistThreads: (ownerId, page = {}) => threads.listThreads(c, ownerId, page),\n\t\tappend: (id, ownerId, list) => messages.append(c, id, ownerId, list),\n\t\tload: (id, ownerId, opts) => messages.load(c, id, ownerId, opts),\n\t\tsetSummary: (id, ownerId, input) =>\n\t\t\tmessages.setSummary(c, id, ownerId, input),\n\t\tfindAction: (id, ownerId) => actions.findAction(c, id, ownerId),\n\t\tupdateAction: (id, ownerId, patch) =>\n\t\t\tactions.updateAction(c, id, ownerId, patch),\n\t\tdeleteThread: (id, ownerId) => threads.deleteThread(c, id, ownerId),\n\t};\n}\n"
12
+ ],
13
+ "mappings": "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",
14
+ "debugId": "A3B506BC8403B42A64756E2164756E21",
15
+ "names": []
16
+ }
@@ -0,0 +1,124 @@
1
+ import { z } from 'zod';
2
+ /** An `@nxgt/ai-core` `Message`; `append` parses every message with it. */
3
+ export declare const messageSchema: z.ZodObject<{
4
+ role: z.ZodEnum<{
5
+ user: "user";
6
+ assistant: "assistant";
7
+ tool: "tool";
8
+ }>;
9
+ parts: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
10
+ type: z.ZodLiteral<"text">;
11
+ text: z.ZodString;
12
+ }, z.core.$strip>, z.ZodObject<{
13
+ type: z.ZodLiteral<"thinking">;
14
+ text: z.ZodString;
15
+ signature: z.ZodOptional<z.ZodString>;
16
+ redacted: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>, z.ZodObject<{
18
+ type: z.ZodLiteral<"tool-call">;
19
+ id: z.ZodString;
20
+ name: z.ZodString;
21
+ input: z.ZodUnknown;
22
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
23
+ isError: z.ZodLiteral<false>;
24
+ output: z.ZodUnknown;
25
+ type: z.ZodLiteral<"tool-result">;
26
+ callId: z.ZodString;
27
+ name: z.ZodString;
28
+ }, z.core.$strip>, z.ZodObject<{
29
+ isError: z.ZodLiteral<true>;
30
+ error: z.ZodObject<{
31
+ code: z.ZodString;
32
+ message: z.ZodString;
33
+ issues: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
34
+ path: z.ZodString;
35
+ message: z.ZodString;
36
+ }, z.core.$strip>>>>;
37
+ }, z.core.$strip>;
38
+ type: z.ZodLiteral<"tool-result">;
39
+ callId: z.ZodString;
40
+ name: z.ZodString;
41
+ }, z.core.$strip>], "isError">, z.ZodObject<{
42
+ type: z.ZodLiteral<"proposed-action">;
43
+ id: z.ZodString;
44
+ tool: z.ZodString;
45
+ input: z.ZodUnknown;
46
+ summary: z.ZodOptional<z.ZodString>;
47
+ expiresAt: z.ZodNumber;
48
+ }, z.core.$strip>]>>;
49
+ }, z.core.$strip>;
50
+ export declare const summarySchema: z.ZodObject<{
51
+ text: z.ZodString;
52
+ throughMessageId: z.ZodString;
53
+ tokens: z.ZodNumber;
54
+ createdAt: z.ZodNumber;
55
+ }, z.core.$strip>;
56
+ export declare const threadSchema: z.ZodObject<{
57
+ id: z.ZodString;
58
+ ownerId: z.ZodString;
59
+ title: z.ZodOptional<z.ZodString>;
60
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
61
+ messageCount: z.ZodNumber;
62
+ summary: z.ZodOptional<z.ZodObject<{
63
+ text: z.ZodString;
64
+ throughMessageId: z.ZodString;
65
+ tokens: z.ZodNumber;
66
+ createdAt: z.ZodNumber;
67
+ }, z.core.$strip>>;
68
+ createdAt: z.ZodNumber;
69
+ updatedAt: z.ZodNumber;
70
+ }, z.core.$strip>;
71
+ export declare const storedMessageSchema: z.ZodObject<{
72
+ id: z.ZodString;
73
+ threadId: z.ZodString;
74
+ seq: z.ZodNumber;
75
+ message: z.ZodObject<{
76
+ role: z.ZodEnum<{
77
+ user: "user";
78
+ assistant: "assistant";
79
+ tool: "tool";
80
+ }>;
81
+ parts: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
82
+ type: z.ZodLiteral<"text">;
83
+ text: z.ZodString;
84
+ }, z.core.$strip>, z.ZodObject<{
85
+ type: z.ZodLiteral<"thinking">;
86
+ text: z.ZodString;
87
+ signature: z.ZodOptional<z.ZodString>;
88
+ redacted: z.ZodOptional<z.ZodString>;
89
+ }, z.core.$strip>, z.ZodObject<{
90
+ type: z.ZodLiteral<"tool-call">;
91
+ id: z.ZodString;
92
+ name: z.ZodString;
93
+ input: z.ZodUnknown;
94
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
95
+ isError: z.ZodLiteral<false>;
96
+ output: z.ZodUnknown;
97
+ type: z.ZodLiteral<"tool-result">;
98
+ callId: z.ZodString;
99
+ name: z.ZodString;
100
+ }, z.core.$strip>, z.ZodObject<{
101
+ isError: z.ZodLiteral<true>;
102
+ error: z.ZodObject<{
103
+ code: z.ZodString;
104
+ message: z.ZodString;
105
+ issues: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
106
+ path: z.ZodString;
107
+ message: z.ZodString;
108
+ }, z.core.$strip>>>>;
109
+ }, z.core.$strip>;
110
+ type: z.ZodLiteral<"tool-result">;
111
+ callId: z.ZodString;
112
+ name: z.ZodString;
113
+ }, z.core.$strip>], "isError">, z.ZodObject<{
114
+ type: z.ZodLiteral<"proposed-action">;
115
+ id: z.ZodString;
116
+ tool: z.ZodString;
117
+ input: z.ZodUnknown;
118
+ summary: z.ZodOptional<z.ZodString>;
119
+ expiresAt: z.ZodNumber;
120
+ }, z.core.$strip>]>>;
121
+ }, z.core.$strip>;
122
+ createdAt: z.ZodNumber;
123
+ }, z.core.$strip>;
124
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqDxB,2EAA2E;AAC3E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAWxB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;iBAOxB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;iBASvB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAO9B,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { ProposedAction } from '@nxgt/ai-core';
2
+ import { assertOwner } from './guards.js';
3
+ import type { StoredMessage, Thread } from './types.js';
4
+ export interface ThreadRecord {
5
+ thread: Thread;
6
+ /** Creation order across the store; the list cursor. */
7
+ order: number;
8
+ messages: StoredMessage[];
9
+ }
10
+ export interface ActionRecord {
11
+ ownerId: string;
12
+ threadId: string;
13
+ action: ProposedAction;
14
+ }
15
+ /** What the store keeps; the functions of the sibling files change it. */
16
+ export interface State {
17
+ now: () => number;
18
+ threads: Map<string, ThreadRecord>;
19
+ /** Keyed by `actionKey`, so an id is only ever taken within one owner. */
20
+ actions: Map<string, ActionRecord>;
21
+ counter: number;
22
+ }
23
+ export { assertOwner };
24
+ export declare const actionKey: (ownerId: string, actionId: string) => string;
25
+ /** The owner's thread, or undefined for an absent or foreign one. */
26
+ export declare function own(s: State, id: string, ownerId: string): ThreadRecord | undefined;
27
+ export declare function ownOrThrow(s: State, id: string, ownerId: string): ThreadRecord;
28
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,WAAW,EAAY,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAErD,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,KAAK;IACrB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC,0EAA0E;IAC1E,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,EAAE,UAAU,MAAM,KAAG,MAChC,CAAC;AAE/B,qEAAqE;AACrE,wBAAgB,GAAG,CAClB,CAAC,EAAE,KAAK,EACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACb,YAAY,GAAG,SAAS,CAI1B;AAED,wBAAgB,UAAU,CACzB,CAAC,EAAE,KAAK,EACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACb,YAAY,CAMd"}
@@ -0,0 +1,11 @@
1
+ import { type Message, type ModelAdapter } from '@nxgt/ai-core';
2
+ export interface SummarizeOptions {
3
+ /** The instruction to the model; the default asks for a faithful brief summary. */
4
+ system?: string;
5
+ /** Cap on the summary, in tokens; default 1024. */
6
+ maxTokens?: number;
7
+ signal?: AbortSignal;
8
+ }
9
+ /** A `summarize` for `compact`, backed by a model through `generate`. */
10
+ export declare function summarizeWith(model: ModelAdapter, options?: SummarizeOptions): (messages: Message[]) => Promise<string>;
11
+ //# sourceMappingURL=summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../src/summarize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAChC,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAOD,yEAAyE;AACzE,wBAAgB,aAAa,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,gBAAqB,GAC5B,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAsB1C"}
@@ -0,0 +1,3 @@
1
+ export { memoryStoreContract } from './contract.js';
2
+ export { inProcessMemory } from './in-process.js';
3
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}