@graphrefly/graphrefly 0.26.0 → 0.27.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/ai-CaR_912Q.d.cts +1033 -0
- package/dist/ai-WlRltJV7.d.ts +1033 -0
- package/dist/audit-ClmqGOCx.d.cts +245 -0
- package/dist/audit-DRlSzBu9.d.ts +245 -0
- package/dist/{chunk-JYXEWPH4.js → chunk-APFNLIRG.js} +2 -2
- package/dist/chunk-AT5LKYNL.js +395 -0
- package/dist/chunk-AT5LKYNL.js.map +1 -0
- package/dist/{chunk-AMCG74RZ.js → chunk-BQ6RQQFF.js} +215 -2128
- package/dist/chunk-BQ6RQQFF.js.map +1 -0
- package/dist/{chunk-IZYUSJC7.js → chunk-DST5DKZS.js} +6 -4
- package/dist/{chunk-IZYUSJC7.js.map → chunk-DST5DKZS.js.map} +1 -1
- package/dist/{chunk-LCE3GF5P.js → chunk-GTE6PWRZ.js} +2 -2
- package/dist/{chunk-RB6QPHJ7.js → chunk-J2VBW3DZ.js} +2 -93
- package/dist/chunk-J2VBW3DZ.js.map +1 -0
- package/dist/{chunk-FQMKGR6L.js → chunk-JWBCY4NC.js} +3 -3
- package/dist/chunk-K2AUJHVP.js +2251 -0
- package/dist/chunk-K2AUJHVP.js.map +1 -0
- package/dist/chunk-NC6S43JJ.js +456 -0
- package/dist/chunk-NC6S43JJ.js.map +1 -0
- package/dist/chunk-OFVJBJXR.js +98 -0
- package/dist/chunk-OFVJBJXR.js.map +1 -0
- package/dist/{chunk-6LDQFTYS.js → chunk-OU5CQKNW.js} +2 -2
- package/dist/{chunk-THTWHNU4.js → chunk-PF7GRZMW.js} +5 -5
- package/dist/chunk-RNHBMHKA.js +1665 -0
- package/dist/chunk-RNHBMHKA.js.map +1 -0
- package/dist/{chunk-SN4YWWYO.js → chunk-WBZOVTYK.js} +11 -11
- package/dist/chunk-WKNUIZOY.js +354 -0
- package/dist/chunk-WKNUIZOY.js.map +1 -0
- package/dist/{chunk-ZQMEI34O.js → chunk-X3VMZYBT.js} +3 -3
- package/dist/chunk-X5R3GL6H.js +525 -0
- package/dist/chunk-X5R3GL6H.js.map +1 -0
- package/dist/compat/index.d.cts +14 -14
- package/dist/compat/index.d.ts +14 -14
- package/dist/compat/index.js +17 -16
- package/dist/compat/jotai/index.d.cts +2 -2
- package/dist/compat/jotai/index.d.ts +2 -2
- package/dist/compat/nanostores/index.d.cts +2 -2
- package/dist/compat/nanostores/index.d.ts +2 -2
- package/dist/compat/nestjs/index.d.cts +6 -6
- package/dist/compat/nestjs/index.d.ts +6 -6
- package/dist/compat/nestjs/index.js +7 -6
- package/dist/compat/react/index.d.cts +2 -2
- package/dist/compat/react/index.d.ts +2 -2
- package/dist/compat/solid/index.d.cts +2 -2
- package/dist/compat/solid/index.d.ts +2 -2
- package/dist/compat/svelte/index.d.cts +2 -2
- package/dist/compat/svelte/index.d.ts +2 -2
- package/dist/compat/vue/index.d.cts +2 -2
- package/dist/compat/vue/index.d.ts +2 -2
- package/dist/compat/zustand/index.d.cts +5 -5
- package/dist/compat/zustand/index.d.ts +5 -5
- package/dist/compat/zustand/index.js +3 -3
- package/dist/composite-C7PcQvcs.d.cts +303 -0
- package/dist/composite-aUCvjZVR.d.ts +303 -0
- package/dist/core/index.d.cts +4 -3
- package/dist/core/index.d.ts +4 -3
- package/dist/{demo-shell-DEp-nMTl.d.ts → demo-shell-BDkOptd6.d.ts} +2 -2
- package/dist/{demo-shell-26p5fVxn.d.cts → demo-shell-Crid1WdR.d.cts} +2 -2
- package/dist/extra/index.d.cts +5 -4
- package/dist/extra/index.d.ts +5 -4
- package/dist/extra/index.js +68 -62
- package/dist/extra/sources.d.cts +1 -1
- package/dist/extra/sources.d.ts +1 -1
- package/dist/graph/index.d.cts +5 -5
- package/dist/graph/index.d.ts +5 -5
- package/dist/graph/index.js +3 -3
- package/dist/{graph-DQ69XU0g.d.ts → graph-CCwGKLCm.d.ts} +4 -4
- package/dist/{graph-6tZ5jEzr.d.cts → graph-DNCrvZSn.d.cts} +4 -4
- package/dist/{index-qldRdbQw.d.ts → index-3lsddbbS.d.ts} +1 -1
- package/dist/{index-Bxb5ZYc9.d.cts → index-B1tloyhO.d.cts} +1 -1
- package/dist/{index-eJ6T_qGM.d.ts → index-B6D3QNSA.d.ts} +2 -2
- package/dist/{index-B4MP_8V_.d.cts → index-B6EhDnjH.d.cts} +1 -1
- package/dist/{index-CmnuOibw.d.ts → index-B9B7_HEY.d.ts} +1 -1
- package/dist/{index-BeIdBfcb.d.cts → index-BHlKbUwO.d.cts} +16 -315
- package/dist/{index-CuYwdKO-.d.ts → index-BPVt8kqc.d.ts} +3 -3
- package/dist/index-BaSM3aYt.d.ts +195 -0
- package/dist/{index-BjI6ty9z.d.ts → index-BuEoe-Qu.d.ts} +9 -9
- package/dist/{index-DdD5MVDL.d.ts → index-BwfLUNw4.d.ts} +16 -315
- package/dist/{index-QBpffFW-.d.cts → index-ByQxazQJ.d.cts} +1 -1
- package/dist/{index-xdGjv0nO.d.ts → index-C0svESO4.d.ts} +1 -1
- package/dist/{index-BW1z3BN9.d.ts → index-C8oil6M6.d.ts} +3 -3
- package/dist/{index-C8mdwMXc.d.cts → index-CI3DprxP.d.cts} +3 -3
- package/dist/{index-CUwyr1Kk.d.cts → index-CO8uBlUh.d.cts} +2 -2
- package/dist/{index-DrISNAOm.d.ts → index-CxFrXH4m.d.ts} +1 -1
- package/dist/{index-BEfE8H_G.d.cts → index-D8wS_PeY.d.cts} +9 -9
- package/dist/{index-CUyrtuOf.d.cts → index-DO_6JN9Z.d.cts} +1 -1
- package/dist/index-DVGiGFGT.d.cts +195 -0
- package/dist/{index-DFhjO4Gg.d.cts → index-DYme44FM.d.cts} +1 -1
- package/dist/{index-_oMEWlDq.d.cts → index-DlLp-2Xn.d.cts} +3 -3
- package/dist/{index-CPgZ5wRl.d.ts → index-Dzk2hrlR.d.ts} +1 -1
- package/dist/{index-Bd_fwmLf.d.cts → index-VHqptjhu.d.cts} +1 -1
- package/dist/{index-CDAjUFIv.d.ts → index-VdHQMPy1.d.ts} +1 -1
- package/dist/{index-B_IP40nB.d.cts → index-Xi3u0HCQ.d.cts} +1 -1
- package/dist/{index-BYOHF0zP.d.ts → index-wEn0eFe8.d.ts} +1 -1
- package/dist/index.d.cts +35 -1692
- package/dist/index.d.ts +35 -1692
- package/dist/index.js +307 -3731
- package/dist/index.js.map +1 -1
- package/dist/memory-C6Z2tGpC.d.cts +139 -0
- package/dist/memory-li6FL5RM.d.ts +139 -0
- package/dist/messaging-Gt4LPbyA.d.cts +269 -0
- package/dist/messaging-XDoYablx.d.ts +269 -0
- package/dist/{meta-C0-8XW6Q.d.cts → meta-BxCA7rcr.d.cts} +1 -1
- package/dist/{meta-BGqSZ7mt.d.ts → meta-CbznRPYJ.d.ts} +1 -1
- package/dist/{node-C_IBuvX2.d.cts → node-BmerH3kS.d.cts} +1 -1
- package/dist/{node-C_IBuvX2.d.ts → node-BmerH3kS.d.ts} +1 -1
- package/dist/{observable-DCk45RH5.d.ts → observable-BgGUwcqp.d.ts} +1 -1
- package/dist/{observable-Crr1jgzx.d.cts → observable-DJt_AxzQ.d.cts} +1 -1
- package/dist/patterns/ai.cjs +7930 -0
- package/dist/patterns/ai.cjs.map +1 -0
- package/dist/patterns/ai.d.cts +10 -0
- package/dist/patterns/ai.d.ts +10 -0
- package/dist/patterns/ai.js +71 -0
- package/dist/patterns/ai.js.map +1 -0
- package/dist/patterns/audit.cjs +5805 -0
- package/dist/patterns/audit.cjs.map +1 -0
- package/dist/patterns/audit.d.cts +6 -0
- package/dist/patterns/audit.d.ts +6 -0
- package/dist/patterns/audit.js +29 -0
- package/dist/patterns/audit.js.map +1 -0
- package/dist/patterns/demo-shell.d.cts +6 -6
- package/dist/patterns/demo-shell.d.ts +6 -6
- package/dist/patterns/demo-shell.js +4 -4
- package/dist/patterns/memory.cjs +5283 -0
- package/dist/patterns/memory.cjs.map +1 -0
- package/dist/patterns/memory.d.cts +5 -0
- package/dist/patterns/memory.d.ts +5 -0
- package/dist/patterns/memory.js +20 -0
- package/dist/patterns/memory.js.map +1 -0
- package/dist/patterns/reactive-layout/index.d.cts +6 -6
- package/dist/patterns/reactive-layout/index.d.ts +6 -6
- package/dist/patterns/reactive-layout/index.js +4 -4
- package/dist/{reactive-layout-BaOQefHu.d.cts → reactive-layout-MQP--J3F.d.cts} +2 -2
- package/dist/{reactive-layout-D9gejYXE.d.ts → reactive-layout-u5Ulnqag.d.ts} +2 -2
- package/dist/{storage-BMycWEh2.d.ts → storage-CMjUUuxn.d.ts} +2 -2
- package/dist/{storage-DiqWHzVI.d.cts → storage-DdWlZo6U.d.cts} +2 -2
- package/dist/sugar-CCOxXK1e.d.ts +201 -0
- package/dist/sugar-D02n5JjF.d.cts +201 -0
- package/package.json +32 -2
- package/dist/chunk-AMCG74RZ.js.map +0 -1
- package/dist/chunk-RB6QPHJ7.js.map +0 -1
- package/dist/index-C0ZXMaXO.d.cts +0 -392
- package/dist/index-CY2TljO4.d.ts +0 -392
- /package/dist/{chunk-JYXEWPH4.js.map → chunk-APFNLIRG.js.map} +0 -0
- /package/dist/{chunk-LCE3GF5P.js.map → chunk-GTE6PWRZ.js.map} +0 -0
- /package/dist/{chunk-FQMKGR6L.js.map → chunk-JWBCY4NC.js.map} +0 -0
- /package/dist/{chunk-6LDQFTYS.js.map → chunk-OU5CQKNW.js.map} +0 -0
- /package/dist/{chunk-THTWHNU4.js.map → chunk-PF7GRZMW.js.map} +0 -0
- /package/dist/{chunk-SN4YWWYO.js.map → chunk-WBZOVTYK.js.map} +0 -0
- /package/dist/{chunk-ZQMEI34O.js.map → chunk-X3VMZYBT.js.map} +0 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Graph
|
|
3
|
+
} from "./chunk-PF7GRZMW.js";
|
|
4
|
+
import {
|
|
5
|
+
derived,
|
|
6
|
+
monotonicNs,
|
|
7
|
+
state
|
|
8
|
+
} from "./chunk-PHOUUNK7.js";
|
|
9
|
+
import {
|
|
10
|
+
DATA,
|
|
11
|
+
__export
|
|
12
|
+
} from "./chunk-SX52TAR4.js";
|
|
13
|
+
|
|
14
|
+
// src/patterns/memory.ts
|
|
15
|
+
var memory_exports = {};
|
|
16
|
+
__export(memory_exports, {
|
|
17
|
+
collection: () => collection,
|
|
18
|
+
decay: () => decay,
|
|
19
|
+
knowledgeGraph: () => knowledgeGraph,
|
|
20
|
+
lightCollection: () => lightCollection,
|
|
21
|
+
vectorIndex: () => vectorIndex
|
|
22
|
+
});
|
|
23
|
+
function decay(baseScore, ageSeconds, ratePerSecond, minScore = 0) {
|
|
24
|
+
if (!Number.isFinite(baseScore)) return minScore;
|
|
25
|
+
if (!Number.isFinite(ageSeconds) || ageSeconds <= 0) return Math.max(minScore, baseScore);
|
|
26
|
+
if (!Number.isFinite(ratePerSecond) || ratePerSecond <= 0) return Math.max(minScore, baseScore);
|
|
27
|
+
const decayed = baseScore * Math.exp(-ratePerSecond * ageSeconds);
|
|
28
|
+
return Math.max(minScore, decayed);
|
|
29
|
+
}
|
|
30
|
+
function assertMaxSize(maxSize) {
|
|
31
|
+
if (maxSize !== void 0 && maxSize < 1) {
|
|
32
|
+
throw new RangeError("maxSize must be >= 1");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function copyMap(m) {
|
|
36
|
+
return new Map(m);
|
|
37
|
+
}
|
|
38
|
+
function readMap(node) {
|
|
39
|
+
return node.cache ?? /* @__PURE__ */ new Map();
|
|
40
|
+
}
|
|
41
|
+
function readArray(node) {
|
|
42
|
+
return node.cache ?? [];
|
|
43
|
+
}
|
|
44
|
+
function cosineSimilarity(a, b) {
|
|
45
|
+
const n = Math.max(a.length, b.length);
|
|
46
|
+
let dot = 0;
|
|
47
|
+
let na = 0;
|
|
48
|
+
let nb = 0;
|
|
49
|
+
for (let i = 0; i < n; i += 1) {
|
|
50
|
+
const av = a[i] ?? 0;
|
|
51
|
+
const bv = b[i] ?? 0;
|
|
52
|
+
dot += av * bv;
|
|
53
|
+
na += av * av;
|
|
54
|
+
nb += bv * bv;
|
|
55
|
+
}
|
|
56
|
+
if (na === 0 || nb === 0) return 0;
|
|
57
|
+
return dot / Math.sqrt(na * nb);
|
|
58
|
+
}
|
|
59
|
+
function lightCollection(opts = {}) {
|
|
60
|
+
const maxSize = opts.maxSize;
|
|
61
|
+
const policy = opts.policy ?? "fifo";
|
|
62
|
+
assertMaxSize(maxSize);
|
|
63
|
+
const entries = state(/* @__PURE__ */ new Map(), {
|
|
64
|
+
name: opts.name,
|
|
65
|
+
describeKind: "state"
|
|
66
|
+
});
|
|
67
|
+
function evictIfNeeded(next) {
|
|
68
|
+
if (maxSize === void 0) return;
|
|
69
|
+
while (next.size > maxSize) {
|
|
70
|
+
let victim;
|
|
71
|
+
for (const entry of next.values()) {
|
|
72
|
+
if (!victim) {
|
|
73
|
+
victim = entry;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const lhs = policy === "lru" ? entry.lastAccessNs : entry.createdAtNs;
|
|
77
|
+
const rhs = policy === "lru" ? victim.lastAccessNs : victim.createdAtNs;
|
|
78
|
+
if (lhs < rhs) victim = entry;
|
|
79
|
+
}
|
|
80
|
+
if (!victim) break;
|
|
81
|
+
next.delete(victim.id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function commit(next) {
|
|
85
|
+
entries.down([[DATA, next]]);
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
entries,
|
|
89
|
+
upsert(id, value) {
|
|
90
|
+
const now = monotonicNs();
|
|
91
|
+
const current = readMap(entries);
|
|
92
|
+
const prev = current.get(id);
|
|
93
|
+
const next = copyMap(current);
|
|
94
|
+
next.set(id, {
|
|
95
|
+
id,
|
|
96
|
+
value,
|
|
97
|
+
createdAtNs: prev?.createdAtNs ?? now,
|
|
98
|
+
lastAccessNs: now
|
|
99
|
+
});
|
|
100
|
+
evictIfNeeded(next);
|
|
101
|
+
commit(next);
|
|
102
|
+
},
|
|
103
|
+
remove(id) {
|
|
104
|
+
const next = copyMap(readMap(entries));
|
|
105
|
+
if (!next.delete(id)) return;
|
|
106
|
+
commit(next);
|
|
107
|
+
},
|
|
108
|
+
clear() {
|
|
109
|
+
if (readMap(entries).size === 0) return;
|
|
110
|
+
commit(/* @__PURE__ */ new Map());
|
|
111
|
+
},
|
|
112
|
+
get(id) {
|
|
113
|
+
const current = readMap(entries);
|
|
114
|
+
const found = current.get(id);
|
|
115
|
+
if (!found) return void 0;
|
|
116
|
+
if (policy === "lru") {
|
|
117
|
+
const now = monotonicNs();
|
|
118
|
+
const next = copyMap(current);
|
|
119
|
+
next.set(id, { ...found, lastAccessNs: now });
|
|
120
|
+
commit(next);
|
|
121
|
+
}
|
|
122
|
+
return found.value;
|
|
123
|
+
},
|
|
124
|
+
has(id) {
|
|
125
|
+
return readMap(entries).has(id);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function collection(name, opts = {}) {
|
|
130
|
+
const maxSize = opts.maxSize;
|
|
131
|
+
const policy = opts.policy ?? "lru";
|
|
132
|
+
const decayRate = opts.decayRate ?? 0;
|
|
133
|
+
const minScore = opts.minScore ?? 0;
|
|
134
|
+
const scoreFn = opts.score ?? (() => 1);
|
|
135
|
+
assertMaxSize(maxSize);
|
|
136
|
+
const graph = new Graph(name);
|
|
137
|
+
const items = state(/* @__PURE__ */ new Map(), {
|
|
138
|
+
name: "items",
|
|
139
|
+
describeKind: "state"
|
|
140
|
+
});
|
|
141
|
+
const ranked = derived(
|
|
142
|
+
[items],
|
|
143
|
+
([snapshot]) => {
|
|
144
|
+
const typed = snapshot ?? /* @__PURE__ */ new Map();
|
|
145
|
+
const now = monotonicNs();
|
|
146
|
+
const out2 = [...typed.values()].map((entry) => {
|
|
147
|
+
const ageSeconds = (now - entry.lastAccessNs) / 1e9;
|
|
148
|
+
return {
|
|
149
|
+
...entry,
|
|
150
|
+
score: decay(entry.baseScore, ageSeconds, decayRate, minScore)
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
out2.sort((a, b) => b.score - a.score || b.lastAccessNs - a.lastAccessNs);
|
|
154
|
+
return out2;
|
|
155
|
+
},
|
|
156
|
+
{ name: "ranked", describeKind: "derived" }
|
|
157
|
+
);
|
|
158
|
+
const size = derived(
|
|
159
|
+
[items],
|
|
160
|
+
([snapshot]) => (snapshot ?? /* @__PURE__ */ new Map()).size,
|
|
161
|
+
{
|
|
162
|
+
name: "size",
|
|
163
|
+
describeKind: "derived",
|
|
164
|
+
initial: 0
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
void ranked.subscribe(() => void 0);
|
|
168
|
+
void size.subscribe(() => void 0);
|
|
169
|
+
graph.add("items", items);
|
|
170
|
+
graph.add("ranked", ranked);
|
|
171
|
+
graph.add("size", size);
|
|
172
|
+
function effective(entry, now) {
|
|
173
|
+
const ageSeconds = (now - entry.lastAccessNs) / 1e9;
|
|
174
|
+
return decay(entry.baseScore, ageSeconds, decayRate, minScore);
|
|
175
|
+
}
|
|
176
|
+
function evictIfNeeded(next) {
|
|
177
|
+
if (maxSize === void 0) return;
|
|
178
|
+
while (next.size > maxSize) {
|
|
179
|
+
const now = monotonicNs();
|
|
180
|
+
let victim;
|
|
181
|
+
let victimScore = Number.POSITIVE_INFINITY;
|
|
182
|
+
for (const entry of next.values()) {
|
|
183
|
+
const score = effective(entry, now);
|
|
184
|
+
if (score < victimScore) {
|
|
185
|
+
victim = entry;
|
|
186
|
+
victimScore = score;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (score === victimScore && victim) {
|
|
190
|
+
const lhs = policy === "lru" ? entry.lastAccessNs : entry.createdAtNs;
|
|
191
|
+
const rhs = policy === "lru" ? victim.lastAccessNs : victim.createdAtNs;
|
|
192
|
+
if (lhs < rhs) victim = entry;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (!victim) break;
|
|
196
|
+
next.delete(victim.id);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function commit(next) {
|
|
200
|
+
items.down([[DATA, next]]);
|
|
201
|
+
}
|
|
202
|
+
const out = Object.assign(graph, {
|
|
203
|
+
upsert(id, value, upsertOpts) {
|
|
204
|
+
const now = monotonicNs();
|
|
205
|
+
const current = readMap(items);
|
|
206
|
+
const prev = current.get(id);
|
|
207
|
+
const baseScore = upsertOpts?.score ?? scoreFn(value);
|
|
208
|
+
const next = copyMap(current);
|
|
209
|
+
next.set(id, {
|
|
210
|
+
id,
|
|
211
|
+
value,
|
|
212
|
+
baseScore,
|
|
213
|
+
createdAtNs: prev?.createdAtNs ?? now,
|
|
214
|
+
lastAccessNs: now
|
|
215
|
+
});
|
|
216
|
+
evictIfNeeded(next);
|
|
217
|
+
commit(next);
|
|
218
|
+
},
|
|
219
|
+
remove(id) {
|
|
220
|
+
const next = copyMap(readMap(items));
|
|
221
|
+
if (!next.delete(id)) return;
|
|
222
|
+
commit(next);
|
|
223
|
+
},
|
|
224
|
+
clear() {
|
|
225
|
+
if (readMap(items).size === 0) return;
|
|
226
|
+
commit(/* @__PURE__ */ new Map());
|
|
227
|
+
},
|
|
228
|
+
getItem(id) {
|
|
229
|
+
const current = readMap(items);
|
|
230
|
+
const found = current.get(id);
|
|
231
|
+
if (!found) return void 0;
|
|
232
|
+
if (policy === "lru") {
|
|
233
|
+
const next = copyMap(current);
|
|
234
|
+
next.set(id, { ...found, lastAccessNs: monotonicNs() });
|
|
235
|
+
commit(next);
|
|
236
|
+
}
|
|
237
|
+
return found;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
return out;
|
|
241
|
+
}
|
|
242
|
+
function vectorIndex(opts = {}) {
|
|
243
|
+
const backend = opts.backend ?? "flat";
|
|
244
|
+
const dimension = opts.dimension;
|
|
245
|
+
let hnsw;
|
|
246
|
+
if (backend === "hnsw") {
|
|
247
|
+
hnsw = opts.hnswFactory?.();
|
|
248
|
+
if (!hnsw) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
'vectorIndex backend "hnsw" requires an optional dependency adapter; install your HNSW package and provide `hnswFactory`.'
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const entries = state(/* @__PURE__ */ new Map(), {
|
|
255
|
+
describeKind: "state",
|
|
256
|
+
name: "vector-index"
|
|
257
|
+
});
|
|
258
|
+
function assertDimension(vector) {
|
|
259
|
+
if (dimension !== void 0 && vector.length !== dimension) {
|
|
260
|
+
throw new RangeError(
|
|
261
|
+
`vector dimension mismatch: expected ${dimension}, got ${vector.length}`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function commit(next) {
|
|
266
|
+
entries.down([[DATA, next]]);
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
backend,
|
|
270
|
+
entries,
|
|
271
|
+
upsert(id, vector, meta) {
|
|
272
|
+
assertDimension(vector);
|
|
273
|
+
const next = copyMap(readMap(entries));
|
|
274
|
+
next.set(id, { id, vector: [...vector], meta });
|
|
275
|
+
if (backend === "hnsw") hnsw.upsert(id, vector, meta);
|
|
276
|
+
commit(next);
|
|
277
|
+
},
|
|
278
|
+
remove(id) {
|
|
279
|
+
const next = copyMap(readMap(entries));
|
|
280
|
+
if (!next.delete(id)) return;
|
|
281
|
+
if (backend === "hnsw") hnsw.remove(id);
|
|
282
|
+
commit(next);
|
|
283
|
+
},
|
|
284
|
+
clear() {
|
|
285
|
+
if (readMap(entries).size === 0) return;
|
|
286
|
+
if (backend === "hnsw") hnsw.clear();
|
|
287
|
+
commit(/* @__PURE__ */ new Map());
|
|
288
|
+
},
|
|
289
|
+
search(query, k = 5) {
|
|
290
|
+
assertDimension(query);
|
|
291
|
+
if (k <= 0) return [];
|
|
292
|
+
if (backend === "hnsw") return hnsw.search(query, k);
|
|
293
|
+
const ranked = [...readMap(entries).values()].map((row) => ({
|
|
294
|
+
id: row.id,
|
|
295
|
+
score: cosineSimilarity(query, row.vector),
|
|
296
|
+
meta: row.meta
|
|
297
|
+
})).sort((a, b) => b.score - a.score).slice(0, k);
|
|
298
|
+
return ranked;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function knowledgeGraph(name) {
|
|
303
|
+
const graph = new Graph(name);
|
|
304
|
+
const entities = state(/* @__PURE__ */ new Map(), {
|
|
305
|
+
name: "entities",
|
|
306
|
+
describeKind: "state"
|
|
307
|
+
});
|
|
308
|
+
const edges = state([], {
|
|
309
|
+
name: "edges",
|
|
310
|
+
describeKind: "state"
|
|
311
|
+
});
|
|
312
|
+
const adjacency = derived(
|
|
313
|
+
[edges],
|
|
314
|
+
([rows]) => {
|
|
315
|
+
const typed = rows ?? [];
|
|
316
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
317
|
+
for (const edge of typed) {
|
|
318
|
+
const prev = out2.get(edge.from) ?? [];
|
|
319
|
+
out2.set(edge.from, Object.freeze([...prev, edge]));
|
|
320
|
+
}
|
|
321
|
+
return out2;
|
|
322
|
+
},
|
|
323
|
+
{ name: "adjacency", describeKind: "derived", initial: /* @__PURE__ */ new Map() }
|
|
324
|
+
);
|
|
325
|
+
void adjacency.subscribe(() => void 0);
|
|
326
|
+
graph.add("entities", entities);
|
|
327
|
+
graph.add("edges", edges);
|
|
328
|
+
graph.add("adjacency", adjacency);
|
|
329
|
+
function commitEntities(next) {
|
|
330
|
+
entities.down([[DATA, next]]);
|
|
331
|
+
}
|
|
332
|
+
function commitEdges(next) {
|
|
333
|
+
edges.down([[DATA, next]]);
|
|
334
|
+
}
|
|
335
|
+
const out = Object.assign(graph, {
|
|
336
|
+
upsertEntity(id, value) {
|
|
337
|
+
const next = copyMap(readMap(entities));
|
|
338
|
+
next.set(id, value);
|
|
339
|
+
commitEntities(next);
|
|
340
|
+
},
|
|
341
|
+
removeEntity(id) {
|
|
342
|
+
const nextEntities = copyMap(readMap(entities));
|
|
343
|
+
const existed = nextEntities.delete(id);
|
|
344
|
+
const currentEdges = readArray(edges);
|
|
345
|
+
const nextEdges = currentEdges.filter((edge) => edge.from !== id && edge.to !== id);
|
|
346
|
+
if (!existed && nextEdges.length === currentEdges.length) return;
|
|
347
|
+
commitEntities(nextEntities);
|
|
348
|
+
commitEdges(nextEdges);
|
|
349
|
+
},
|
|
350
|
+
link(from, to, relation, weight = 1) {
|
|
351
|
+
const key = `${from}\0${to}\0${relation}`;
|
|
352
|
+
const currentEdges = readArray(edges);
|
|
353
|
+
const existing = new Set(
|
|
354
|
+
currentEdges.map((edge) => `${edge.from}\0${edge.to}\0${edge.relation}`)
|
|
355
|
+
);
|
|
356
|
+
const next = [...currentEdges];
|
|
357
|
+
if (existing.has(key)) {
|
|
358
|
+
for (let i = 0; i < next.length; i += 1) {
|
|
359
|
+
const edge = next[i];
|
|
360
|
+
if (edge.from === from && edge.to === to && edge.relation === relation) {
|
|
361
|
+
next[i] = { ...edge, weight };
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
next.push({ from, to, relation, weight });
|
|
367
|
+
}
|
|
368
|
+
commitEdges(next);
|
|
369
|
+
},
|
|
370
|
+
unlink(from, to, relation) {
|
|
371
|
+
const currentEdges = readArray(edges);
|
|
372
|
+
const next = currentEdges.filter(
|
|
373
|
+
(edge) => relation === void 0 ? !(edge.from === from && edge.to === to) : !(edge.from === from && edge.to === to && edge.relation === relation)
|
|
374
|
+
);
|
|
375
|
+
if (next.length === currentEdges.length) return;
|
|
376
|
+
commitEdges(next);
|
|
377
|
+
},
|
|
378
|
+
related(id, relation) {
|
|
379
|
+
return readArray(edges).filter(
|
|
380
|
+
(edge) => (edge.from === id || edge.to === id) && (relation === void 0 || edge.relation === relation)
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
return out;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export {
|
|
388
|
+
decay,
|
|
389
|
+
lightCollection,
|
|
390
|
+
collection,
|
|
391
|
+
vectorIndex,
|
|
392
|
+
knowledgeGraph,
|
|
393
|
+
memory_exports
|
|
394
|
+
};
|
|
395
|
+
//# sourceMappingURL=chunk-AT5LKYNL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/patterns/memory.ts"],"sourcesContent":["/**\n * Memory patterns (roadmap §4.3).\n *\n * Domain-layer helpers composed from GraphRefly primitives. `vectorIndex` uses\n * an exact-search backend by default; an HNSW adapter can be injected as an\n * optional dependency.\n */\n\nimport { monotonicNs } from \"../core/clock.js\";\nimport { DATA } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { derived, state } from \"../core/sugar.js\";\nimport { Graph } from \"../graph/graph.js\";\n\nexport type CollectionPolicy = \"fifo\" | \"lru\";\nexport type VectorBackend = \"flat\" | \"hnsw\";\n\nexport type LightCollectionEntry<T> = {\n\treadonly id: string;\n\treadonly value: T;\n\treadonly createdAtNs: number;\n\treadonly lastAccessNs: number;\n};\n\nexport type LightCollectionOptions = {\n\tname?: string;\n\tmaxSize?: number;\n\tpolicy?: CollectionPolicy;\n};\n\nexport type LightCollectionBundle<T> = {\n\treadonly entries: Node<ReadonlyMap<string, LightCollectionEntry<T>>>;\n\tupsert: (id: string, value: T) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tget: (id: string) => T | undefined;\n\thas: (id: string) => boolean;\n};\n\nexport type CollectionEntry<T> = LightCollectionEntry<T> & {\n\treadonly baseScore: number;\n};\n\nexport type RankedCollectionEntry<T> = CollectionEntry<T> & {\n\treadonly score: number;\n};\n\nexport type CollectionOptions<T> = {\n\tmaxSize?: number;\n\tpolicy?: CollectionPolicy;\n\t/**\n\t * Produces a base score at insert/update time.\n\t */\n\tscore?: (value: T) => number;\n\t/**\n\t * Exponential decay rate per second. 0 disables decay.\n\t */\n\tdecayRate?: number;\n\t/**\n\t * Minimum score floor after decay.\n\t */\n\tminScore?: number;\n};\n\nexport type CollectionGraph<T> = Graph & {\n\tupsert: (id: string, value: T, opts?: { score?: number }) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tgetItem: (id: string) => CollectionEntry<T> | undefined;\n};\n\nexport type VectorRecord<TMeta> = {\n\treadonly id: string;\n\treadonly vector: readonly number[];\n\treadonly meta?: TMeta;\n};\n\nexport type VectorSearchResult<TMeta> = {\n\treadonly id: string;\n\treadonly score: number;\n\treadonly meta?: TMeta;\n};\n\nexport type HnswAdapter<TMeta> = {\n\tupsert: (id: string, vector: readonly number[], meta?: TMeta) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tsearch: (query: readonly number[], k: number) => ReadonlyArray<VectorSearchResult<TMeta>>;\n};\n\nexport type VectorIndexOptions<TMeta> = {\n\tbackend?: VectorBackend;\n\tdimension?: number;\n\t/**\n\t * Optional dependency seam for HNSW.\n\t */\n\thnswFactory?: () => HnswAdapter<TMeta>;\n};\n\nexport type VectorIndexBundle<TMeta> = {\n\treadonly backend: VectorBackend;\n\treadonly entries: Node<ReadonlyMap<string, VectorRecord<TMeta>>>;\n\tupsert: (id: string, vector: readonly number[], meta?: TMeta) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tsearch: (query: readonly number[], k?: number) => ReadonlyArray<VectorSearchResult<TMeta>>;\n};\n\nexport type KnowledgeEdge<TRelation extends string = string> = {\n\treadonly from: string;\n\treadonly to: string;\n\treadonly relation: TRelation;\n\treadonly weight: number;\n};\n\nexport type KnowledgeGraphGraph<TEntity, TRelation extends string = string> = Graph & {\n\tupsertEntity: (id: string, value: TEntity) => void;\n\tremoveEntity: (id: string) => void;\n\tlink: (from: string, to: string, relation: TRelation, weight?: number) => void;\n\tunlink: (from: string, to: string, relation?: TRelation) => void;\n\trelated: (id: string, relation?: TRelation) => ReadonlyArray<KnowledgeEdge<TRelation>>;\n};\n\nexport function decay(\n\tbaseScore: number,\n\tageSeconds: number,\n\tratePerSecond: number,\n\tminScore = 0,\n): number {\n\tif (!Number.isFinite(baseScore)) return minScore;\n\tif (!Number.isFinite(ageSeconds) || ageSeconds <= 0) return Math.max(minScore, baseScore);\n\tif (!Number.isFinite(ratePerSecond) || ratePerSecond <= 0) return Math.max(minScore, baseScore);\n\tconst decayed = baseScore * Math.exp(-ratePerSecond * ageSeconds);\n\treturn Math.max(minScore, decayed);\n}\n\nfunction assertMaxSize(maxSize: number | undefined): void {\n\tif (maxSize !== undefined && maxSize < 1) {\n\t\tthrow new RangeError(\"maxSize must be >= 1\");\n\t}\n}\n\nfunction copyMap<K, V>(m: ReadonlyMap<K, V>): Map<K, V> {\n\treturn new Map(m);\n}\n\nfunction readMap<K, V>(node: Node<ReadonlyMap<K, V>>): ReadonlyMap<K, V> {\n\treturn node.cache ?? new Map<K, V>();\n}\n\nfunction readArray<T>(node: Node<ReadonlyArray<T>>): ReadonlyArray<T> {\n\treturn node.cache ?? [];\n}\n\nfunction cosineSimilarity(a: readonly number[], b: readonly number[]): number {\n\tconst n = Math.max(a.length, b.length);\n\tlet dot = 0;\n\tlet na = 0;\n\tlet nb = 0;\n\tfor (let i = 0; i < n; i += 1) {\n\t\tconst av = a[i] ?? 0;\n\t\tconst bv = b[i] ?? 0;\n\t\tdot += av * bv;\n\t\tna += av * av;\n\t\tnb += bv * bv;\n\t}\n\tif (na === 0 || nb === 0) return 0;\n\treturn dot / Math.sqrt(na * nb);\n}\n\nexport function lightCollection<T>(opts: LightCollectionOptions = {}): LightCollectionBundle<T> {\n\tconst maxSize = opts.maxSize;\n\tconst policy = opts.policy ?? \"fifo\";\n\tassertMaxSize(maxSize);\n\n\tconst entries = state<ReadonlyMap<string, LightCollectionEntry<T>>>(new Map(), {\n\t\tname: opts.name,\n\t\tdescribeKind: \"state\",\n\t});\n\n\tfunction evictIfNeeded(next: Map<string, LightCollectionEntry<T>>): void {\n\t\tif (maxSize === undefined) return;\n\t\twhile (next.size > maxSize) {\n\t\t\tlet victim: LightCollectionEntry<T> | undefined;\n\t\t\tfor (const entry of next.values()) {\n\t\t\t\tif (!victim) {\n\t\t\t\t\tvictim = entry;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst lhs = policy === \"lru\" ? entry.lastAccessNs : entry.createdAtNs;\n\t\t\t\tconst rhs = policy === \"lru\" ? victim.lastAccessNs : victim.createdAtNs;\n\t\t\t\tif (lhs < rhs) victim = entry;\n\t\t\t}\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim.id);\n\t\t}\n\t}\n\n\tfunction commit(next: Map<string, LightCollectionEntry<T>>): void {\n\t\tentries.down([[DATA, next]]);\n\t}\n\n\treturn {\n\t\tentries,\n\t\tupsert(id, value) {\n\t\t\tconst now = monotonicNs();\n\t\t\tconst current = readMap(entries);\n\t\t\tconst prev = current.get(id);\n\t\t\tconst next = copyMap(current);\n\t\t\tnext.set(id, {\n\t\t\t\tid,\n\t\t\t\tvalue,\n\t\t\t\tcreatedAtNs: prev?.createdAtNs ?? now,\n\t\t\t\tlastAccessNs: now,\n\t\t\t});\n\t\t\tevictIfNeeded(next);\n\t\t\tcommit(next);\n\t\t},\n\t\tremove(id) {\n\t\t\tconst next = copyMap(readMap(entries));\n\t\t\tif (!next.delete(id)) return;\n\t\t\tcommit(next);\n\t\t},\n\t\tclear() {\n\t\t\tif (readMap(entries).size === 0) return;\n\t\t\tcommit(new Map());\n\t\t},\n\t\tget(id) {\n\t\t\tconst current = readMap(entries);\n\t\t\tconst found = current.get(id);\n\t\t\tif (!found) return undefined;\n\t\t\tif (policy === \"lru\") {\n\t\t\t\tconst now = monotonicNs();\n\t\t\t\tconst next = copyMap(current);\n\t\t\t\tnext.set(id, { ...found, lastAccessNs: now });\n\t\t\t\tcommit(next);\n\t\t\t}\n\t\t\treturn found.value;\n\t\t},\n\t\thas(id) {\n\t\t\treturn readMap(entries).has(id);\n\t\t},\n\t};\n}\n\nexport function collection<T>(name: string, opts: CollectionOptions<T> = {}): CollectionGraph<T> {\n\tconst maxSize = opts.maxSize;\n\tconst policy = opts.policy ?? \"lru\";\n\tconst decayRate = opts.decayRate ?? 0;\n\tconst minScore = opts.minScore ?? 0;\n\tconst scoreFn = opts.score ?? (() => 1);\n\tassertMaxSize(maxSize);\n\n\tconst graph = new Graph(name);\n\tconst items = state<ReadonlyMap<string, CollectionEntry<T>>>(new Map(), {\n\t\tname: \"items\",\n\t\tdescribeKind: \"state\",\n\t});\n\tconst ranked = derived(\n\t\t[items],\n\t\t([snapshot]) => {\n\t\t\tconst typed = (snapshot ?? new Map()) as ReadonlyMap<string, CollectionEntry<T>>;\n\t\t\tconst now = monotonicNs();\n\t\t\tconst out = [...typed.values()].map((entry) => {\n\t\t\t\tconst ageSeconds = (now - entry.lastAccessNs) / 1_000_000_000;\n\t\t\t\treturn {\n\t\t\t\t\t...entry,\n\t\t\t\t\tscore: decay(entry.baseScore, ageSeconds, decayRate, minScore),\n\t\t\t\t};\n\t\t\t});\n\t\t\tout.sort((a, b) => b.score - a.score || b.lastAccessNs - a.lastAccessNs);\n\t\t\treturn out;\n\t\t},\n\t\t{ name: \"ranked\", describeKind: \"derived\" },\n\t);\n\tconst size = derived(\n\t\t[items],\n\t\t([snapshot]) => ((snapshot ?? new Map()) as ReadonlyMap<string, CollectionEntry<T>>).size,\n\t\t{\n\t\t\tname: \"size\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: 0,\n\t\t},\n\t);\n\tvoid ranked.subscribe(() => undefined);\n\tvoid size.subscribe(() => undefined);\n\n\tgraph.add(\"items\", items);\n\tgraph.add(\"ranked\", ranked);\n\tgraph.add(\"size\", size);\n\n\tfunction effective(entry: CollectionEntry<T>, now: number): number {\n\t\tconst ageSeconds = (now - entry.lastAccessNs) / 1_000_000_000;\n\t\treturn decay(entry.baseScore, ageSeconds, decayRate, minScore);\n\t}\n\n\tfunction evictIfNeeded(next: Map<string, CollectionEntry<T>>): void {\n\t\tif (maxSize === undefined) return;\n\t\twhile (next.size > maxSize) {\n\t\t\tconst now = monotonicNs();\n\t\t\tlet victim: CollectionEntry<T> | undefined;\n\t\t\tlet victimScore = Number.POSITIVE_INFINITY;\n\t\t\tfor (const entry of next.values()) {\n\t\t\t\tconst score = effective(entry, now);\n\t\t\t\tif (score < victimScore) {\n\t\t\t\t\tvictim = entry;\n\t\t\t\t\tvictimScore = score;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (score === victimScore && victim) {\n\t\t\t\t\tconst lhs = policy === \"lru\" ? entry.lastAccessNs : entry.createdAtNs;\n\t\t\t\t\tconst rhs = policy === \"lru\" ? victim.lastAccessNs : victim.createdAtNs;\n\t\t\t\t\tif (lhs < rhs) victim = entry;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim.id);\n\t\t}\n\t}\n\n\tfunction commit(next: Map<string, CollectionEntry<T>>): void {\n\t\titems.down([[DATA, next]]);\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tupsert(id: string, value: T, upsertOpts?: { score?: number }) {\n\t\t\tconst now = monotonicNs();\n\t\t\tconst current = readMap(items);\n\t\t\tconst prev = current.get(id);\n\t\t\tconst baseScore = upsertOpts?.score ?? scoreFn(value);\n\t\t\tconst next = copyMap(current);\n\t\t\tnext.set(id, {\n\t\t\t\tid,\n\t\t\t\tvalue,\n\t\t\t\tbaseScore,\n\t\t\t\tcreatedAtNs: prev?.createdAtNs ?? now,\n\t\t\t\tlastAccessNs: now,\n\t\t\t});\n\t\t\tevictIfNeeded(next);\n\t\t\tcommit(next);\n\t\t},\n\t\tremove(id: string) {\n\t\t\tconst next = copyMap(readMap(items));\n\t\t\tif (!next.delete(id)) return;\n\t\t\tcommit(next);\n\t\t},\n\t\tclear() {\n\t\t\tif (readMap(items).size === 0) return;\n\t\t\tcommit(new Map());\n\t\t},\n\t\tgetItem(id: string): CollectionEntry<T> | undefined {\n\t\t\tconst current = readMap(items);\n\t\t\tconst found = current.get(id);\n\t\t\tif (!found) return undefined;\n\t\t\tif (policy === \"lru\") {\n\t\t\t\tconst next = copyMap(current);\n\t\t\t\tnext.set(id, { ...found, lastAccessNs: monotonicNs() });\n\t\t\t\tcommit(next);\n\t\t\t}\n\t\t\treturn found;\n\t\t},\n\t}) as CollectionGraph<T>;\n\treturn out;\n}\n\nexport function vectorIndex<TMeta>(opts: VectorIndexOptions<TMeta> = {}): VectorIndexBundle<TMeta> {\n\tconst backend = opts.backend ?? \"flat\";\n\tconst dimension = opts.dimension;\n\tlet hnsw: HnswAdapter<TMeta> | undefined;\n\tif (backend === \"hnsw\") {\n\t\thnsw = opts.hnswFactory?.();\n\t\tif (!hnsw) {\n\t\t\tthrow new Error(\n\t\t\t\t'vectorIndex backend \"hnsw\" requires an optional dependency adapter; install your HNSW package and provide `hnswFactory`.',\n\t\t\t);\n\t\t}\n\t}\n\n\tconst entries = state<ReadonlyMap<string, VectorRecord<TMeta>>>(new Map(), {\n\t\tdescribeKind: \"state\",\n\t\tname: \"vector-index\",\n\t});\n\n\tfunction assertDimension(vector: readonly number[]): void {\n\t\tif (dimension !== undefined && vector.length !== dimension) {\n\t\t\tthrow new RangeError(\n\t\t\t\t`vector dimension mismatch: expected ${dimension}, got ${vector.length}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tfunction commit(next: Map<string, VectorRecord<TMeta>>): void {\n\t\tentries.down([[DATA, next]]);\n\t}\n\n\treturn {\n\t\tbackend,\n\t\tentries,\n\t\tupsert(id, vector, meta) {\n\t\t\tassertDimension(vector);\n\t\t\tconst next = copyMap(readMap(entries));\n\t\t\tnext.set(id, { id, vector: [...vector], meta });\n\t\t\tif (backend === \"hnsw\") hnsw!.upsert(id, vector, meta);\n\t\t\tcommit(next);\n\t\t},\n\t\tremove(id) {\n\t\t\tconst next = copyMap(readMap(entries));\n\t\t\tif (!next.delete(id)) return;\n\t\t\tif (backend === \"hnsw\") hnsw!.remove(id);\n\t\t\tcommit(next);\n\t\t},\n\t\tclear() {\n\t\t\tif (readMap(entries).size === 0) return;\n\t\t\tif (backend === \"hnsw\") hnsw!.clear();\n\t\t\tcommit(new Map());\n\t\t},\n\t\tsearch(query, k = 5) {\n\t\t\tassertDimension(query);\n\t\t\tif (k <= 0) return [];\n\t\t\tif (backend === \"hnsw\") return hnsw!.search(query, k);\n\t\t\tconst ranked = [...readMap(entries).values()]\n\t\t\t\t.map((row) => ({\n\t\t\t\t\tid: row.id,\n\t\t\t\t\tscore: cosineSimilarity(query, row.vector),\n\t\t\t\t\tmeta: row.meta,\n\t\t\t\t}))\n\t\t\t\t.sort((a, b) => b.score - a.score)\n\t\t\t\t.slice(0, k);\n\t\t\treturn ranked;\n\t\t},\n\t};\n}\n\nexport function knowledgeGraph<TEntity, TRelation extends string = string>(\n\tname: string,\n): KnowledgeGraphGraph<TEntity, TRelation> {\n\tconst graph = new Graph(name);\n\tconst entities = state<ReadonlyMap<string, TEntity>>(new Map(), {\n\t\tname: \"entities\",\n\t\tdescribeKind: \"state\",\n\t});\n\tconst edges = state<ReadonlyArray<KnowledgeEdge<TRelation>>>([], {\n\t\tname: \"edges\",\n\t\tdescribeKind: \"state\",\n\t});\n\tconst adjacency = derived(\n\t\t[edges],\n\t\t([rows]) => {\n\t\t\tconst typed = (rows ?? []) as ReadonlyArray<KnowledgeEdge<TRelation>>;\n\t\t\tconst out = new Map<string, ReadonlyArray<KnowledgeEdge<TRelation>>>();\n\t\t\tfor (const edge of typed) {\n\t\t\t\tconst prev = out.get(edge.from) ?? [];\n\t\t\t\tout.set(edge.from, Object.freeze([...prev, edge]));\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\t{ name: \"adjacency\", describeKind: \"derived\", initial: new Map() },\n\t);\n\tvoid adjacency.subscribe(() => undefined);\n\n\tgraph.add(\"entities\", entities);\n\tgraph.add(\"edges\", edges);\n\tgraph.add(\"adjacency\", adjacency);\n\n\tfunction commitEntities(next: Map<string, TEntity>): void {\n\t\tentities.down([[DATA, next]]);\n\t}\n\n\tfunction commitEdges(next: ReadonlyArray<KnowledgeEdge<TRelation>>): void {\n\t\tedges.down([[DATA, next]]);\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tupsertEntity(id: string, value: TEntity) {\n\t\t\tconst next = copyMap(readMap(entities));\n\t\t\tnext.set(id, value);\n\t\t\tcommitEntities(next);\n\t\t},\n\t\tremoveEntity(id: string) {\n\t\t\tconst nextEntities = copyMap(readMap(entities));\n\t\t\tconst existed = nextEntities.delete(id);\n\t\t\tconst currentEdges = readArray(edges);\n\t\t\tconst nextEdges = currentEdges.filter((edge) => edge.from !== id && edge.to !== id);\n\t\t\tif (!existed && nextEdges.length === currentEdges.length) return;\n\t\t\tcommitEntities(nextEntities);\n\t\t\tcommitEdges(nextEdges);\n\t\t},\n\t\tlink(from: string, to: string, relation: TRelation, weight = 1) {\n\t\t\tconst key = `${from}\\u0000${to}\\u0000${relation}`;\n\t\t\tconst currentEdges = readArray(edges);\n\t\t\tconst existing = new Set(\n\t\t\t\tcurrentEdges.map((edge) => `${edge.from}\\u0000${edge.to}\\u0000${edge.relation}`),\n\t\t\t);\n\t\t\tconst next = [...currentEdges];\n\t\t\tif (existing.has(key)) {\n\t\t\t\tfor (let i = 0; i < next.length; i += 1) {\n\t\t\t\t\tconst edge = next[i]!;\n\t\t\t\t\tif (edge.from === from && edge.to === to && edge.relation === relation) {\n\t\t\t\t\t\tnext[i] = { ...edge, weight };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnext.push({ from, to, relation, weight });\n\t\t\t}\n\t\t\tcommitEdges(next);\n\t\t},\n\t\tunlink(from: string, to: string, relation?: TRelation) {\n\t\t\tconst currentEdges = readArray(edges);\n\t\t\tconst next = currentEdges.filter((edge) =>\n\t\t\t\trelation === undefined\n\t\t\t\t\t? !(edge.from === from && edge.to === to)\n\t\t\t\t\t: !(edge.from === from && edge.to === to && edge.relation === relation),\n\t\t\t);\n\t\t\tif (next.length === currentEdges.length) return;\n\t\t\tcommitEdges(next);\n\t\t},\n\t\trelated(id: string, relation?: TRelation): ReadonlyArray<KnowledgeEdge<TRelation>> {\n\t\t\treturn readArray(edges).filter(\n\t\t\t\t(edge) =>\n\t\t\t\t\t(edge.from === id || edge.to === id) &&\n\t\t\t\t\t(relation === undefined || edge.relation === relation),\n\t\t\t);\n\t\t},\n\t}) as KnowledgeGraphGraph<TEntity, TRelation>;\n\treturn out;\n}\n"],"mappings":"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","names":["out"]}
|