neo4j-agent-memory 0.3.17
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 +161 -0
- package/dist/cypher/feedback_batch.cypher +42 -0
- package/dist/cypher/feedback_co_used_with_batch.cypher +34 -0
- package/dist/cypher/index.ts +23 -0
- package/dist/cypher/list_memories.cypher +39 -0
- package/dist/cypher/relate_concepts.cypher +13 -0
- package/dist/cypher/retrieve_context_bundle.cypher +555 -0
- package/dist/cypher/schema.cypher +20 -0
- package/dist/cypher/upsert_case.cypher +61 -0
- package/dist/cypher/upsert_memory.cypher +38 -0
- package/dist/index.cjs +789 -0
- package/dist/index.d.ts +320 -0
- package/dist/index.js +738 -0
- package/package.json +49 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { Session } from 'neo4j-driver';
|
|
2
|
+
|
|
3
|
+
type MemoryKind = "semantic" | "procedural" | "episodic";
|
|
4
|
+
type MemoryPolarity = "positive" | "negative";
|
|
5
|
+
interface EnvironmentFingerprint {
|
|
6
|
+
hash?: string;
|
|
7
|
+
os?: "macos" | "linux" | "windows";
|
|
8
|
+
distro?: string;
|
|
9
|
+
ci?: string;
|
|
10
|
+
container?: boolean;
|
|
11
|
+
filesystem?: string;
|
|
12
|
+
workspaceMount?: "local" | "network" | "bind" | "readonly";
|
|
13
|
+
nodeVersion?: string;
|
|
14
|
+
packageManager?: "npm" | "pnpm" | "yarn";
|
|
15
|
+
pmVersion?: string;
|
|
16
|
+
}
|
|
17
|
+
interface DistilledInvariant {
|
|
18
|
+
invariant: string;
|
|
19
|
+
justification?: string;
|
|
20
|
+
verification?: string[];
|
|
21
|
+
applicability?: string[];
|
|
22
|
+
risks?: string[];
|
|
23
|
+
}
|
|
24
|
+
interface MemoryRecord {
|
|
25
|
+
id: string;
|
|
26
|
+
kind: MemoryKind;
|
|
27
|
+
polarity: MemoryPolarity;
|
|
28
|
+
title: string;
|
|
29
|
+
content: string;
|
|
30
|
+
tags: string[];
|
|
31
|
+
confidence: number;
|
|
32
|
+
utility: number;
|
|
33
|
+
createdAt?: string;
|
|
34
|
+
updatedAt?: string;
|
|
35
|
+
signals?: {
|
|
36
|
+
symptoms?: string[];
|
|
37
|
+
environment?: string[];
|
|
38
|
+
};
|
|
39
|
+
distilled?: {
|
|
40
|
+
invariants?: DistilledInvariant[];
|
|
41
|
+
steps?: string[];
|
|
42
|
+
verificationSteps?: string[];
|
|
43
|
+
gotchas?: string[];
|
|
44
|
+
};
|
|
45
|
+
antiPattern?: {
|
|
46
|
+
action: string;
|
|
47
|
+
whyBad: string;
|
|
48
|
+
saferAlternative?: string;
|
|
49
|
+
};
|
|
50
|
+
env?: EnvironmentFingerprint;
|
|
51
|
+
}
|
|
52
|
+
interface MemorySummary {
|
|
53
|
+
id: string;
|
|
54
|
+
kind: MemoryKind;
|
|
55
|
+
polarity: MemoryPolarity;
|
|
56
|
+
title: string;
|
|
57
|
+
tags: string[];
|
|
58
|
+
confidence: number;
|
|
59
|
+
utility: number;
|
|
60
|
+
createdAt?: string | null;
|
|
61
|
+
updatedAt?: string | null;
|
|
62
|
+
}
|
|
63
|
+
interface CaseRecord {
|
|
64
|
+
id: string;
|
|
65
|
+
title: string;
|
|
66
|
+
summary: string;
|
|
67
|
+
outcome: "resolved" | "unresolved" | "workaround";
|
|
68
|
+
symptoms: string[];
|
|
69
|
+
env: EnvironmentFingerprint;
|
|
70
|
+
resolvedByMemoryIds: string[];
|
|
71
|
+
negativeMemoryIds: string[];
|
|
72
|
+
resolvedAtIso?: string | null;
|
|
73
|
+
}
|
|
74
|
+
interface RetrieveContextArgs {
|
|
75
|
+
agentId: string;
|
|
76
|
+
prompt: string;
|
|
77
|
+
symptoms?: string[];
|
|
78
|
+
tags?: string[];
|
|
79
|
+
kinds?: MemoryKind[];
|
|
80
|
+
env?: EnvironmentFingerprint;
|
|
81
|
+
baseline?: Record<string, {
|
|
82
|
+
a: number;
|
|
83
|
+
b: number;
|
|
84
|
+
}>;
|
|
85
|
+
caseLimit?: number;
|
|
86
|
+
fixLimit?: number;
|
|
87
|
+
dontLimit?: number;
|
|
88
|
+
nowIso?: string;
|
|
89
|
+
}
|
|
90
|
+
interface ListMemoriesArgs {
|
|
91
|
+
kind?: MemoryKind;
|
|
92
|
+
limit?: number;
|
|
93
|
+
agentId?: string;
|
|
94
|
+
}
|
|
95
|
+
interface BetaEdge {
|
|
96
|
+
a: number;
|
|
97
|
+
b: number;
|
|
98
|
+
/** Posterior mean a/(a+b), cached for query speed */
|
|
99
|
+
strength: number;
|
|
100
|
+
/** Evidence mass a+b, cached for query speed */
|
|
101
|
+
evidence: number;
|
|
102
|
+
updatedAt: string | null;
|
|
103
|
+
}
|
|
104
|
+
type ContextMemoryBase = Pick<MemoryRecord, "id" | "kind" | "polarity" | "title" | "content" | "tags" | "confidence" | "utility" | "updatedAt">;
|
|
105
|
+
type ContextMemorySummary = ContextMemoryBase & {
|
|
106
|
+
/** Posterior snapshot before the current run (baseline) */
|
|
107
|
+
edgeBefore?: BetaEdge;
|
|
108
|
+
/** Posterior snapshot after the current run (undefined until feedback arrives) */
|
|
109
|
+
edgeAfter?: BetaEdge;
|
|
110
|
+
};
|
|
111
|
+
interface ContextBundle {
|
|
112
|
+
sessionId: string;
|
|
113
|
+
sections: {
|
|
114
|
+
fix: ContextMemorySummary[];
|
|
115
|
+
doNotDo: ContextMemorySummary[];
|
|
116
|
+
};
|
|
117
|
+
injection: {
|
|
118
|
+
fixBlock: string;
|
|
119
|
+
doNotDoBlock: string;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
interface FeedbackMetrics {
|
|
123
|
+
durationMs?: number;
|
|
124
|
+
quality?: number;
|
|
125
|
+
hallucinationRisk?: number;
|
|
126
|
+
toolCalls?: number;
|
|
127
|
+
verificationPassed?: boolean;
|
|
128
|
+
}
|
|
129
|
+
interface MemoryFeedback {
|
|
130
|
+
agentId: string;
|
|
131
|
+
sessionId: string;
|
|
132
|
+
usedIds: string[];
|
|
133
|
+
usefulIds: string[];
|
|
134
|
+
notUsefulIds: string[];
|
|
135
|
+
preventedErrorIds?: string[];
|
|
136
|
+
metrics?: FeedbackMetrics;
|
|
137
|
+
notes?: string;
|
|
138
|
+
}
|
|
139
|
+
interface CaptureEpisodeArgs {
|
|
140
|
+
agentId: string;
|
|
141
|
+
runId: string;
|
|
142
|
+
workflowName: string;
|
|
143
|
+
prompt: string;
|
|
144
|
+
response: string;
|
|
145
|
+
outcome?: "success" | "failure" | "partial" | "unknown";
|
|
146
|
+
tags?: string[];
|
|
147
|
+
}
|
|
148
|
+
interface CaptureStepEpisodeArgs extends CaptureEpisodeArgs {
|
|
149
|
+
stepName: string;
|
|
150
|
+
}
|
|
151
|
+
interface MemoryEvent {
|
|
152
|
+
type: "read" | "write";
|
|
153
|
+
action: string;
|
|
154
|
+
at: string;
|
|
155
|
+
meta?: Record<string, unknown>;
|
|
156
|
+
}
|
|
157
|
+
interface LearningCandidate {
|
|
158
|
+
kind: MemoryKind;
|
|
159
|
+
polarity?: MemoryPolarity;
|
|
160
|
+
title: string;
|
|
161
|
+
content: string;
|
|
162
|
+
tags: string[];
|
|
163
|
+
confidence: number;
|
|
164
|
+
signals?: MemoryRecord["signals"];
|
|
165
|
+
env?: EnvironmentFingerprint;
|
|
166
|
+
triage?: {
|
|
167
|
+
symptoms: string[];
|
|
168
|
+
likelyCauses: string[];
|
|
169
|
+
verificationSteps?: string[];
|
|
170
|
+
fixSteps?: string[];
|
|
171
|
+
gotchas?: string[];
|
|
172
|
+
};
|
|
173
|
+
antiPattern?: MemoryRecord["antiPattern"];
|
|
174
|
+
}
|
|
175
|
+
interface SaveLearningRequest {
|
|
176
|
+
agentId: string;
|
|
177
|
+
sessionId?: string;
|
|
178
|
+
taskId?: string;
|
|
179
|
+
learnings: LearningCandidate[];
|
|
180
|
+
policy?: {
|
|
181
|
+
minConfidence?: number;
|
|
182
|
+
requireVerificationSteps?: boolean;
|
|
183
|
+
maxItems?: number;
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
interface SaveLearningResult {
|
|
187
|
+
saved: Array<{
|
|
188
|
+
id: string;
|
|
189
|
+
kind: MemoryKind;
|
|
190
|
+
title: string;
|
|
191
|
+
deduped: boolean;
|
|
192
|
+
}>;
|
|
193
|
+
rejected: Array<{
|
|
194
|
+
title: string;
|
|
195
|
+
reason: string;
|
|
196
|
+
}>;
|
|
197
|
+
}
|
|
198
|
+
interface MemoryServiceConfig {
|
|
199
|
+
neo4j: {
|
|
200
|
+
uri: string;
|
|
201
|
+
username: string;
|
|
202
|
+
password: string;
|
|
203
|
+
database?: string;
|
|
204
|
+
};
|
|
205
|
+
vectorIndex?: string;
|
|
206
|
+
fulltextIndex?: string;
|
|
207
|
+
halfLifeSeconds?: number;
|
|
208
|
+
onMemoryEvent?: (event: MemoryEvent) => void;
|
|
209
|
+
}
|
|
210
|
+
type MemoryToolName = "store_skill" | "store_pattern" | "store_concept" | "relate_concepts" | "recall_skills" | "recall_concepts" | "recall_patterns";
|
|
211
|
+
interface MemoryToolDefinition<TInput, TResult> {
|
|
212
|
+
name: MemoryToolName;
|
|
213
|
+
description: string;
|
|
214
|
+
inputSchema?: unknown;
|
|
215
|
+
execute: (input: TInput) => Promise<TResult>;
|
|
216
|
+
}
|
|
217
|
+
type MemoryToolSet = Record<MemoryToolName, MemoryToolDefinition<any, any>>;
|
|
218
|
+
|
|
219
|
+
declare class MemoryService {
|
|
220
|
+
private client;
|
|
221
|
+
private vectorIndex;
|
|
222
|
+
private fulltextIndex;
|
|
223
|
+
private halfLifeSeconds;
|
|
224
|
+
private onMemoryEvent?;
|
|
225
|
+
private cyUpsertMemory;
|
|
226
|
+
private cyUpsertCase;
|
|
227
|
+
private cyRetrieveBundle;
|
|
228
|
+
private cyFeedbackBatch;
|
|
229
|
+
private cyFeedbackCoUsed;
|
|
230
|
+
private cyListMemories;
|
|
231
|
+
private cyRelateConcepts;
|
|
232
|
+
private cyGetRecallEdges;
|
|
233
|
+
constructor(cfg: MemoryServiceConfig);
|
|
234
|
+
init(): Promise<void>;
|
|
235
|
+
close(): Promise<void>;
|
|
236
|
+
private ensureEnvHash;
|
|
237
|
+
private emit;
|
|
238
|
+
/**
|
|
239
|
+
* Save a distilled memory (semantic/procedural/episodic) with exact dedupe by contentHash.
|
|
240
|
+
* NOTE: This package intentionally does not store "full answers" as semantic/procedural.
|
|
241
|
+
*/
|
|
242
|
+
upsertMemory(l: LearningCandidate & {
|
|
243
|
+
id?: string;
|
|
244
|
+
}): Promise<{
|
|
245
|
+
id: string;
|
|
246
|
+
deduped: boolean;
|
|
247
|
+
}>;
|
|
248
|
+
/**
|
|
249
|
+
* Upsert an episodic Case (case-based reasoning) that links symptoms + env + resolved_by + negative memories.
|
|
250
|
+
*/
|
|
251
|
+
upsertCase(c: CaseRecord): Promise<string>;
|
|
252
|
+
/**
|
|
253
|
+
* Retrieve a ContextBundle with separate Fix and Do-not-do sections, using case-based reasoning.
|
|
254
|
+
* The key idea: match cases by symptoms + env similarity, then pull linked memories.
|
|
255
|
+
*/
|
|
256
|
+
retrieveContextBundle(args: RetrieveContextArgs): Promise<ContextBundle>;
|
|
257
|
+
listMemories(args?: ListMemoriesArgs): Promise<MemorySummary[]>;
|
|
258
|
+
listEpisodes(args?: Omit<ListMemoriesArgs, "kind">): Promise<MemorySummary[]>;
|
|
259
|
+
listSkills(args?: Omit<ListMemoriesArgs, "kind">): Promise<MemorySummary[]>;
|
|
260
|
+
listConcepts(args?: Omit<ListMemoriesArgs, "kind">): Promise<MemorySummary[]>;
|
|
261
|
+
relateConcepts(args: {
|
|
262
|
+
sourceId: string;
|
|
263
|
+
targetId: string;
|
|
264
|
+
weight?: number;
|
|
265
|
+
}): Promise<void>;
|
|
266
|
+
captureEpisode(args: CaptureEpisodeArgs): Promise<SaveLearningResult>;
|
|
267
|
+
captureStepEpisode(args: CaptureStepEpisodeArgs): Promise<SaveLearningResult>;
|
|
268
|
+
/**
|
|
269
|
+
* Reinforce/degrade agent->memory association weights using a single batched Cypher query.
|
|
270
|
+
* This supports mid-run retrieval by making feedback cheap and frequent.
|
|
271
|
+
*/
|
|
272
|
+
feedback(fb: MemoryFeedback): Promise<void>;
|
|
273
|
+
/**
|
|
274
|
+
* Save distilled learnings discovered during a task.
|
|
275
|
+
* Enforces quality gates and stores negative memories explicitly.
|
|
276
|
+
* Automatically creates a Case if learnings have triage.symptoms.
|
|
277
|
+
*/
|
|
278
|
+
saveLearnings(req: SaveLearningRequest): Promise<SaveLearningResult>;
|
|
279
|
+
}
|
|
280
|
+
declare function createMemoryService(cfg: MemoryServiceConfig): Promise<MemoryService>;
|
|
281
|
+
|
|
282
|
+
interface Neo4jClientConfig {
|
|
283
|
+
uri: string;
|
|
284
|
+
username: string;
|
|
285
|
+
password: string;
|
|
286
|
+
database?: string;
|
|
287
|
+
}
|
|
288
|
+
declare class Neo4jClient {
|
|
289
|
+
private driver;
|
|
290
|
+
private database?;
|
|
291
|
+
constructor(cfg: Neo4jClientConfig);
|
|
292
|
+
session(mode?: "READ" | "WRITE"): Session;
|
|
293
|
+
close(): Promise<void>;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
declare const schemaVersion = 1;
|
|
297
|
+
declare function ensureSchema(client: Neo4jClient): Promise<void>;
|
|
298
|
+
declare function migrate(client: Neo4jClient, targetVersion?: number): Promise<void>;
|
|
299
|
+
|
|
300
|
+
declare function loadCypher(rel: string): string;
|
|
301
|
+
declare const cypher: {
|
|
302
|
+
schema: string;
|
|
303
|
+
upsertMemory: string;
|
|
304
|
+
upsertCase: string;
|
|
305
|
+
retrieveContextBundle: string;
|
|
306
|
+
feedbackBatch: string;
|
|
307
|
+
feedbackCoUsed: string;
|
|
308
|
+
listMemories: string;
|
|
309
|
+
relateConcepts: string;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
declare function createMemoryTools(service: MemoryService): MemoryToolSet;
|
|
313
|
+
|
|
314
|
+
declare function sha256Hex(s: string): string;
|
|
315
|
+
declare function canonicaliseForHash(title: string, content: string, tags: string[]): string;
|
|
316
|
+
declare function newId(prefix: string): string;
|
|
317
|
+
declare function normaliseSymptom(s: string): string;
|
|
318
|
+
declare function envHash(env: EnvironmentFingerprint): string;
|
|
319
|
+
|
|
320
|
+
export { type BetaEdge, type CaptureEpisodeArgs, type CaptureStepEpisodeArgs, type CaseRecord, type ContextBundle, type ContextMemoryBase, type ContextMemorySummary, type DistilledInvariant, type EnvironmentFingerprint, type FeedbackMetrics, type LearningCandidate, type ListMemoriesArgs, type MemoryEvent, type MemoryFeedback, type MemoryKind, type MemoryPolarity, type MemoryRecord, MemoryService, type MemoryServiceConfig, type MemorySummary, type MemoryToolDefinition, type MemoryToolName, type MemoryToolSet, Neo4jClient, type Neo4jClientConfig, type RetrieveContextArgs, type SaveLearningRequest, type SaveLearningResult, canonicaliseForHash, createMemoryService, createMemoryTools, cypher, ensureSchema, envHash, loadCypher, migrate, newId, normaliseSymptom, schemaVersion, sha256Hex };
|