@easynet/agent-memory 1.0.34 → 1.0.36
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 +1 -1
- package/dist/src/config/index.js +10 -18
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/ref.js +3 -8
- package/dist/src/config/ref.js.map +1 -1
- package/dist/src/core/agent-memory.d.ts +2 -0
- package/dist/src/core/agent-memory.d.ts.map +1 -1
- package/dist/src/core/agent-memory.js +71 -20
- package/dist/src/core/agent-memory.js.map +1 -1
- package/dist/src/core/config.js +5 -9
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/observability.js +2 -7
- package/dist/src/core/observability.js.map +1 -1
- package/dist/src/core/policy.js +3 -7
- package/dist/src/core/policy.js.map +1 -1
- package/dist/src/core/privacy.js +1 -5
- package/dist/src/core/privacy.js.map +1 -1
- package/dist/src/core/router.js +1 -5
- package/dist/src/core/router.js.map +1 -1
- package/dist/src/core/types.d.ts +1 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js +7 -12
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/create-agent-memory.d.ts +33 -1
- package/dist/src/create-agent-memory.d.ts.map +1 -1
- package/dist/src/create-agent-memory.helpers.js +14 -21
- package/dist/src/create-agent-memory.helpers.js.map +1 -1
- package/dist/src/create-agent-memory.js +166 -51
- package/dist/src/create-agent-memory.js.map +1 -1
- package/dist/src/index.d.ts +3 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -14
- package/dist/src/index.js.map +1 -1
- package/dist/src/ingest/common-ingest.d.ts +2 -2
- package/dist/src/ingest/common-ingest.d.ts.map +1 -1
- package/dist/src/ingest/common-ingest.js +2 -6
- package/dist/src/ingest/common-ingest.js.map +1 -1
- package/dist/src/ingest/compat-loaders.js +1 -4
- package/dist/src/ingest/compat-loaders.js.map +1 -1
- package/dist/src/ingest/index.js +2 -7
- package/dist/src/ingest/index.js.map +1 -1
- package/dist/src/ingest/pdf-ingest.js +4 -7
- package/dist/src/ingest/pdf-ingest.js.map +1 -1
- package/dist/src/ingest/url-ingest.d.ts +3 -2
- package/dist/src/ingest/url-ingest.d.ts.map +1 -1
- package/dist/src/ingest/url-ingest.js +148 -18
- package/dist/src/ingest/url-ingest.js.map +1 -1
- package/dist/src/integrations/deepagents-adapter.js +2 -6
- package/dist/src/integrations/deepagents-adapter.js.map +1 -1
- package/dist/src/integrations/langgraph.js +2 -6
- package/dist/src/integrations/langgraph.js.map +1 -1
- package/dist/src/internal.d.ts +7 -0
- package/dist/src/internal.d.ts.map +1 -0
- package/dist/src/internal.js +6 -0
- package/dist/src/internal.js.map +1 -0
- package/dist/src/providers/in-memory-store.js +3 -7
- package/dist/src/providers/in-memory-store.js.map +1 -1
- package/dist/src/providers/index.js +5 -14
- package/dist/src/providers/index.js.map +1 -1
- package/dist/src/providers/mem0-provider.js +3 -7
- package/dist/src/providers/mem0-provider.js.map +1 -1
- package/dist/src/providers/optional-ctors.js +2 -6
- package/dist/src/providers/optional-ctors.js.map +1 -1
- package/dist/src/providers/rag-provider.js +1 -5
- package/dist/src/providers/rag-provider.js.map +1 -1
- package/dist/src/providers/sqlite-store.js +3 -7
- package/dist/src/providers/sqlite-store.js.map +1 -1
- package/dist/src/register-memory.d.ts +16 -0
- package/dist/src/register-memory.d.ts.map +1 -0
- package/dist/src/register-memory.js +18 -0
- package/dist/src/register-memory.js.map +1 -0
- package/dist/test/core/agent-memory.test.js +76 -45
- package/dist/test/core/agent-memory.test.js.map +1 -1
- package/dist/test/core/config.test.js +114 -119
- package/dist/test/core/config.test.js.map +1 -1
- package/dist/test/core/observability.test.js +20 -25
- package/dist/test/core/observability.test.js.map +1 -1
- package/dist/test/core/policy.test.js +27 -32
- package/dist/test/core/policy.test.js.map +1 -1
- package/dist/test/core/privacy.test.js +24 -29
- package/dist/test/core/privacy.test.js.map +1 -1
- package/dist/test/core/router.test.js +25 -30
- package/dist/test/core/router.test.js.map +1 -1
- package/dist/test/create-agent-memory.test.js +102 -78
- package/dist/test/create-agent-memory.test.js.map +1 -1
- package/dist/test/ingest/url-ingest.test.js +64 -69
- package/dist/test/ingest/url-ingest.test.js.map +1 -1
- package/dist/test/integration/agent-memory-flow.test.js +22 -27
- package/dist/test/integration/agent-memory-flow.test.js.map +1 -1
- package/dist/test/integration/helpers/ollama-live.js +2 -6
- package/dist/test/integration/helpers/ollama-live.js.map +1 -1
- package/dist/test/integration/real-memory-features.test.js +46 -51
- package/dist/test/integration/real-memory-features.test.js.map +1 -1
- package/dist/test/integration/url-ingest-flow.test.js +22 -27
- package/dist/test/integration/url-ingest-flow.test.js.map +1 -1
- package/dist/test/integration/vlm-llm-live.test.js +54 -59
- package/dist/test/integration/vlm-llm-live.test.js.map +1 -1
- package/dist/test/providers/in-memory-store.test.js +16 -21
- package/dist/test/providers/in-memory-store.test.js.map +1 -1
- package/dist/test/providers/mem0-provider.test.js +19 -24
- package/dist/test/providers/mem0-provider.test.js.map +1 -1
- package/dist/test/providers/rag-provider.test.js +27 -32
- package/dist/test/providers/rag-provider.test.js.map +1 -1
- package/dist/test/providers/sqlite-store.test.js +29 -34
- package/dist/test/providers/sqlite-store.test.js.map +1 -1
- package/package.json +4 -3
|
@@ -1,141 +1,136 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const node_crypto_1 = require("node:crypto");
|
|
12
|
-
const agent_memory_js_1 = require("../../src/core/agent-memory.js");
|
|
13
|
-
const router_js_1 = require("../../src/core/router.js");
|
|
14
|
-
const in_memory_store_js_1 = require("../../src/providers/in-memory-store.js");
|
|
15
|
-
const url_ingest_js_1 = require("../../src/ingest/url-ingest.js");
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { writeFile, mkdir, rm } from "node:fs/promises";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { AgentMemory } from "../../src/core/agent-memory.js";
|
|
8
|
+
import { MemoryRouter } from "../../src/core/router.js";
|
|
9
|
+
import { InMemoryStoreProvider } from "../../src/providers/in-memory-store.js";
|
|
10
|
+
import { ingestUrlToMemory } from "../../src/ingest/url-ingest.js";
|
|
16
11
|
function makeTestMemory() {
|
|
17
|
-
const provider = new
|
|
18
|
-
const router = new
|
|
12
|
+
const provider = new InMemoryStoreProvider();
|
|
13
|
+
const router = new MemoryRouter({
|
|
19
14
|
providers: new Map([["default", provider]]),
|
|
20
15
|
defaultProviderId: "default",
|
|
21
16
|
});
|
|
22
|
-
return new
|
|
17
|
+
return new AgentMemory({ router });
|
|
23
18
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const dir =
|
|
27
|
-
await
|
|
28
|
-
const filePath =
|
|
19
|
+
describe("ingestUrlToMemory", () => {
|
|
20
|
+
it("ingests local txt file and memorizes chunks", async () => {
|
|
21
|
+
const dir = join(tmpdir(), `agent-memory-ingest-${randomUUID()}`);
|
|
22
|
+
await mkdir(dir, { recursive: true });
|
|
23
|
+
const filePath = join(dir, "doc.txt");
|
|
29
24
|
const content = "First paragraph.\n\nSecond paragraph.\n\nThird.";
|
|
30
|
-
await
|
|
25
|
+
await writeFile(filePath, content, "utf-8");
|
|
31
26
|
const memory = makeTestMemory();
|
|
32
27
|
try {
|
|
33
|
-
const { count, firstItem } = await
|
|
28
|
+
const { count, firstItem } = await ingestUrlToMemory(memory, {
|
|
34
29
|
url: filePath,
|
|
35
30
|
namespace: "test",
|
|
36
31
|
chunkSize: 50,
|
|
37
32
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
assert.ok(count >= 1);
|
|
34
|
+
assert.ok(firstItem?.id);
|
|
35
|
+
assert.strictEqual(firstItem?.type, "knowledge");
|
|
41
36
|
const result = await memory.recall({
|
|
42
37
|
namespace: "test",
|
|
43
38
|
query: "paragraph",
|
|
44
39
|
topK: 10,
|
|
45
40
|
});
|
|
46
|
-
|
|
41
|
+
assert.ok(result.items.length >= 1);
|
|
47
42
|
}
|
|
48
43
|
finally {
|
|
49
|
-
await
|
|
44
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
50
45
|
}
|
|
51
46
|
});
|
|
52
|
-
|
|
53
|
-
const dir =
|
|
54
|
-
await
|
|
55
|
-
const filePath =
|
|
56
|
-
await
|
|
47
|
+
it("ingests HTML and strips tags", async () => {
|
|
48
|
+
const dir = join(tmpdir(), `agent-memory-html-${randomUUID()}`);
|
|
49
|
+
await mkdir(dir, { recursive: true });
|
|
50
|
+
const filePath = join(dir, "page.html");
|
|
51
|
+
await writeFile(filePath, "<html><body><script>ignore</script><p>Visible text</p></body></html>", "utf-8");
|
|
57
52
|
const memory = makeTestMemory();
|
|
58
53
|
try {
|
|
59
|
-
const { count, firstItem } = await
|
|
54
|
+
const { count, firstItem } = await ingestUrlToMemory(memory, {
|
|
60
55
|
url: filePath,
|
|
61
56
|
namespace: "test",
|
|
62
57
|
chunkSize: 500,
|
|
63
58
|
});
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
assert.ok(count >= 1);
|
|
60
|
+
assert.ok(firstItem);
|
|
66
61
|
const result = await memory.recall({
|
|
67
62
|
namespace: "test",
|
|
68
63
|
query: "Visible",
|
|
69
64
|
topK: 5,
|
|
70
65
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
assert.strictEqual(result.items.length, 1);
|
|
67
|
+
assert.ok(result.items[0].content.includes("Visible text"));
|
|
68
|
+
assert.ok(!result.items[0].content.includes("<script>"));
|
|
74
69
|
}
|
|
75
70
|
finally {
|
|
76
|
-
await
|
|
71
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
77
72
|
}
|
|
78
73
|
});
|
|
79
|
-
|
|
80
|
-
const dir =
|
|
81
|
-
await
|
|
82
|
-
const filePath =
|
|
83
|
-
await
|
|
74
|
+
it("uses captionFn for image when provided", async () => {
|
|
75
|
+
const dir = join(tmpdir(), `agent-memory-img-${randomUUID()}`);
|
|
76
|
+
await mkdir(dir, { recursive: true });
|
|
77
|
+
const filePath = join(dir, "fake.png");
|
|
78
|
+
await writeFile(filePath, "not a real png", "utf-8");
|
|
84
79
|
const memory = makeTestMemory();
|
|
85
80
|
const captionFn = async (_buffer) => "Caption for image";
|
|
86
81
|
try {
|
|
87
|
-
const { count, firstItem } = await
|
|
82
|
+
const { count, firstItem } = await ingestUrlToMemory(memory, {
|
|
88
83
|
url: filePath,
|
|
89
84
|
namespace: "test",
|
|
90
85
|
captionFn,
|
|
91
86
|
chunkSize: 500,
|
|
92
87
|
});
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
assert.ok(count >= 1);
|
|
89
|
+
assert.strictEqual(firstItem?.content, "Caption for image");
|
|
95
90
|
}
|
|
96
91
|
finally {
|
|
97
|
-
await
|
|
92
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
98
93
|
}
|
|
99
94
|
});
|
|
100
|
-
|
|
101
|
-
const dir =
|
|
102
|
-
await
|
|
103
|
-
const filePath =
|
|
104
|
-
await
|
|
95
|
+
it("uses placeholder when image and no captionFn", async () => {
|
|
96
|
+
const dir = join(tmpdir(), `agent-memory-img2-${randomUUID()}`);
|
|
97
|
+
await mkdir(dir, { recursive: true });
|
|
98
|
+
const filePath = join(dir, "x.png");
|
|
99
|
+
await writeFile(filePath, "x", "utf-8");
|
|
105
100
|
const memory = makeTestMemory();
|
|
106
101
|
try {
|
|
107
|
-
const { count, firstItem } = await
|
|
102
|
+
const { count, firstItem } = await ingestUrlToMemory(memory, {
|
|
108
103
|
url: filePath,
|
|
109
104
|
namespace: "test",
|
|
110
105
|
chunkSize: 500,
|
|
111
106
|
});
|
|
112
|
-
|
|
113
|
-
|
|
107
|
+
assert.ok(count >= 1);
|
|
108
|
+
assert.ok(firstItem?.content.startsWith("(image:"));
|
|
114
109
|
}
|
|
115
110
|
finally {
|
|
116
|
-
await
|
|
111
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
117
112
|
}
|
|
118
113
|
});
|
|
119
|
-
|
|
120
|
-
const dir =
|
|
121
|
-
await
|
|
114
|
+
it("detects image by magic bytes when path has no extension (e.g. upload temp file)", async () => {
|
|
115
|
+
const dir = join(tmpdir(), `agent-memory-img3-${randomUUID()}`);
|
|
116
|
+
await mkdir(dir, { recursive: true });
|
|
122
117
|
const minimalPng = Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==", "base64");
|
|
123
|
-
const filePath =
|
|
124
|
-
await
|
|
118
|
+
const filePath = join(dir, "upload-temp-no-ext");
|
|
119
|
+
await writeFile(filePath, minimalPng);
|
|
125
120
|
const captionFn = async (_buffer) => "Caption for image";
|
|
126
121
|
const memory = makeTestMemory();
|
|
127
122
|
try {
|
|
128
|
-
const { count, firstItem } = await
|
|
123
|
+
const { count, firstItem } = await ingestUrlToMemory(memory, {
|
|
129
124
|
url: filePath,
|
|
130
125
|
namespace: "test",
|
|
131
126
|
chunkSize: 500,
|
|
132
127
|
captionFn,
|
|
133
128
|
});
|
|
134
|
-
|
|
135
|
-
|
|
129
|
+
assert.strictEqual(count, 1, "image should produce exactly one caption, not many chunks");
|
|
130
|
+
assert.strictEqual(firstItem?.content, "Caption for image");
|
|
136
131
|
}
|
|
137
132
|
finally {
|
|
138
|
-
await
|
|
133
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
139
134
|
}
|
|
140
135
|
});
|
|
141
136
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-ingest.test.js","sourceRoot":"","sources":["../../../test/ingest/url-ingest.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"url-ingest.test.js","sourceRoot":"","sources":["../../../test/ingest/url-ingest.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,36 +1,31 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Integration tests: full createAgentMemory → memorize → recall flow.
|
|
4
3
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const create_agent_memory_js_1 = require("../../src/create-agent-memory.js");
|
|
12
|
-
(0, node_test_1.describe)("createAgentMemory integration", () => {
|
|
13
|
-
(0, node_test_1.it)("createAgentMemory with config: memorize and recall", async () => {
|
|
14
|
-
const memoryRegistry = await (0, create_agent_memory_js_1.createAgentMemoryRegistry)({
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
import assert from "node:assert";
|
|
6
|
+
import { createAgentMemoryRegistry } from "../../src/create-agent-memory.js";
|
|
7
|
+
describe("createAgentMemory integration", () => {
|
|
8
|
+
it("createAgentMemory with config: memorize and recall", async () => {
|
|
9
|
+
const memoryRegistry = await createAgentMemoryRegistry({
|
|
15
10
|
config: {
|
|
16
11
|
stores: [{ id: "default", type: "in_memory" }],
|
|
17
12
|
},
|
|
18
13
|
});
|
|
19
14
|
const memory = await memoryRegistry.getAgentMemory();
|
|
20
15
|
const item = await memory.memorize("user:1", "cross_thread", "User prefers dark mode.");
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
assert.ok(item.id);
|
|
17
|
+
assert.strictEqual(item.content, "User prefers dark mode.");
|
|
18
|
+
assert.strictEqual(item.type, "cross_thread");
|
|
24
19
|
const result = await memory.recall({
|
|
25
20
|
namespace: "user:1",
|
|
26
21
|
query: "user preferences",
|
|
27
22
|
topK: 5,
|
|
28
23
|
});
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
assert.strictEqual(result.items.length, 1);
|
|
25
|
+
assert.strictEqual(result.items[0].content, "User prefers dark mode.");
|
|
31
26
|
});
|
|
32
|
-
|
|
33
|
-
const memoryRegistry = await
|
|
27
|
+
it("recall returns formatted items", async () => {
|
|
28
|
+
const memoryRegistry = await createAgentMemoryRegistry({
|
|
34
29
|
config: {
|
|
35
30
|
stores: [{ id: "default", type: "in_memory" }],
|
|
36
31
|
},
|
|
@@ -42,27 +37,27 @@ const create_agent_memory_js_1 = require("../../src/create-agent-memory.js");
|
|
|
42
37
|
query: "API",
|
|
43
38
|
topK: 5,
|
|
44
39
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
assert.ok(result.traceId);
|
|
41
|
+
assert.ok(result.injectedText.includes("knowledge"));
|
|
42
|
+
assert.strictEqual(result.items.length, 1);
|
|
43
|
+
assert.strictEqual(result.items[0].content, "API docs: GET /users returns list.");
|
|
49
44
|
});
|
|
50
|
-
|
|
51
|
-
const memoryRegistry = await
|
|
45
|
+
it("memorize and recall", async () => {
|
|
46
|
+
const memoryRegistry = await createAgentMemoryRegistry({
|
|
52
47
|
config: {
|
|
53
48
|
stores: [{ id: "default", type: "in_memory" }],
|
|
54
49
|
},
|
|
55
50
|
});
|
|
56
51
|
const memory = await memoryRegistry.getAgentMemory();
|
|
57
52
|
const item = await memory.memorize("user:1", "cross_thread", "Legacy write.");
|
|
58
|
-
|
|
53
|
+
assert.ok(item.id);
|
|
59
54
|
const result = await memory.recall({
|
|
60
55
|
namespace: "user:1",
|
|
61
56
|
query: "any",
|
|
62
57
|
topK: 5,
|
|
63
58
|
});
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
assert.strictEqual(result.items.length, 1);
|
|
60
|
+
assert.strictEqual(result.items[0].content, "Legacy write.");
|
|
66
61
|
});
|
|
67
62
|
});
|
|
68
63
|
//# sourceMappingURL=agent-memory-flow.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-memory-flow.test.js","sourceRoot":"","sources":["../../../test/integration/agent-memory-flow.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-memory-flow.test.js","sourceRoot":"","sources":["../../../test/integration/agent-memory-flow.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Helpers for live integration tests: call real Ollama VLM (caption) and LLM (classify).
|
|
4
3
|
* Used only when RUN_LIVE_INTEGRATION=1; no use-case hardcoding.
|
|
5
4
|
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.createOllamaCaptionFn = createOllamaCaptionFn;
|
|
8
|
-
exports.createOllamaClassifyMemoryFn = createOllamaClassifyMemoryFn;
|
|
9
5
|
const MEMORY_TYPES = ["thread", "cross_thread", "knowledge"];
|
|
10
6
|
/** Normalize base URL (no trailing slash) for fetch. */
|
|
11
7
|
function baseUrl(url) {
|
|
@@ -68,7 +64,7 @@ async function ollamaChatWithImage(baseUrlStr, model, userPrompt, imagesBase64)
|
|
|
68
64
|
* Create a captionFn that calls the given Ollama VLM with the image buffer.
|
|
69
65
|
* Uses /api/chat with images (recommended for vision models like qwen3-vl).
|
|
70
66
|
*/
|
|
71
|
-
function createOllamaCaptionFn(vlmBaseUrl, model, prompt = "Describe this image in one short sentence.") {
|
|
67
|
+
export function createOllamaCaptionFn(vlmBaseUrl, model, prompt = "Describe this image in one short sentence.") {
|
|
72
68
|
return async (buffer) => {
|
|
73
69
|
const base64 = buffer.toString("base64");
|
|
74
70
|
const caption = await ollamaChatWithImage(vlmBaseUrl, model, prompt, [
|
|
@@ -81,7 +77,7 @@ function createOllamaCaptionFn(vlmBaseUrl, model, prompt = "Describe this image
|
|
|
81
77
|
* Create a classifyMemory callback that calls the given Ollama LLM to infer
|
|
82
78
|
* memory type (thread / cross_thread / knowledge). Returns one of the allowed types.
|
|
83
79
|
*/
|
|
84
|
-
function createOllamaClassifyMemoryFn(llmBaseUrl, model) {
|
|
80
|
+
export function createOllamaClassifyMemoryFn(llmBaseUrl, model) {
|
|
85
81
|
const systemPrompt = `You classify memory content into exactly one word: thread, cross_thread, or knowledge.
|
|
86
82
|
- thread: session-specific, ephemeral.
|
|
87
83
|
- cross_thread: user preferences, facts, cross-session.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama-live.js","sourceRoot":"","sources":["../../../../test/integration/helpers/ollama-live.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ollama-live.js","sourceRoot":"","sources":["../../../../test/integration/helpers/ollama-live.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Real backend integration tests.
|
|
4
3
|
*
|
|
@@ -8,26 +7,22 @@
|
|
|
8
7
|
* Optional mem0 live test:
|
|
9
8
|
* RUN_REAL_MEMORY_INTEGRATION=1 RUN_REAL_MEM0_INTEGRATION=1 AGENT_MEMORY_MEM0_CONFIG_JSON='{"vectorStore":{"provider":"qdrant","config":{"host":"localhost","port":6333}}}' pnpm -C agent-memory test:integration
|
|
10
9
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const node_crypto_1 = require("node:crypto");
|
|
21
|
-
const node_url_1 = require("node:url");
|
|
22
|
-
const create_agent_memory_js_1 = require("../../src/create-agent-memory.js");
|
|
23
|
-
const sqlite_store_js_1 = require("../../src/providers/sqlite-store.js");
|
|
10
|
+
import { describe, it } from "node:test";
|
|
11
|
+
import assert from "node:assert";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
import { randomUUID } from "node:crypto";
|
|
16
|
+
import { pathToFileURL } from "node:url";
|
|
17
|
+
import { createAgentMemoryRegistry } from "../../src/create-agent-memory.js";
|
|
18
|
+
import { SqliteStoreProvider } from "../../src/providers/sqlite-store.js";
|
|
24
19
|
const RUN_REAL = process.env.RUN_REAL_MEMORY_INTEGRATION === "1";
|
|
25
20
|
const RUN_REAL_MEM0 = process.env.RUN_REAL_MEM0_INTEGRATION === "1";
|
|
26
21
|
const MEM0_CONFIG_JSON = process.env.AGENT_MEMORY_MEM0_CONFIG_JSON;
|
|
27
22
|
const HAS_WORKING_SQLITE = (() => {
|
|
28
23
|
try {
|
|
29
24
|
// Use the same provider path as production runtime to verify sqlite is actually usable.
|
|
30
|
-
void new
|
|
25
|
+
void new SqliteStoreProvider({ dbPath: ":memory:" });
|
|
31
26
|
return true;
|
|
32
27
|
}
|
|
33
28
|
catch {
|
|
@@ -39,19 +34,19 @@ async function openDb(dbPath) {
|
|
|
39
34
|
return new Database(dbPath);
|
|
40
35
|
}
|
|
41
36
|
async function createTempDir(prefix) {
|
|
42
|
-
const dir =
|
|
43
|
-
await
|
|
37
|
+
const dir = join(tmpdir(), `${prefix}-${randomUUID()}`);
|
|
38
|
+
await mkdir(dir, { recursive: true });
|
|
44
39
|
return dir;
|
|
45
40
|
}
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
describe("real memory backends", { skip: !RUN_REAL }, () => {
|
|
42
|
+
it("sqlite: thread/cross_thread/knowledge persistence + key APIs", { skip: !HAS_WORKING_SQLITE }, async () => {
|
|
48
43
|
const dir = await createTempDir("agent-memory-real-sqlite");
|
|
49
|
-
const threadDb =
|
|
50
|
-
const crossDb =
|
|
51
|
-
const knowledgeDb =
|
|
52
|
-
const notePath =
|
|
53
|
-
await
|
|
54
|
-
const memoryRegistry = await
|
|
44
|
+
const threadDb = join(dir, "thread.sqlite");
|
|
45
|
+
const crossDb = join(dir, "cross.sqlite");
|
|
46
|
+
const knowledgeDb = join(dir, "knowledge.sqlite");
|
|
47
|
+
const notePath = join(dir, "guide.txt");
|
|
48
|
+
await writeFile(notePath, "TypeScript coding standards. Keep APIs small and explicit.", "utf8");
|
|
49
|
+
const memoryRegistry = await createAgentMemoryRegistry({
|
|
55
50
|
config: {
|
|
56
51
|
stores: {
|
|
57
52
|
thread: { id: "thread_sqlite", type: "sqlite", options: { dbPath: threadDb } },
|
|
@@ -73,7 +68,7 @@ async function createTempDir(prefix) {
|
|
|
73
68
|
key: "doc://stack",
|
|
74
69
|
source: "manual",
|
|
75
70
|
});
|
|
76
|
-
await memory.memorize("user:real", "knowledge",
|
|
71
|
+
await memory.memorize("user:real", "knowledge", pathToFileURL(notePath), {
|
|
77
72
|
key: "doc://guide",
|
|
78
73
|
source: "file",
|
|
79
74
|
});
|
|
@@ -83,13 +78,13 @@ async function createTempDir(prefix) {
|
|
|
83
78
|
types: ["thread", "cross_thread", "knowledge"],
|
|
84
79
|
topK: 20,
|
|
85
80
|
});
|
|
86
|
-
|
|
81
|
+
assert.ok(all.items.length >= 3, "should recall entries from all memory types");
|
|
87
82
|
const byKey = await memory.getByKey("user:real", "doc://stack");
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
assert.ok(byKey, "getByKey should return persisted knowledge item");
|
|
84
|
+
assert.strictEqual(byKey?.type, "knowledge");
|
|
90
85
|
await memory.deleteByKey("user:real", "doc://stack");
|
|
91
86
|
const deleted = await memory.getByKey("user:real", "doc://stack");
|
|
92
|
-
|
|
87
|
+
assert.strictEqual(deleted, null);
|
|
93
88
|
const threadCount = (await openDb(threadDb))
|
|
94
89
|
.prepare("SELECT COUNT(*) as c FROM memory_items WHERE namespace = ?")
|
|
95
90
|
.get("user:real").c;
|
|
@@ -99,9 +94,9 @@ async function createTempDir(prefix) {
|
|
|
99
94
|
const knowledgeCount = (await openDb(knowledgeDb))
|
|
100
95
|
.prepare("SELECT COUNT(*) as c FROM memory_items WHERE namespace = ?")
|
|
101
96
|
.get("user:real").c;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
assert.ok(threadCount >= 1, "thread sqlite DB should contain rows");
|
|
98
|
+
assert.ok(crossCount >= 1, "cross_thread sqlite DB should contain rows");
|
|
99
|
+
assert.ok(knowledgeCount >= 1, "knowledge sqlite DB should contain rows");
|
|
105
100
|
await memory.deleteByNamespace("user:real");
|
|
106
101
|
const afterDelete = await memory.recall({
|
|
107
102
|
namespace: "user:real",
|
|
@@ -109,21 +104,21 @@ async function createTempDir(prefix) {
|
|
|
109
104
|
types: ["thread", "cross_thread", "knowledge"],
|
|
110
105
|
topK: 20,
|
|
111
106
|
});
|
|
112
|
-
|
|
107
|
+
assert.strictEqual(afterDelete.items.length, 0);
|
|
113
108
|
}
|
|
114
109
|
finally {
|
|
115
|
-
await
|
|
110
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
116
111
|
}
|
|
117
112
|
});
|
|
118
|
-
|
|
113
|
+
it("thread compaction: writes summary into real sqlite", { skip: !HAS_WORKING_SQLITE }, async () => {
|
|
119
114
|
const dir = await createTempDir("agent-memory-real-compaction");
|
|
120
|
-
const threadDb =
|
|
121
|
-
const memoryRegistry = await
|
|
115
|
+
const threadDb = join(dir, "thread.sqlite");
|
|
116
|
+
const memoryRegistry = await createAgentMemoryRegistry({
|
|
122
117
|
config: {
|
|
123
118
|
stores: {
|
|
124
119
|
thread: { id: "thread_sqlite", type: "sqlite", options: { dbPath: threadDb } },
|
|
125
|
-
cross_thread: { id: "cross_sqlite", type: "sqlite", options: { dbPath:
|
|
126
|
-
knowledge: { id: "knowledge_sqlite", type: "sqlite", options: { dbPath:
|
|
120
|
+
cross_thread: { id: "cross_sqlite", type: "sqlite", options: { dbPath: join(dir, "cross.sqlite") } },
|
|
121
|
+
knowledge: { id: "knowledge_sqlite", type: "sqlite", options: { dbPath: join(dir, "knowledge.sqlite") } },
|
|
127
122
|
},
|
|
128
123
|
memory: {
|
|
129
124
|
thread: {
|
|
@@ -147,22 +142,22 @@ async function createTempDir(prefix) {
|
|
|
147
142
|
await memory.memorize("session:real", "thread", "A".repeat(40));
|
|
148
143
|
await memory.memorize("session:real", "thread", "B".repeat(40));
|
|
149
144
|
const summary = await memory.getByKey("session:real", "__summary__");
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
assert.ok(summary, "summary should be stored after compaction");
|
|
146
|
+
assert.strictEqual(summary?.type, "thread");
|
|
147
|
+
assert.strictEqual(summary?.content, "summary(1)");
|
|
153
148
|
const summaryCount = (await openDb(threadDb))
|
|
154
149
|
.prepare("SELECT COUNT(*) as c FROM memory_items WHERE namespace = ? AND path_key = ?")
|
|
155
150
|
.get("session:real", "__summary__").c;
|
|
156
|
-
|
|
151
|
+
assert.strictEqual(summaryCount, 1);
|
|
157
152
|
}
|
|
158
153
|
finally {
|
|
159
|
-
await
|
|
154
|
+
await rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
160
155
|
}
|
|
161
156
|
});
|
|
162
|
-
|
|
157
|
+
it("mem0 live: cross_thread write/query with real backend", { skip: !RUN_REAL_MEM0 || !MEM0_CONFIG_JSON }, async () => {
|
|
163
158
|
const { Memory } = (await import("mem0ai/oss"));
|
|
164
159
|
const mem0 = new Memory(JSON.parse(MEM0_CONFIG_JSON));
|
|
165
|
-
const memoryRegistry = await
|
|
160
|
+
const memoryRegistry = await createAgentMemoryRegistry({
|
|
166
161
|
config: {
|
|
167
162
|
stores: {
|
|
168
163
|
thread: { id: "thread_sqlite", type: "sqlite", options: { dbPath: ":memory:" } },
|
|
@@ -178,7 +173,7 @@ async function createTempDir(prefix) {
|
|
|
178
173
|
overrides: { mem0 },
|
|
179
174
|
});
|
|
180
175
|
const memory = await memoryRegistry.getAgentMemory();
|
|
181
|
-
const namespace = `user:mem0:${
|
|
176
|
+
const namespace = `user:mem0:${randomUUID()}`;
|
|
182
177
|
await memory.memorize(namespace, "cross_thread", "User prefers concise answers and markdown lists.");
|
|
183
178
|
const recalled = await memory.recall({
|
|
184
179
|
namespace,
|
|
@@ -186,8 +181,8 @@ async function createTempDir(prefix) {
|
|
|
186
181
|
types: ["cross_thread"],
|
|
187
182
|
topK: 5,
|
|
188
183
|
});
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
assert.ok(recalled.items.length >= 1, "mem0 recall should return at least one item");
|
|
185
|
+
assert.ok(recalled.items.some((item) => item.content.toLowerCase().includes("concise")), "mem0 recall should include inserted preference");
|
|
191
186
|
await memory.deleteByNamespace(namespace);
|
|
192
187
|
const afterDelete = await memory.recall({
|
|
193
188
|
namespace,
|
|
@@ -195,7 +190,7 @@ async function createTempDir(prefix) {
|
|
|
195
190
|
types: ["cross_thread"],
|
|
196
191
|
topK: 5,
|
|
197
192
|
});
|
|
198
|
-
|
|
193
|
+
assert.strictEqual(afterDelete.items.length, 0);
|
|
199
194
|
});
|
|
200
195
|
});
|
|
201
196
|
//# sourceMappingURL=real-memory-features.test.js.map
|