memory-forge 0.3.13 → 0.4.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/dist/auto/index.d.ts +5 -3
- package/dist/auto/index.js +93 -54
- package/dist/auto/index.js.map +1 -1
- package/dist/embedding.js +13 -1
- package/dist/embedding.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +333 -64
- package/dist/index.js.map +1 -1
- package/dist/migrate/import.js +1 -14
- package/dist/migrate/import.js.map +1 -1
- package/dist/pro.d.ts +32 -0
- package/dist/pro.js +211 -25
- package/dist/pro.js.map +1 -1
- package/dist/scenario-test.d.ts +1 -0
- package/dist/scenario-test.js +177 -0
- package/dist/scenario-test.js.map +1 -0
- package/dist/setup.js +10 -4
- package/dist/setup.js.map +1 -1
- package/dist/storage/shelby.d.ts +21 -2
- package/dist/storage/shelby.js +103 -8
- package/dist/storage/shelby.js.map +1 -1
- package/dist/store.d.ts +11 -1
- package/dist/store.js +80 -9
- package/dist/store.js.map +1 -1
- package/dist/transcript.js +3 -1
- package/dist/transcript.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-world scenario tests — simulates actual user workflows.
|
|
3
|
+
*/
|
|
4
|
+
import { MemoryStore, contentOverlap } from "./store.js";
|
|
5
|
+
import { loadAllMemories } from "./storage/local.js";
|
|
6
|
+
import { autoName, generateContextSummary } from "./auto/index.js";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
let ok = 0;
|
|
11
|
+
let ng = 0;
|
|
12
|
+
function t(name, fn) { try {
|
|
13
|
+
fn();
|
|
14
|
+
ok++;
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
ng++;
|
|
18
|
+
console.log("FAIL:", name, "—", e.message);
|
|
19
|
+
} }
|
|
20
|
+
const now = new Date().toISOString();
|
|
21
|
+
// ═══ SCENARIO 1: Corrupted memory file ═══
|
|
22
|
+
console.log("=== Scenario 1: Corrupted memory file ===");
|
|
23
|
+
const corruptId = randomUUID();
|
|
24
|
+
const memDir = path.join(process.env.HOME ?? process.env.USERPROFILE ?? "/tmp", ".memory-forge", "memories");
|
|
25
|
+
const corruptPath = path.join(memDir, corruptId + ".md");
|
|
26
|
+
fs.mkdirSync(memDir, { recursive: true });
|
|
27
|
+
fs.writeFileSync(corruptPath, "NOT VALID MEMORY FILE\njust garbage\nno frontmatter");
|
|
28
|
+
t("corrupted file does not crash loader", () => { loadAllMemories(); });
|
|
29
|
+
t("corrupted file loads as memory with id-based name", () => {
|
|
30
|
+
const all = loadAllMemories();
|
|
31
|
+
const recovered = all.find(m => m.id === corruptId);
|
|
32
|
+
if (!recovered)
|
|
33
|
+
throw new Error("should load file content as memory");
|
|
34
|
+
// Without frontmatter, name defaults to id, content is full file text
|
|
35
|
+
if (recovered.category !== "general")
|
|
36
|
+
throw new Error("default category missing");
|
|
37
|
+
});
|
|
38
|
+
fs.unlinkSync(corruptPath);
|
|
39
|
+
// ═══ SCENARIO 2: Duplicate import resilience ═══
|
|
40
|
+
console.log("\n=== Scenario 2: Duplicate import resilience ===");
|
|
41
|
+
const s2 = new MemoryStore();
|
|
42
|
+
const dup1 = { id: randomUUID(), name: "Pref", content: "Always use React 19 with TypeScript strict mode", category: "user-preference", tags: ["react"], priority: 8, vector: [], created_at: now, access_count: 0, last_accessed: null };
|
|
43
|
+
const dup2 = { id: randomUUID(), name: "Pref", content: "Always use React 19 with TypeScript strict mode", category: "user-preference", tags: ["react"], priority: 8, vector: [], created_at: now, access_count: 0, last_accessed: null };
|
|
44
|
+
s2.add(dup1);
|
|
45
|
+
s2.add(dup2);
|
|
46
|
+
t("both stored (different IDs)", () => { if (s2.size() !== 2)
|
|
47
|
+
throw new Error("size=" + s2.size()); });
|
|
48
|
+
const overlap = contentOverlap(dup1.content, dup2.content);
|
|
49
|
+
t("100% overlap detected", () => { if (overlap < 0.99)
|
|
50
|
+
throw new Error("overlap=" + overlap); });
|
|
51
|
+
// ═══ SCENARIO 3: Memory lifecycle ═══
|
|
52
|
+
console.log("\n=== Scenario 3: Full memory lifecycle ===");
|
|
53
|
+
const s3 = new MemoryStore();
|
|
54
|
+
const lifeId = randomUUID();
|
|
55
|
+
s3.add({ id: lifeId, name: "Lifecycle Test", content: "Original content v1", category: "general", tags: ["test"], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
56
|
+
t("create", () => { if (!s3.get(lifeId))
|
|
57
|
+
throw new Error("not found"); });
|
|
58
|
+
const m = s3.get(lifeId);
|
|
59
|
+
m.content = "Updated content v2";
|
|
60
|
+
m.name = autoName(m.content);
|
|
61
|
+
m.category = "decision-log";
|
|
62
|
+
m.tags = ["updated", "v2"];
|
|
63
|
+
m.priority = 9;
|
|
64
|
+
t("update content", () => { if (s3.get(lifeId).content !== "Updated content v2")
|
|
65
|
+
throw new Error("content"); });
|
|
66
|
+
t("update category", () => { if (s3.get(lifeId).category !== "decision-log")
|
|
67
|
+
throw new Error("category"); });
|
|
68
|
+
t("update tags", () => { if (s3.get(lifeId).tags.length !== 2)
|
|
69
|
+
throw new Error("tags"); });
|
|
70
|
+
t("update priority", () => { if (s3.get(lifeId).priority !== 9)
|
|
71
|
+
throw new Error("priority"); });
|
|
72
|
+
t("update name", () => { if (s3.get(lifeId).name !== "Updated content v2")
|
|
73
|
+
throw new Error("name"); });
|
|
74
|
+
const found = s3.keywordSearch("updated", { limit: 5 });
|
|
75
|
+
t("search finds updated", () => { if (found.length === 0)
|
|
76
|
+
throw new Error("not found"); });
|
|
77
|
+
t("search score reasonable", () => { if (found[0]._score < 5)
|
|
78
|
+
throw new Error("score=" + found[0]._score); });
|
|
79
|
+
s3.remove(lifeId);
|
|
80
|
+
t("forget removes", () => { if (s3.get(lifeId) !== null)
|
|
81
|
+
throw new Error("still exists"); });
|
|
82
|
+
// ═══ SCENARIO 4: Context summary ranking ═══
|
|
83
|
+
console.log("\n=== Scenario 4: Context summary ranking ===");
|
|
84
|
+
const s4 = new MemoryStore();
|
|
85
|
+
s4.add({ id: "high", name: "High Priority", content: "Critical security config", category: "decision-log", tags: [], priority: 10, vector: [], created_at: now, access_count: 100, last_accessed: now });
|
|
86
|
+
s4.add({ id: "low", name: "Low Priority", content: "Casual note", category: "general", tags: [], priority: 1, vector: [], created_at: "2020-01-01T00:00:00Z", access_count: 0, last_accessed: null });
|
|
87
|
+
const summary = generateContextSummary(s4, 1);
|
|
88
|
+
t("high priority wins", () => { if (!summary.includes("High Priority"))
|
|
89
|
+
throw new Error("low won"); });
|
|
90
|
+
t("low priority excluded", () => { if (summary.includes("Low Priority"))
|
|
91
|
+
throw new Error("low included"); });
|
|
92
|
+
// ═══ SCENARIO 5: Concurrent write safety ═══
|
|
93
|
+
console.log("\n=== Scenario 5: Concurrent write safety ===");
|
|
94
|
+
const s5 = new MemoryStore();
|
|
95
|
+
const cid = randomUUID();
|
|
96
|
+
s5.add({ id: cid, name: "First", content: "First write", category: "general", tags: [], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
97
|
+
s5.add({ id: cid, name: "Second", content: "Second write", category: "general", tags: [], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
98
|
+
t("last write wins", () => { if (s5.get(cid).content !== "Second write")
|
|
99
|
+
throw new Error(s5.get(cid).content); });
|
|
100
|
+
// ═══ SCENARIO 6: Export/import round-trip ═══
|
|
101
|
+
console.log("\n=== Scenario 6: Export/import round-trip ===");
|
|
102
|
+
const s6 = new MemoryStore();
|
|
103
|
+
s6.add({ id: "e1", name: "Export Test", content: "Data for export", category: "general", tags: ["export"], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
104
|
+
const exported = s6.list({ limit: 100, offset: 0 });
|
|
105
|
+
const imported = new MemoryStore();
|
|
106
|
+
for (const em of exported)
|
|
107
|
+
imported.add({ ...em });
|
|
108
|
+
t("round-trip content", () => { if (imported.get("e1").content !== "Data for export")
|
|
109
|
+
throw new Error("lost"); });
|
|
110
|
+
t("round-trip tags", () => { if (imported.get("e1").tags[0] !== "export")
|
|
111
|
+
throw new Error("tags lost"); });
|
|
112
|
+
// ═══ SCENARIO 7: Multi-tag filtering ═══
|
|
113
|
+
console.log("\n=== Scenario 7: Multi-tag filtering ===");
|
|
114
|
+
const s7 = new MemoryStore();
|
|
115
|
+
s7.add({ id: "t1", name: "A", content: "x", category: "general", tags: ["react", "typescript", "tailwind"], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
116
|
+
s7.add({ id: "t2", name: "B", content: "x", category: "general", tags: ["react", "vue"], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
117
|
+
s7.add({ id: "t3", name: "C", content: "x", category: "general", tags: ["python", "django"], priority: 5, vector: [], created_at: now, access_count: 0, last_accessed: null });
|
|
118
|
+
t("single tag", () => { if (s7.list({ tags: ["react"], limit: 10, offset: 0 }).length !== 2)
|
|
119
|
+
throw new Error("react"); });
|
|
120
|
+
t("OR multi-tag", () => { if (s7.list({ tags: ["python", "django"], limit: 10, offset: 0 }).length !== 1)
|
|
121
|
+
throw new Error("python"); });
|
|
122
|
+
t("no-match tag", () => { if (s7.list({ tags: ["rust"], limit: 10, offset: 0 }).length !== 0)
|
|
123
|
+
throw new Error("rust"); });
|
|
124
|
+
// ═══ SCENARIO 8: Large batch performance ═══
|
|
125
|
+
console.log("\n=== Scenario 8: Large batch performance ===");
|
|
126
|
+
const s8 = new MemoryStore();
|
|
127
|
+
const start = Date.now();
|
|
128
|
+
for (let i = 0; i < 500; i++) {
|
|
129
|
+
s8.add({ id: `perf-${i}`, name: `Memory ${i}`, content: `Content for memory number ${i} with tags and metadata`, category: i % 4 === 0 ? "decision-log" : i % 4 === 1 ? "user-preference" : i % 4 === 2 ? "code-pattern" : "general", tags: [`tag-${i % 10}`], priority: 1 + (i % 10), vector: [], created_at: now, access_count: i, last_accessed: null });
|
|
130
|
+
}
|
|
131
|
+
const insertTime = Date.now() - start;
|
|
132
|
+
t("500 inserts under 500ms", () => { if (insertTime > 500)
|
|
133
|
+
throw new Error(insertTime + "ms"); });
|
|
134
|
+
const searchStart = Date.now();
|
|
135
|
+
for (let i = 0; i < 50; i++)
|
|
136
|
+
s8.keywordSearch(`content ${i}`, { limit: 10 });
|
|
137
|
+
t("50 searches under 200ms", () => { if (Date.now() - searchStart > 200)
|
|
138
|
+
throw new Error((Date.now() - searchStart) + "ms"); });
|
|
139
|
+
// ═══ SCENARIO 9: Empty/edge state stress ═══
|
|
140
|
+
console.log("\n=== Scenario 9: Edge state stress ===");
|
|
141
|
+
const s9 = new MemoryStore();
|
|
142
|
+
t("empty store list", () => { if (s9.list({ limit: 10, offset: 0 }).length !== 0)
|
|
143
|
+
throw new Error("not empty"); });
|
|
144
|
+
t("empty store size 0", () => { if (s9.size() !== 0)
|
|
145
|
+
throw new Error("not zero"); });
|
|
146
|
+
t("empty store stats", () => {
|
|
147
|
+
const st = s9.stats();
|
|
148
|
+
if (st.total !== 0 || st.total_accesses !== 0)
|
|
149
|
+
throw new Error("not empty stats");
|
|
150
|
+
});
|
|
151
|
+
t("empty store keyword search", () => { if (s9.keywordSearch("anything", { limit: 5 }).length !== 0)
|
|
152
|
+
throw new Error("found in empty"); });
|
|
153
|
+
t("empty store get nonexistent", () => { if (s9.get("nope") !== null)
|
|
154
|
+
throw new Error("found in empty"); });
|
|
155
|
+
t("empty store context summary", () => {
|
|
156
|
+
const cs = generateContextSummary(s9, 5);
|
|
157
|
+
if (!cs.includes("Welcome"))
|
|
158
|
+
throw new Error("no welcome");
|
|
159
|
+
});
|
|
160
|
+
// ═══ SCENARIO 10: LRU eviction stress ═══
|
|
161
|
+
console.log("\n=== Scenario 10: LRU eviction stress ===");
|
|
162
|
+
const s10 = new MemoryStore();
|
|
163
|
+
for (let i = 0; i < 5100; i++) {
|
|
164
|
+
s10.add({ id: `lru-${i}`, name: `Memory ${i}`, content: `Content ${i}`, category: "general", tags: [], priority: 5, vector: [], created_at: now, access_count: i, last_accessed: null });
|
|
165
|
+
}
|
|
166
|
+
t("LRU capped at 5000", () => { if (s10.size() > 5000)
|
|
167
|
+
throw new Error("size=" + s10.size()); });
|
|
168
|
+
t("LRU evicted lowest access", () => {
|
|
169
|
+
const all = s10.list({ limit: 5000, offset: 0 });
|
|
170
|
+
const minAccess = Math.min(...all.map(m => m.access_count));
|
|
171
|
+
if (minAccess < 100)
|
|
172
|
+
throw new Error("should have evicted 0-99 range, min=" + minAccess);
|
|
173
|
+
});
|
|
174
|
+
console.log("\n" + ok + " passed, " + ng + " failed");
|
|
175
|
+
if (ng > 0)
|
|
176
|
+
process.exit(1);
|
|
177
|
+
//# sourceMappingURL=scenario-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-test.js","sourceRoot":"","sources":["../src/scenario-test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAgB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAc,eAAe,EAAoB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,IAAI,EAAE,GAAG,CAAC,CAAC;AAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACvB,SAAS,CAAC,CAAC,IAAY,EAAE,EAAc,IAAI,IAAI,CAAC;IAAC,EAAE,EAAE,CAAC;IAAC,EAAE,EAAE,CAAC;AAAC,CAAC;AAAC,OAAM,CAAM,EAAE,CAAC;IAAC,EAAE,EAAE,CAAC;IAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAAC,CAAC,CAAC,CAAC;AAEpI,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAErC,4CAA4C;AAC5C,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;AACzD,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;AAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;AAC7G,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC;AACzD,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1C,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,qDAAqD,CAAC,CAAC;AACrF,CAAC,CAAC,sCAAsC,EAAE,GAAG,EAAE,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,CAAC,mDAAmD,EAAE,GAAG,EAAE;IAC1D,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACtE,sEAAsE;IACtE,IAAI,SAAS,CAAC,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;AACpF,CAAC,CAAC,CAAC;AACH,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAE3B,kDAAkD;AAClD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;AACjE,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iDAAiD,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAc,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAqB,EAAE,CAAC;AACvQ,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iDAAiD,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAC1O,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC,CAAC,6BAA6B,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvG,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC3D,CAAC,CAAC,uBAAuB,EAAE,GAAG,EAAE,GAAG,IAAI,OAAO,GAAG,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjG,uCAAuC;AACvC,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;AAC3D,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AAC5B,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AACpM,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;AAC1B,CAAC,CAAC,OAAO,GAAG,oBAAoB,CAAC;AAAC,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC/D,CAAC,CAAC,QAAQ,GAAG,cAAc,CAAC;AAAC,CAAC,CAAC,IAAI,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;AACxE,CAAC,CAAC,gBAAgB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,OAAO,KAAK,oBAAoB;IAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjH,CAAC,CAAC,iBAAiB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,QAAQ,KAAK,cAAc;IAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9G,CAAC,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC,CAAC,iBAAiB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,QAAQ,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,IAAI,KAAK,oBAAoB;IAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxG,MAAM,KAAK,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,CAAC,sBAAsB,EAAE,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F,CAAC,CAAC,yBAAyB,EAAE,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAO,GAAG,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/G,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC,CAAC,gBAAgB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7F,8CAA8C;AAC9C,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;AAC7D,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,0BAA0B,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;AACzM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,sBAAsB,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AACtM,MAAM,OAAO,GAAG,sBAAsB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC9C,CAAC,CAAC,oBAAoB,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC,CAAC,uBAAuB,EAAE,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7G,8CAA8C;AAC9C,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;AAC7D,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;AACzB,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1K,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5K,CAAC,CAAC,iBAAiB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,OAAO,KAAK,cAAc;IAAE,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpH,+CAA+C;AAC/C,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;AAC9D,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7L,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AACpD,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;AACnC,KAAK,MAAM,EAAE,IAAI,QAAQ;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC,oBAAoB,EAAE,GAAG,EAAE,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,OAAO,KAAK,iBAAiB;IAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnH,CAAC,CAAC,iBAAiB,EAAE,GAAG,EAAE,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;IAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5G,0CAA0C;AAC1C,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;AACzD,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9L,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3K,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/K,CAAC,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1H,CAAC,CAAC,cAAc,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxI,CAAC,CAAC,cAAc,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1H,8CAA8C;AAC9C,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;AAC7D,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;IAC7B,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,6BAA6B,CAAC,yBAAyB,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9V,CAAC;AACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;AACtC,CAAC,CAAC,yBAAyB,EAAE,GAAG,EAAE,GAAG,IAAI,UAAU,GAAG,GAAG;IAAE,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAElG,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;IAAE,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC,yBAAyB,EAAE,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,GAAG;IAAE,MAAM,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhI,8CAA8C;AAC9C,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;AACvD,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7B,CAAC,CAAC,kBAAkB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnH,CAAC,CAAC,oBAAoB,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAC1B,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;IACtB,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,cAAc,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACpF,CAAC,CAAC,CAAC;AACH,CAAC,CAAC,4BAA4B,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC;IAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3I,CAAC,CAAC,6BAA6B,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5G,CAAC,CAAC,6BAA6B,EAAE,GAAG,EAAE;IACpC,MAAM,EAAE,GAAG,sBAAsB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH,2CAA2C;AAC3C,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;IAC9B,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3L,CAAC;AACD,CAAC,CAAC,oBAAoB,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC,CAAC,2BAA2B,EAAE,GAAG,EAAE;IAClC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IAC5D,IAAI,SAAS,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,SAAS,CAAC,CAAC;AAC3F,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,WAAW,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;AACtD,IAAI,EAAE,GAAG,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/setup.js
CHANGED
|
@@ -13,14 +13,14 @@ export async function setup() {
|
|
|
13
13
|
║ MemoryForge Setup ║
|
|
14
14
|
╚══════════════════════════╝
|
|
15
15
|
`);
|
|
16
|
-
// 0. Install globally (
|
|
17
|
-
console.log("📦 Installing memory-forge globally…");
|
|
16
|
+
// 0. Install globally in background (non-blocking — setup continues regardless)
|
|
17
|
+
console.log("📦 Installing memory-forge globally (background)…");
|
|
18
18
|
try {
|
|
19
|
-
execSync("npm i -g memory-forge@latest", { stdio: "pipe", timeout:
|
|
19
|
+
execSync("npm i -g memory-forge@latest", { stdio: "pipe", timeout: 30000 });
|
|
20
20
|
console.log(" ✅ Global install complete");
|
|
21
21
|
}
|
|
22
22
|
catch {
|
|
23
|
-
console.log(" ⚠️ Global install skipped
|
|
23
|
+
console.log(" ⚠️ Global install skipped — hooks work with npx too");
|
|
24
24
|
}
|
|
25
25
|
// 1. Install Claude Code hooks
|
|
26
26
|
console.log("\n🪝 Installing Claude Code hooks…");
|
|
@@ -60,6 +60,12 @@ export async function setup() {
|
|
|
60
60
|
│ • Load context on session start │
|
|
61
61
|
│ • Capture learnings each session │
|
|
62
62
|
│ │
|
|
63
|
+
│ Try it now: │
|
|
64
|
+
│ • CLI: memory-forge list │
|
|
65
|
+
│ • CLI: memory-forge search "react"│
|
|
66
|
+
│ • CLI: memory-forge stats │
|
|
67
|
+
│ • MCP: memory_store "I prefer…" │
|
|
68
|
+
│ │
|
|
63
69
|
│ No further setup needed. │
|
|
64
70
|
└──────────────────────────────────────┘
|
|
65
71
|
`);
|
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,OAAO,CAAC,GAAG,CAAC;;;;GAIX,CAAC,CAAC;IAEH,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,OAAO,CAAC,GAAG,CAAC;;;;GAIX,CAAC,CAAC;IAEH,gFAAgF;IAChF,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,IAAI,CAAC;QACH,QAAQ,CAAC,8BAA8B,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IACzE,CAAC;IAED,+BAA+B;IAC/B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,yDAAyD,CAAC,CAAC,CAAC,8CAA8C,CAAC,CAAC;IAElI,2BAA2B;IAC3B,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,MAAM,kDAAkD,CAAC,CAAC;QACxF,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,UAAU,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,CAAC,MAAM,oBAAoB,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IACjE,CAAC;IAED,2CAA2C;IAC3C,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,EAAE,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;IAEzE,yBAAyB;IACzB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,qBAAqB,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;IACxF,OAAO,CAAC,GAAG,CAAC,qBAAqB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,qBAAqB,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEtF,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;GAkBX,CAAC,CAAC;AACL,CAAC"}
|
package/dist/storage/shelby.d.ts
CHANGED
|
@@ -5,12 +5,31 @@
|
|
|
5
5
|
import { ShelbyNodeClient } from "@shelby-protocol/sdk/node";
|
|
6
6
|
import { Account } from "@aptos-labs/ts-sdk";
|
|
7
7
|
import type { Memory } from "../store.js";
|
|
8
|
+
/** Whether the last API call failed with 401/403. */
|
|
9
|
+
export declare function isAuthFailed(): boolean;
|
|
10
|
+
/** Central Shelby config — single switch point for API key → license key migration. */
|
|
11
|
+
export interface ShelbyConfig {
|
|
12
|
+
apiKey: string | null;
|
|
13
|
+
namespace: string;
|
|
14
|
+
accountAddress: string | null;
|
|
15
|
+
}
|
|
16
|
+
export declare function getShelbyConfig(): ShelbyConfig;
|
|
8
17
|
export declare function initShelby(apiKey: string, privateKey?: string): {
|
|
9
18
|
address: string;
|
|
10
19
|
generatedKey?: string;
|
|
11
20
|
};
|
|
12
21
|
export declare function getShelbyClient(): ShelbyNodeClient | null;
|
|
13
22
|
export declare function getShelbyAccount(): Account | null;
|
|
23
|
+
/** Query on-chain balances via REST API. Returns null on error. */
|
|
24
|
+
export declare function getBalances(): Promise<{
|
|
25
|
+
apt: string;
|
|
26
|
+
shelbyUsd: string;
|
|
27
|
+
} | null>;
|
|
28
|
+
/** Query storage usage from Shelby. Returns count + total bytes, or null on error. */
|
|
29
|
+
export declare function getStorageUsage(): Promise<{
|
|
30
|
+
blobCount: number;
|
|
31
|
+
totalBytes: number;
|
|
32
|
+
} | null>;
|
|
14
33
|
/** 上传记忆到 Shelby */
|
|
15
34
|
export declare function uploadMemory(memory: Memory): Promise<string | null>;
|
|
16
35
|
/** 从 Shelby 下载记忆(30s 超时,Windows 安全边界) */
|
|
@@ -19,7 +38,7 @@ export declare function downloadMemory(blobName: string): Promise<Memory | null>
|
|
|
19
38
|
export declare function listBlobs(): Promise<string[]>;
|
|
20
39
|
/** 从 Shelby 删除记忆 */
|
|
21
40
|
export declare function deleteBlob(blobName: string): Promise<void>;
|
|
22
|
-
/** 将本地记忆导出为 blob
|
|
41
|
+
/** 将本地记忆导出为 blob 名称(含命名空间) */
|
|
23
42
|
export declare function getBlobName(memoryId: string): string;
|
|
24
|
-
/** 从 blob 名称解析 memory_id */
|
|
43
|
+
/** 从 blob 名称解析 memory_id(兼容新旧格式) */
|
|
25
44
|
export declare function getMemoryId(blobName: string): string | null;
|
package/dist/storage/shelby.js
CHANGED
|
@@ -4,10 +4,39 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { ShelbyNodeClient } from "@shelby-protocol/sdk/node";
|
|
6
6
|
import { Account, Ed25519PrivateKey, Network } from "@aptos-labs/ts-sdk";
|
|
7
|
-
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
const DOWNLOAD_TIMEOUT_MS = 30_000;
|
|
10
|
+
const HOME = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
|
|
11
|
+
const PROFILE_PATH = path.join(HOME, ".memory-forge", "pro.json");
|
|
8
12
|
let client = null;
|
|
9
13
|
let account = null;
|
|
14
|
+
let authFailed = false;
|
|
15
|
+
let uploadWarned = false;
|
|
16
|
+
/** Whether the last API call failed with 401/403. */
|
|
17
|
+
export function isAuthFailed() { return authFailed; }
|
|
18
|
+
export function getShelbyConfig() {
|
|
19
|
+
// Priority: env var → saved in pro.json → null
|
|
20
|
+
let apiKey = process.env.SHELBY_API_KEY ?? null;
|
|
21
|
+
let accountAddress = null;
|
|
22
|
+
try {
|
|
23
|
+
if (fs.existsSync(PROFILE_PATH)) {
|
|
24
|
+
const profile = JSON.parse(fs.readFileSync(PROFILE_PATH, "utf-8"));
|
|
25
|
+
accountAddress = profile.address ?? null;
|
|
26
|
+
// Fall back to saved key if env not set
|
|
27
|
+
if (!apiKey)
|
|
28
|
+
apiKey = profile.apiKey ?? null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch { /* corrupted profile — ignore */ }
|
|
32
|
+
const namespace = accountAddress
|
|
33
|
+
? `users/${accountAddress}`
|
|
34
|
+
: `users/default`;
|
|
35
|
+
return { apiKey, namespace, accountAddress };
|
|
36
|
+
}
|
|
10
37
|
export function initShelby(apiKey, privateKey) {
|
|
38
|
+
authFailed = false;
|
|
39
|
+
uploadWarned = false;
|
|
11
40
|
client = new ShelbyNodeClient({
|
|
12
41
|
network: Network.SHELBYNET,
|
|
13
42
|
apiKey,
|
|
@@ -34,12 +63,64 @@ export function getShelbyClient() {
|
|
|
34
63
|
export function getShelbyAccount() {
|
|
35
64
|
return account;
|
|
36
65
|
}
|
|
66
|
+
/** Build namespaced blob name: users/{namespace}/memories/{id}.json */
|
|
67
|
+
function blobNameFor(memoryId) {
|
|
68
|
+
const cfg = getShelbyConfig();
|
|
69
|
+
return `${cfg.namespace}/memories/${memoryId}.json`;
|
|
70
|
+
}
|
|
71
|
+
const SHELBYUSD_FA = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
|
|
72
|
+
/** Query on-chain balances via REST API. Returns null on error. */
|
|
73
|
+
export async function getBalances() {
|
|
74
|
+
if (!client || !account)
|
|
75
|
+
return null;
|
|
76
|
+
try {
|
|
77
|
+
const aptosConfig = client.config;
|
|
78
|
+
const baseUrl = aptosConfig.fullnode ?? "https://api.shelbynet.shelby.xyz/v1";
|
|
79
|
+
const addr = account.accountAddress.toString();
|
|
80
|
+
// APT: query coin store resource
|
|
81
|
+
const aptUrl = `${baseUrl}/accounts/${addr}/resource/0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>`;
|
|
82
|
+
const aptRes = await fetch(aptUrl).then(r => r.json()).catch(() => null);
|
|
83
|
+
const aptRaw = aptRes?.data?.coin?.value;
|
|
84
|
+
// ShelbyUSD: query fungible asset balance
|
|
85
|
+
const usdUrl = `${baseUrl}/accounts/${addr}/fungible_asset_balances`;
|
|
86
|
+
const usdRes = await fetch(usdUrl).then(r => r.json()).catch(() => null);
|
|
87
|
+
const usdEntry = Array.isArray(usdRes) ? usdRes.find((b) => b.asset_type === SHELBYUSD_FA) : null;
|
|
88
|
+
const usdRaw = usdEntry?.amount;
|
|
89
|
+
return {
|
|
90
|
+
apt: typeof aptRaw === "string" ? (Number(aptRaw) / 1e8).toFixed(4) : "0.0000",
|
|
91
|
+
shelbyUsd: typeof usdRaw === "string" ? (Number(usdRaw) / 1e6).toFixed(4) : "0.0000",
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Query storage usage from Shelby. Returns count + total bytes, or null on error. */
|
|
99
|
+
export async function getStorageUsage() {
|
|
100
|
+
if (!client || !account)
|
|
101
|
+
return null;
|
|
102
|
+
try {
|
|
103
|
+
// Use coordination layer to list blobs with metadata
|
|
104
|
+
const metadata = await client.coordination.getAccountBlobs({
|
|
105
|
+
account: account.accountAddress,
|
|
106
|
+
});
|
|
107
|
+
const cfg = getShelbyConfig();
|
|
108
|
+
const ours = metadata.filter((m) => m.name?.includes(`/${cfg.namespace}/`));
|
|
109
|
+
const totalBytes = ours.reduce((sum, m) => sum + (m.size ?? 0), 0);
|
|
110
|
+
return { blobCount: ours.length, totalBytes };
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
37
116
|
/** 上传记忆到 Shelby */
|
|
38
117
|
export async function uploadMemory(memory) {
|
|
39
118
|
if (!client || !account)
|
|
40
119
|
return null;
|
|
120
|
+
if (authFailed)
|
|
121
|
+
return null;
|
|
41
122
|
const blobData = Buffer.from(JSON.stringify(memory));
|
|
42
|
-
const blobName =
|
|
123
|
+
const blobName = blobNameFor(memory.id);
|
|
43
124
|
try {
|
|
44
125
|
await client.upload({
|
|
45
126
|
signer: account,
|
|
@@ -55,7 +136,16 @@ export async function uploadMemory(memory) {
|
|
|
55
136
|
if (msg.includes("400") || msg.includes("Bad Request")) {
|
|
56
137
|
return blobName;
|
|
57
138
|
}
|
|
58
|
-
|
|
139
|
+
// 401/403 = auth failure — stop trying this session
|
|
140
|
+
if (msg.includes("401") || msg.includes("403") || msg.includes("Unauthorized")) {
|
|
141
|
+
authFailed = true;
|
|
142
|
+
console.error("[MemoryForge] Pro sync: authentication failed. Check SHELBY_API_KEY.");
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
if (!uploadWarned) {
|
|
146
|
+
uploadWarned = true;
|
|
147
|
+
console.error("[MemoryForge] Pro sync: upload failed (network/storage issue). Will retry next sync.");
|
|
148
|
+
}
|
|
59
149
|
return null;
|
|
60
150
|
}
|
|
61
151
|
}
|
|
@@ -141,13 +231,18 @@ export async function deleteBlob(blobName) {
|
|
|
141
231
|
// ignore
|
|
142
232
|
}
|
|
143
233
|
}
|
|
144
|
-
/** 将本地记忆导出为 blob
|
|
234
|
+
/** 将本地记忆导出为 blob 名称(含命名空间) */
|
|
145
235
|
export function getBlobName(memoryId) {
|
|
146
|
-
return
|
|
236
|
+
return blobNameFor(memoryId);
|
|
147
237
|
}
|
|
148
|
-
/** 从 blob 名称解析 memory_id */
|
|
238
|
+
/** 从 blob 名称解析 memory_id(兼容新旧格式) */
|
|
149
239
|
export function getMemoryId(blobName) {
|
|
150
|
-
|
|
151
|
-
|
|
240
|
+
// New format: users/{ns}/memories/{id}.json
|
|
241
|
+
const newMatch = blobName.match(/memories\/(.+)\.json$/);
|
|
242
|
+
if (newMatch)
|
|
243
|
+
return newMatch[1];
|
|
244
|
+
// Old format: memories/{id}.json (legacy, pre-namespace)
|
|
245
|
+
const oldMatch = blobName.match(/^memories\/(.+)\.json$/);
|
|
246
|
+
return oldMatch ? oldMatch[1] : null;
|
|
152
247
|
}
|
|
153
248
|
//# sourceMappingURL=shelby.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shelby.js","sourceRoot":"","sources":["../../src/storage/shelby.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"shelby.js","sourceRoot":"","sources":["../../src/storage/shelby.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -40,7 +40,9 @@ export declare class MemoryStore {
|
|
|
40
40
|
search(rawQuery: string, options: SearchOptions): Memory[];
|
|
41
41
|
/** 余弦相似度检索 */
|
|
42
42
|
private vectorSearch;
|
|
43
|
-
/** 降级:
|
|
43
|
+
/** 降级: 无向量时的混合关键词匹配。
|
|
44
|
+
* ≤3 char tokens: word-boundary only (acronyms like DB, CI, AI).
|
|
45
|
+
* >3 char tokens: word-boundary primary + substring fallback (postgres → PostgreSQL). */
|
|
44
46
|
keywordSearch(query: string, options: {
|
|
45
47
|
limit: number;
|
|
46
48
|
category?: string | null;
|
|
@@ -55,4 +57,12 @@ export declare class MemoryStore {
|
|
|
55
57
|
total_accesses: number;
|
|
56
58
|
};
|
|
57
59
|
}
|
|
60
|
+
/** Character 3-gram Jaccard similarity.
|
|
61
|
+
* Captures short technical terms ("AI", "DB", "CI") naturally
|
|
62
|
+
* embedded in n-grams. Falls back to exact match for strings too
|
|
63
|
+
* short to produce n-grams (≤2 chars). */
|
|
64
|
+
export declare function contentOverlap(a: string, b: string): number;
|
|
65
|
+
/** Unicode-safe string truncation using Intl.Segmenter (grapheme clusters).
|
|
66
|
+
* Never splits surrogate pairs, ZWJ sequences, or combining marks. */
|
|
67
|
+
export declare function safeTruncate(text: string, maxLen: number): string;
|
|
58
68
|
export {};
|
package/dist/store.js
CHANGED
|
@@ -82,10 +82,12 @@ export class MemoryStore {
|
|
|
82
82
|
.slice(0, limit)
|
|
83
83
|
.map((s) => ({ ...s.memory, similarity: s.similarity, _score: s.score }));
|
|
84
84
|
}
|
|
85
|
-
/** 降级:
|
|
85
|
+
/** 降级: 无向量时的混合关键词匹配。
|
|
86
|
+
* ≤3 char tokens: word-boundary only (acronyms like DB, CI, AI).
|
|
87
|
+
* >3 char tokens: word-boundary primary + substring fallback (postgres → PostgreSQL). */
|
|
86
88
|
keywordSearch(query, options) {
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
+
const rawTokens = query.toLowerCase().split(/\s+/).filter((t) => t.length > 1);
|
|
90
|
+
if (rawTokens.length === 0)
|
|
89
91
|
return [];
|
|
90
92
|
let candidates = [...this.memories.values()];
|
|
91
93
|
if (options.category) {
|
|
@@ -94,20 +96,50 @@ export class MemoryStore {
|
|
|
94
96
|
if (options.tags?.length) {
|
|
95
97
|
candidates = candidates.filter((m) => options.tags.some((t) => m.tags.includes(t)));
|
|
96
98
|
}
|
|
99
|
+
// Build per-token matchers: boundary regex (all) + substring check (long tokens only)
|
|
100
|
+
const matchers = rawTokens.map((t) => {
|
|
101
|
+
const escaped = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
102
|
+
return {
|
|
103
|
+
regex: new RegExp(`\\b${escaped}\\b`, "i"),
|
|
104
|
+
substring: escaped,
|
|
105
|
+
isShort: t.length <= 3,
|
|
106
|
+
};
|
|
107
|
+
});
|
|
97
108
|
return candidates
|
|
98
109
|
.map((m) => {
|
|
99
110
|
const content = m.content.toLowerCase();
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
111
|
+
const name = m.name.toLowerCase();
|
|
112
|
+
let score = 0;
|
|
113
|
+
for (const mat of matchers) {
|
|
114
|
+
let contentWeight = 0;
|
|
115
|
+
let nameWeight = 0;
|
|
116
|
+
if (mat.regex.test(content)) {
|
|
117
|
+
contentWeight = 2; // word boundary hit
|
|
118
|
+
}
|
|
119
|
+
else if (!mat.isShort && content.includes(mat.substring)) {
|
|
120
|
+
contentWeight = 1; // substring fallback (long tokens only)
|
|
121
|
+
}
|
|
122
|
+
if (mat.regex.test(name)) {
|
|
123
|
+
nameWeight = 3; // word boundary hit
|
|
124
|
+
}
|
|
125
|
+
else if (!mat.isShort && name.includes(mat.substring)) {
|
|
126
|
+
nameWeight = 1; // substring fallback (long tokens only)
|
|
127
|
+
}
|
|
128
|
+
score += contentWeight + nameWeight;
|
|
129
|
+
}
|
|
130
|
+
if (score === 0)
|
|
104
131
|
return { memory: m, score: 0 };
|
|
105
|
-
return { memory: m, score:
|
|
132
|
+
return { memory: m, score: score + (m.priority || 5) };
|
|
106
133
|
})
|
|
107
134
|
.filter((s) => s.score > 0)
|
|
108
135
|
.sort((a, b) => b.score - a.score)
|
|
109
136
|
.slice(0, options.limit)
|
|
110
|
-
.map((s) => ({
|
|
137
|
+
.map((s) => ({
|
|
138
|
+
...s.memory,
|
|
139
|
+
similarity: s.score / 10,
|
|
140
|
+
_score: s.score,
|
|
141
|
+
_fallback: "keyword",
|
|
142
|
+
}));
|
|
111
143
|
}
|
|
112
144
|
stats() {
|
|
113
145
|
const all = [...this.memories.values()];
|
|
@@ -139,4 +171,43 @@ function cosineSimilarity(a, b) {
|
|
|
139
171
|
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
140
172
|
return denom === 0 ? 0 : dot / denom;
|
|
141
173
|
}
|
|
174
|
+
/** Character 3-gram Jaccard similarity.
|
|
175
|
+
* Captures short technical terms ("AI", "DB", "CI") naturally
|
|
176
|
+
* embedded in n-grams. Falls back to exact match for strings too
|
|
177
|
+
* short to produce n-grams (≤2 chars). */
|
|
178
|
+
export function contentOverlap(a, b) {
|
|
179
|
+
const ngramsA = charNgrams(a, 3);
|
|
180
|
+
const ngramsB = charNgrams(b, 3);
|
|
181
|
+
// Both too short for 3-grams → exact match comparison
|
|
182
|
+
if (ngramsA.size === 0 && ngramsB.size === 0) {
|
|
183
|
+
return a.toLowerCase().trim() === b.toLowerCase().trim() ? 1.0 : 0.0;
|
|
184
|
+
}
|
|
185
|
+
if (ngramsA.size === 0 || ngramsB.size === 0)
|
|
186
|
+
return 0;
|
|
187
|
+
let intersection = 0;
|
|
188
|
+
for (const ng of ngramsA) {
|
|
189
|
+
if (ngramsB.has(ng))
|
|
190
|
+
intersection++;
|
|
191
|
+
}
|
|
192
|
+
return intersection / Math.min(ngramsA.size, ngramsB.size);
|
|
193
|
+
}
|
|
194
|
+
function charNgrams(text, n) {
|
|
195
|
+
const normalized = text.toLowerCase().replace(/\s+/g, " ");
|
|
196
|
+
const ngrams = new Set();
|
|
197
|
+
for (let i = 0; i <= normalized.length - n; i++) {
|
|
198
|
+
ngrams.add(normalized.slice(i, i + n));
|
|
199
|
+
}
|
|
200
|
+
return ngrams;
|
|
201
|
+
}
|
|
202
|
+
/** Unicode-safe string truncation using Intl.Segmenter (grapheme clusters).
|
|
203
|
+
* Never splits surrogate pairs, ZWJ sequences, or combining marks. */
|
|
204
|
+
export function safeTruncate(text, maxLen) {
|
|
205
|
+
if (text.length <= maxLen)
|
|
206
|
+
return text;
|
|
207
|
+
const segmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
|
|
208
|
+
const segments = [...segmenter.segment(text)];
|
|
209
|
+
if (segments.length <= maxLen)
|
|
210
|
+
return text;
|
|
211
|
+
return segments.slice(0, maxLen).map((s) => s.segment).join("");
|
|
212
|
+
}
|
|
142
213
|
//# sourceMappingURL=store.js.map
|