@tangle-network/agent-knowledge 1.6.0 → 1.7.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.
package/README.md CHANGED
@@ -11,6 +11,7 @@ This package turns raw sources and generated markdown knowledge into a versionab
11
11
  - [CLI](#cli) — `init` → `source-add` → `index` → `search` → `lint`
12
12
  - [Design](#design) — the invariants (immutable sources, cited claims, deterministic graph)
13
13
  - [Agent-Eval integration](#agent-eval-integration) — readiness bundles + release reports
14
+ - [Memory adapters](#memory-adapters) — generic memory contract + Neo4j Agent Memory bridge
14
15
  - [Research loop](#research-loop) — `runKnowledgeResearchLoop` + control-loop adapter
15
16
  - [Researcher profile](#researcher-profile) — sandbox `AgentProfile` for `runLoop`
16
17
  - [Pluggable knowledge sources](#pluggable-knowledge-sources) — live authorities → eval re-runs
@@ -106,6 +107,10 @@ from `@tangle-network/agent-knowledge`.
106
107
 
107
108
  The `/viz` subpath exports graph insight helpers without UI dependencies.
108
109
 
110
+ The `/memory` subpath exports an optional memory adapter contract. Use it to
111
+ bridge episodic or graph-native memory systems into the same source-grounded
112
+ readiness/eval machinery without making `agent-knowledge` own the database.
113
+
109
114
  ## Agent-Eval Integration
110
115
 
111
116
  To answer whether a candidate knowledge base actually improves agent task success, run an `@tangle-network/agent-eval` improvement loop (`runImprovementLoop`) over your KB variants on a real task corpus; each run is scored into a `RunRecord`.
@@ -143,6 +148,38 @@ Pass `readiness.report` to `blockingKnowledgeEval()` from
143
148
  `@tangle-network/agent-eval`; use `readiness.questions` and
144
149
  `readiness.acquisitionPlans` to drive UI or connector workflows.
145
150
 
151
+ ## Memory Adapters
152
+
153
+ `agent-knowledge` does not store operational memory itself. It defines the
154
+ contract that lets a runtime read/write memory through any backend, then turn
155
+ memory hits into `SourceRecord` evidence for readiness, linting, and eval gates.
156
+
157
+ ```ts
158
+ import {
159
+ createNeo4jAgentMemoryAdapter,
160
+ memoryHitToSourceRecord,
161
+ } from '@tangle-network/agent-knowledge/memory'
162
+
163
+ const memory = createNeo4jAgentMemoryAdapter({ client: neo4jMemoryClient })
164
+
165
+ const context = await memory.getContext('What does this user prefer?', {
166
+ scope: { userId: 'user-123', sessionId: 'session-456' },
167
+ limit: 5,
168
+ })
169
+
170
+ const sourceRecords = context.hits.map((hit) =>
171
+ memoryHitToSourceRecord(hit, { scope: { userId: 'user-123' } }),
172
+ )
173
+ ```
174
+
175
+ The Neo4j adapter is runtime dependency-free: pass the real
176
+ `@neo4j-labs/agent-memory` client in products, or a fake client in tests. CI
177
+ typechecks against `@neo4j-labs/agent-memory@0.4.0` and covers the published
178
+ TypeScript SDK surface: `shortTerm.addMessage/searchMessages/getContext`,
179
+ `longTerm.addEntity/addPreference/addFact/searchEntities/searchPreferences`,
180
+ and `reasoning.getSimilarTraces`. Generic `search` / `getContext` and
181
+ snake_case bridge-style methods remain supported for non-hosted clients.
182
+
146
183
  ## Research Loop
147
184
 
148
185
  Use `runKnowledgeResearchLoop()` when an agent is acting as a researcher or
@@ -0,0 +1,585 @@
1
+ import {
2
+ sha256,
3
+ stableId
4
+ } from "./chunk-YMKHCTS2.js";
5
+
6
+ // src/memory/source-record.ts
7
+ function memoryHitToSourceRecord(hit, options = {}) {
8
+ const contentHash = sha256(`${hit.uri}
9
+ ${hit.text}`);
10
+ return {
11
+ id: stableId("src", `${hit.uri}:${contentHash}`),
12
+ uri: hit.uri,
13
+ title: hit.title ?? `${hit.kind}:${hit.id}`,
14
+ mediaType: "text/plain",
15
+ contentHash,
16
+ text: hit.text,
17
+ validUntil: hit.validUntil,
18
+ lastVerifiedAt: hit.lastVerifiedAt,
19
+ createdAt: (options.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
20
+ metadata: {
21
+ ...hit.metadata ?? {},
22
+ source: "agent-memory",
23
+ memoryId: hit.id,
24
+ memoryKind: hit.kind,
25
+ score: hit.score,
26
+ normalizedScore: hit.normalizedScore,
27
+ confidence: hit.confidence,
28
+ scope: options.scope
29
+ }
30
+ };
31
+ }
32
+ function memoryWriteResultToSourceRecord(result, text, options = {}) {
33
+ return memoryHitToSourceRecord(
34
+ {
35
+ id: result.id,
36
+ uri: result.uri,
37
+ kind: result.kind,
38
+ text,
39
+ metadata: result.metadata
40
+ },
41
+ options
42
+ );
43
+ }
44
+
45
+ // src/memory/adapter.ts
46
+ async function defaultGetMemoryContext(adapter, query, options = {}) {
47
+ const hits = await adapter.search(query, options);
48
+ return {
49
+ query,
50
+ hits,
51
+ sourceRecords: hits.map((hit) => memoryHitToSourceRecord(hit, { scope: options.scope })),
52
+ text: renderMemoryContext(hits)
53
+ };
54
+ }
55
+ function renderMemoryContext(hits) {
56
+ return hits.map((hit, index) => {
57
+ const label = hit.title ?? `${hit.kind}:${hit.id}`;
58
+ const score = typeof hit.normalizedScore === "number" ? ` score=${hit.normalizedScore.toFixed(3)}` : "";
59
+ return [`[${index + 1}] ${label}${score}`, hit.text].join("\n");
60
+ }).join("\n\n");
61
+ }
62
+
63
+ // src/memory/neo4j.ts
64
+ function createNeo4jAgentMemoryAdapter(options) {
65
+ const client = options.client;
66
+ const id = options.id ?? "neo4j-agent-memory";
67
+ return {
68
+ id,
69
+ async search(query, searchOptions = {}) {
70
+ const sdkHits = await searchNeo4jMemory(client, query, searchOptions, id);
71
+ if (sdkHits.length > 0) return sdkHits;
72
+ const result = await callOptional(
73
+ client,
74
+ ["search", "memory_search"],
75
+ [query, neo4jOptions(searchOptions)]
76
+ );
77
+ if (result !== void 0) return normalizeHits(result, searchOptions, id);
78
+ const context = await callOptional(
79
+ client,
80
+ ["getContext", "get_context"],
81
+ [query, neo4jOptions(searchOptions)]
82
+ );
83
+ if (context !== void 0) return normalizeHits(context, searchOptions, id);
84
+ return [];
85
+ },
86
+ async getContext(query, searchOptions = {}) {
87
+ const shortTerm = nested(client, ["shortTerm", "short_term"], {});
88
+ const sessionId = searchOptions.scope?.sessionId;
89
+ if (sessionId) {
90
+ const conversationContext = await callOptional(
91
+ shortTerm,
92
+ ["getContext", "get_context"],
93
+ [sessionId]
94
+ );
95
+ if (conversationContext !== void 0) {
96
+ const hits2 = normalizeConversationContextHits(conversationContext, searchOptions, id);
97
+ const text = textFromConversationContext(conversationContext) ?? (typeof conversationContext === "string" ? conversationContext : hits2.length > 0 ? renderHits(hits2) : "");
98
+ return {
99
+ query,
100
+ text,
101
+ hits: hits2,
102
+ sourceRecords: hits2.map(
103
+ (hit) => memoryHitToSourceRecord(hit, { scope: searchOptions.scope })
104
+ ),
105
+ metadata: { adapter: id, rawContext: conversationContext }
106
+ };
107
+ }
108
+ }
109
+ const result = await callOptional(
110
+ client,
111
+ ["getContext", "get_context"],
112
+ [query, neo4jOptions(searchOptions)]
113
+ );
114
+ if (result === void 0) {
115
+ return defaultGetMemoryContext(
116
+ {
117
+ search: async () => {
118
+ const sdkHits = await searchNeo4jMemory(client, query, searchOptions, id);
119
+ if (sdkHits.length > 0) return sdkHits;
120
+ const searchResult = await callOptional(
121
+ client,
122
+ ["search", "memory_search"],
123
+ [query, neo4jOptions(searchOptions)]
124
+ );
125
+ return normalizeHits(searchResult, searchOptions, id);
126
+ }
127
+ },
128
+ query,
129
+ searchOptions
130
+ );
131
+ }
132
+ if (typeof result === "string") {
133
+ const hit = {
134
+ id: stableId("mem", `${id}:${query}:${result}`),
135
+ uri: `memory://${id}/context/${stableId("ctx", query)}`,
136
+ kind: "fact",
137
+ text: result,
138
+ title: "Memory context",
139
+ normalizedScore: 1
140
+ };
141
+ return {
142
+ query,
143
+ text: result,
144
+ hits: [hit],
145
+ sourceRecords: [memoryHitToSourceRecord(hit, { scope: searchOptions.scope })],
146
+ metadata: { adapter: id }
147
+ };
148
+ }
149
+ const hits = normalizeHits(result, searchOptions, id);
150
+ if (hits.length > 0)
151
+ return defaultGetMemoryContext({ search: async () => hits }, query, searchOptions);
152
+ return defaultGetMemoryContext({ search: async () => [] }, query, searchOptions);
153
+ },
154
+ async write(input) {
155
+ const result = await writeNeo4jMemory(client, input, id);
156
+ return {
157
+ ...result,
158
+ sourceRecord: memoryWriteResultToSourceRecord(result, input.text, { scope: input.scope })
159
+ };
160
+ }
161
+ };
162
+ }
163
+ async function writeNeo4jMemory(client, input, adapterId) {
164
+ const scope = input.scope ?? {};
165
+ const sessionId = scope.sessionId ?? input.metadata?.sessionId;
166
+ let result;
167
+ if (input.kind === "message") {
168
+ const shortTerm = nested(client, ["shortTerm", "short_term"], client);
169
+ result = await callOptional(
170
+ shortTerm,
171
+ ["addMessage"],
172
+ [
173
+ sessionId,
174
+ input.role ?? "user",
175
+ input.text,
176
+ {
177
+ metadata: input.metadata,
178
+ conversationId: sessionId,
179
+ userId: scope.userId
180
+ }
181
+ ]
182
+ );
183
+ if (result === void 0) {
184
+ result = await callRequired(
185
+ shortTerm,
186
+ ["add_message"],
187
+ [
188
+ {
189
+ session_id: sessionId,
190
+ sessionId,
191
+ role: input.role ?? "user",
192
+ content: input.text,
193
+ user_identifier: scope.userId,
194
+ userIdentifier: scope.userId,
195
+ metadata: input.metadata
196
+ }
197
+ ]
198
+ );
199
+ }
200
+ } else if (input.kind === "entity") {
201
+ const longTerm = nested(client, ["longTerm", "long_term"], client);
202
+ result = await callOptional(
203
+ longTerm,
204
+ ["addEntity"],
205
+ [
206
+ input.entityName ?? input.title ?? input.text,
207
+ input.entityType ?? "ENTITY",
208
+ neo4jEntityOptions(input)
209
+ ]
210
+ );
211
+ if (result === void 0) {
212
+ result = await callRequired(
213
+ longTerm,
214
+ ["add_entity"],
215
+ [
216
+ input.entityName ?? input.title ?? input.text,
217
+ input.entityType ?? "ENTITY",
218
+ neo4jWriteOptions(input)
219
+ ]
220
+ );
221
+ }
222
+ } else if (input.kind === "preference") {
223
+ const longTerm = nested(client, ["longTerm", "long_term"], client);
224
+ result = await callOptional(
225
+ longTerm,
226
+ ["addPreference"],
227
+ [input.category ?? "general", input.text, neo4jPreferenceOptions(input)]
228
+ );
229
+ if (result === void 0) {
230
+ result = await callRequired(
231
+ longTerm,
232
+ ["add_preference"],
233
+ [input.category ?? "general", input.text, neo4jWriteOptions(input)]
234
+ );
235
+ }
236
+ } else {
237
+ result = await callRequired(
238
+ nested(client, ["longTerm", "long_term"], client),
239
+ ["addFact", "add_fact"],
240
+ [
241
+ input.subject ?? input.title ?? input.kind,
242
+ input.predicate ?? "states",
243
+ input.object ?? input.text
244
+ ]
245
+ );
246
+ }
247
+ const id = idFromResult(result) ?? input.id ?? stableId("mem", `${input.kind}:${input.text}`);
248
+ return {
249
+ accepted: true,
250
+ id,
251
+ uri: `memory://${adapterId}/${encodeURIComponent(id)}`,
252
+ kind: input.kind,
253
+ metadata: { rawResult: result }
254
+ };
255
+ }
256
+ async function searchNeo4jMemory(client, query, options, adapterId) {
257
+ const searches = [];
258
+ const kinds = options.kinds;
259
+ const includeKind = (kind) => !kinds?.length || kinds.includes(kind);
260
+ const shortTerm = nested(client, ["shortTerm", "short_term"], {});
261
+ const longTerm = nested(client, ["longTerm", "long_term"], {});
262
+ const reasoning = nested(client, ["reasoning"], {});
263
+ if (includeKind("message")) {
264
+ searches.push(
265
+ callOptional(
266
+ shortTerm,
267
+ ["searchMessages", "search_messages"],
268
+ [query, searchMessagesOptions(options)]
269
+ ).then((result) => normalizeHits(result, { ...options, kinds: ["message"] }, adapterId))
270
+ );
271
+ }
272
+ if (includeKind("entity")) {
273
+ searches.push(
274
+ callOptional(
275
+ longTerm,
276
+ ["searchEntities", "search_entities"],
277
+ [query, searchEntitiesOptions(options)]
278
+ ).then((result) => normalizeHits(result, { ...options, kinds: ["entity"] }, adapterId))
279
+ );
280
+ }
281
+ if (includeKind("preference")) {
282
+ searches.push(
283
+ callOptional(
284
+ longTerm,
285
+ ["searchPreferences", "search_preferences"],
286
+ [query, searchPreferencesOptions(options)]
287
+ ).then((result) => normalizeHits(result, { ...options, kinds: ["preference"] }, adapterId))
288
+ );
289
+ }
290
+ if (includeKind("reasoning-trace")) {
291
+ searches.push(
292
+ callOptional(
293
+ reasoning,
294
+ ["getSimilarTraces", "get_similar_traces"],
295
+ [query, similarTracesOptions(options)]
296
+ ).then(
297
+ (result) => normalizeHits(result, { ...options, kinds: ["reasoning-trace"] }, adapterId)
298
+ )
299
+ );
300
+ }
301
+ const hits = (await Promise.all(searches)).flat();
302
+ return hits.sort((a, b) => (b.normalizedScore ?? b.score ?? 0) - (a.normalizedScore ?? a.score ?? 0)).slice(0, options.limit);
303
+ }
304
+ function neo4jOptions(options) {
305
+ return {
306
+ limit: options.limit,
307
+ k: options.limit,
308
+ min_score: options.minScore,
309
+ minScore: options.minScore,
310
+ user_identifier: options.scope?.userId,
311
+ userIdentifier: options.scope?.userId,
312
+ session_id: options.scope?.sessionId,
313
+ sessionId: options.scope?.sessionId,
314
+ namespace: options.scope?.namespace,
315
+ tenant_id: options.scope?.tenantId,
316
+ tenantId: options.scope?.tenantId,
317
+ kinds: options.kinds,
318
+ metadata: options.metadata
319
+ };
320
+ }
321
+ function searchMessagesOptions(options) {
322
+ return {
323
+ limit: options.limit,
324
+ sessionId: options.scope?.sessionId,
325
+ conversationId: options.scope?.sessionId,
326
+ threshold: options.minScore,
327
+ metadata: options.metadata
328
+ };
329
+ }
330
+ function searchEntitiesOptions(options) {
331
+ return {
332
+ limit: options.limit,
333
+ type: options.metadata?.type
334
+ };
335
+ }
336
+ function searchPreferencesOptions(options) {
337
+ return {
338
+ limit: options.limit,
339
+ category: options.metadata?.category
340
+ };
341
+ }
342
+ function similarTracesOptions(options) {
343
+ return {
344
+ limit: options.limit,
345
+ sessionId: options.scope?.sessionId,
346
+ successOnly: options.metadata?.successOnly
347
+ };
348
+ }
349
+ function neo4jWriteOptions(input) {
350
+ return {
351
+ user_identifier: input.scope?.userId,
352
+ userIdentifier: input.scope?.userId,
353
+ session_id: input.scope?.sessionId,
354
+ sessionId: input.scope?.sessionId,
355
+ namespace: input.scope?.namespace,
356
+ confidence: input.confidence,
357
+ metadata: input.metadata
358
+ };
359
+ }
360
+ function neo4jEntityOptions(input) {
361
+ return {
362
+ description: input.metadata?.description ?? input.title
363
+ };
364
+ }
365
+ function neo4jPreferenceOptions(input) {
366
+ return {
367
+ context: input.metadata?.context ?? input.title
368
+ };
369
+ }
370
+ async function callOptional(target, names, args) {
371
+ for (const name of names) {
372
+ const fn = target[name];
373
+ if (typeof fn === "function") return await fn.apply(target, args);
374
+ }
375
+ return void 0;
376
+ }
377
+ async function callRequired(target, names, args) {
378
+ const result = await callOptional(target, names, args);
379
+ if (result !== void 0) return result;
380
+ throw new Error(`Neo4j agent-memory client is missing method ${names.join(" or ")}`);
381
+ }
382
+ function nested(target, names, fallback) {
383
+ for (const name of names) {
384
+ const value = target[name];
385
+ if (value && typeof value === "object") return value;
386
+ }
387
+ return fallback;
388
+ }
389
+ function normalizeHits(value, options, adapterId) {
390
+ const rawHits = rawHitsFrom(value);
391
+ return rawHits.map((hit, index) => normalizeHit(hit, index, adapterId)).filter((hit) => hit !== null).filter(
392
+ (hit) => options.minScore === void 0 ? true : (hit.normalizedScore ?? hit.score ?? 0) >= options.minScore
393
+ ).filter((hit) => options.kinds?.length ? options.kinds.includes(hit.kind) : true).slice(0, options.limit);
394
+ }
395
+ function normalizeHit(value, index, adapterId) {
396
+ if (typeof value === "string") {
397
+ return {
398
+ id: stableId("mem", value),
399
+ uri: `memory://${adapterId}/${stableId("mem", value)}`,
400
+ kind: "fact",
401
+ text: value,
402
+ normalizedScore: index === 0 ? 1 : void 0
403
+ };
404
+ }
405
+ const obj = record(value);
406
+ if (!obj) return null;
407
+ const kind = memoryKind(stringField(obj, ["kind", "type", "label"]), obj);
408
+ const text = textFromHitObject(obj, kind);
409
+ if (!text) return null;
410
+ const id = stringField(obj, ["id", "memoryId", "uuid"]) ?? stableId("mem", text);
411
+ return {
412
+ id,
413
+ uri: stringField(obj, ["uri"]) ?? `memory://${adapterId}/${encodeURIComponent(id)}`,
414
+ kind,
415
+ text,
416
+ title: stringField(obj, ["title", "name", "task", "subject"]),
417
+ score: numberField(obj, ["score"]),
418
+ normalizedScore: numberField(obj, ["normalizedScore", "normalized_score"]),
419
+ confidence: numberField(obj, ["confidence"]),
420
+ createdAt: stringField(obj, ["createdAt", "created_at"]),
421
+ validUntil: stringField(obj, ["validUntil", "valid_until"]),
422
+ lastVerifiedAt: stringField(obj, ["lastVerifiedAt", "last_verified_at"]),
423
+ metadata: obj
424
+ };
425
+ }
426
+ function memoryKind(value, obj = {}) {
427
+ if (value === "message" || value === "entity" || value === "fact" || value === "preference" || value === "observation" || value === "reasoning-trace") {
428
+ return value;
429
+ }
430
+ if ("role" in obj && "content" in obj) return "message";
431
+ if ("name" in obj && ("type" in obj || "entityType" in obj)) return "entity";
432
+ if ("preference" in obj && "category" in obj) return "preference";
433
+ if ("task" in obj && "steps" in obj) return "reasoning-trace";
434
+ return "fact";
435
+ }
436
+ function rawHitsFrom(value) {
437
+ if (Array.isArray(value)) return value;
438
+ const obj = record(value);
439
+ if (!obj) return typeof value === "string" ? [value] : [];
440
+ if (Array.isArray(obj.hits)) return obj.hits;
441
+ if (Array.isArray(obj.results)) return obj.results;
442
+ if (Array.isArray(obj.messages)) return obj.messages;
443
+ if (Array.isArray(obj.recentMessages)) return obj.recentMessages;
444
+ if (Array.isArray(obj.observations)) return obj.observations;
445
+ if (Array.isArray(obj.reflections)) return obj.reflections;
446
+ if (typeof obj.content === "string" || typeof obj.text === "string") return [obj];
447
+ return [];
448
+ }
449
+ function textFromHitObject(obj, kind) {
450
+ const direct = stringField(obj, [
451
+ "text",
452
+ "content",
453
+ "body",
454
+ "summary",
455
+ "preference",
456
+ "description"
457
+ ]);
458
+ if (direct) return direct;
459
+ if (kind === "entity") return stringField(obj, ["name"]);
460
+ if (kind === "fact") {
461
+ const subject = stringField(obj, ["subject"]);
462
+ const predicate = stringField(obj, ["predicate"]);
463
+ const object = stringField(obj, ["object", "obj"]);
464
+ if (subject && predicate && object) return `${subject} ${predicate} ${object}`;
465
+ }
466
+ if (kind === "reasoning-trace") {
467
+ const task = stringField(obj, ["task"]);
468
+ const outcome = stringField(obj, ["outcome"]);
469
+ return [task, outcome].filter(Boolean).join("\n") || void 0;
470
+ }
471
+ return void 0;
472
+ }
473
+ function textFromConversationContext(value) {
474
+ const obj = record(value);
475
+ if (!obj) return void 0;
476
+ const parts = [
477
+ ...rawHitsFrom(obj.reflections).map((hit) => normalizeContextPart(hit)),
478
+ ...rawHitsFrom(obj.observations).map((hit) => normalizeContextPart(hit)),
479
+ ...rawHitsFrom(obj.recentMessages).map((hit) => normalizeContextPart(hit))
480
+ ].filter(Boolean);
481
+ return parts.length > 0 ? parts.join("\n\n") : void 0;
482
+ }
483
+ function normalizeConversationContextHits(value, options, adapterId) {
484
+ const obj = record(value);
485
+ if (!obj) return normalizeHits(value, options, adapterId);
486
+ const raw = [
487
+ ...rawHitsFrom(obj.reflections).map((hit) => tagContextHit(hit, "observation", "Reflection")),
488
+ ...rawHitsFrom(obj.observations).map((hit) => tagContextHit(hit, "observation", "Observation")),
489
+ ...rawHitsFrom(obj.recentMessages).map((hit) => tagContextHit(hit, "message"))
490
+ ];
491
+ return raw.length > 0 ? normalizeHits(raw, options, adapterId) : normalizeHits(value, options, adapterId);
492
+ }
493
+ function tagContextHit(value, kind, title) {
494
+ return value && typeof value === "object" && !Array.isArray(value) ? { kind, title, ...value } : { kind, title, content: value };
495
+ }
496
+ function normalizeContextPart(value) {
497
+ if (typeof value === "string") return value;
498
+ const obj = record(value);
499
+ return obj ? textFromHitObject(obj, memoryKind(stringField(obj, ["kind", "type", "label"]), obj)) : void 0;
500
+ }
501
+ function renderHits(hits) {
502
+ return hits.map((hit) => hit.text).join("\n\n");
503
+ }
504
+ function idFromResult(value) {
505
+ const obj = record(value);
506
+ return obj ? stringField(obj, ["id", "memoryId", "uuid"]) : void 0;
507
+ }
508
+ function record(value) {
509
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
510
+ }
511
+ function stringField(obj, names) {
512
+ for (const name of names) {
513
+ const value = obj[name];
514
+ if (typeof value === "string" && value.length > 0) return value;
515
+ }
516
+ return void 0;
517
+ }
518
+ function numberField(obj, names) {
519
+ for (const name of names) {
520
+ const value = obj[name];
521
+ if (typeof value === "number" && Number.isFinite(value)) return value;
522
+ }
523
+ return void 0;
524
+ }
525
+
526
+ // src/memory/schemas.ts
527
+ import { z } from "zod";
528
+ var AgentMemoryKindSchema = z.enum([
529
+ "message",
530
+ "entity",
531
+ "fact",
532
+ "preference",
533
+ "observation",
534
+ "reasoning-trace"
535
+ ]);
536
+ var AgentMemoryScopeSchema = z.object({
537
+ tenantId: z.string().optional(),
538
+ userId: z.string().optional(),
539
+ sessionId: z.string().optional(),
540
+ namespace: z.string().optional(),
541
+ tags: z.record(z.string(), z.string()).optional()
542
+ });
543
+ var AgentMemoryHitSchema = z.object({
544
+ id: z.string().min(1),
545
+ uri: z.string().min(1),
546
+ kind: AgentMemoryKindSchema,
547
+ text: z.string().min(1),
548
+ title: z.string().optional(),
549
+ score: z.number().optional(),
550
+ normalizedScore: z.number().optional(),
551
+ confidence: z.number().optional(),
552
+ createdAt: z.string().optional(),
553
+ validUntil: z.string().optional(),
554
+ lastVerifiedAt: z.string().optional(),
555
+ metadata: z.record(z.string(), z.unknown()).optional()
556
+ });
557
+ var AgentMemoryWriteInputSchema = z.object({
558
+ kind: AgentMemoryKindSchema,
559
+ text: z.string().min(1),
560
+ id: z.string().optional(),
561
+ title: z.string().optional(),
562
+ role: z.enum(["system", "user", "assistant", "tool"]).optional(),
563
+ entityName: z.string().optional(),
564
+ entityType: z.string().optional(),
565
+ category: z.string().optional(),
566
+ predicate: z.string().optional(),
567
+ subject: z.string().optional(),
568
+ object: z.string().optional(),
569
+ confidence: z.number().min(0).max(1).optional(),
570
+ scope: AgentMemoryScopeSchema.optional(),
571
+ metadata: z.record(z.string(), z.unknown()).optional()
572
+ });
573
+
574
+ export {
575
+ memoryHitToSourceRecord,
576
+ memoryWriteResultToSourceRecord,
577
+ defaultGetMemoryContext,
578
+ renderMemoryContext,
579
+ createNeo4jAgentMemoryAdapter,
580
+ AgentMemoryKindSchema,
581
+ AgentMemoryScopeSchema,
582
+ AgentMemoryHitSchema,
583
+ AgentMemoryWriteInputSchema
584
+ };
585
+ //# sourceMappingURL=chunk-U6KQ4FS3.js.map