pi-okf-memory 0.1.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/lib/client.js ADDED
@@ -0,0 +1,417 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "pi-okf-memory",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ //#region \0rolldown/runtime.js
8
+ var __create = Object.create;
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
+ var __getOwnPropNames = Object.getOwnPropertyNames;
12
+ var __getProtoOf = Object.getPrototypeOf;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
16
+ key = keys[i];
17
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
18
+ get: ((k) => from[k]).bind(null, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
25
+ value: mod,
26
+ enumerable: true
27
+ }) : target, mod));
28
+ //#endregion
29
+ let react = require("react");
30
+ react = __toESM(react, 1);
31
+ //#region src/client/index.tsx
32
+ /**
33
+ * okf-memory client(浏览器半,dsh 专用) — 记忆图谱会话标签页。
34
+ *
35
+ * 契约:
36
+ * - package.json 声明 dsh.client { platform:'web', inject:[client服务] }
37
+ * - ctx.slots.inject("conversation.view", ...) 注册对话视图标签
38
+ * - fetch 后端 /okf-graph → 力导向渲染
39
+ * - 交互:滚轮缩放 / 拖拽平移 / 拖节点 / 悬停显示详情 / 搜索命中+神经传导
40
+ *
41
+ * 只保留「记忆图谱」一个视图。
42
+ */
43
+ const inject = ["slots", "locale"];
44
+ const NS = "okf-memory";
45
+ const TYPE_COLORS = {
46
+ Fact: "#2f7bff",
47
+ Preference: "#ffd400",
48
+ Decision: "#ff2d55",
49
+ Method: "#00e66e",
50
+ Insight: "#c04dff",
51
+ Idea: "#ff7a00",
52
+ Lesson: "#c8d1dd",
53
+ TechChoice: "#00e5ff",
54
+ Other: "#9aa7b8"
55
+ };
56
+ function MemoryGraphView() {
57
+ const [graph, setGraph] = react.default.useState(null);
58
+ const [error, setError] = react.default.useState(null);
59
+ const [query, setQuery] = react.default.useState("");
60
+ const canvasRef = react.default.useRef(null);
61
+ const layoutRef = react.default.useRef([]);
62
+ const viewRef = react.default.useRef({
63
+ zoom: 1,
64
+ panX: 0,
65
+ panY: 0
66
+ });
67
+ const dragRef = react.default.useRef({
68
+ id: null,
69
+ offX: 0,
70
+ offY: 0,
71
+ panning: false,
72
+ lastX: 0,
73
+ lastY: 0
74
+ });
75
+ const hoverRef = react.default.useRef(null);
76
+ const [, forceRender] = react.default.useState(0);
77
+ const queryRef = react.default.useRef("");
78
+ queryRef.current = query;
79
+ react.default.useEffect(() => {
80
+ fetch("/okf-graph").then((r) => r.json()).then((g) => {
81
+ if (g.error) setError(g.error);
82
+ else setGraph(g);
83
+ }).catch((e) => setError(String(e.message || e)));
84
+ }, []);
85
+ react.default.useEffect(() => {
86
+ if (!graph || layoutRef.current.length) return;
87
+ const maxW = Math.max(...graph.nodes.map((n) => n.weight), 1);
88
+ const n = graph.nodes.length;
89
+ const R = Math.max(120, Math.min(300, 60 + n * 30));
90
+ layoutRef.current = graph.nodes.map((node, i) => {
91
+ const h = hash(node.id);
92
+ const ang = i / n * Math.PI * 2;
93
+ const r = R * (.6 + h % 100 / 100 * .5);
94
+ const x = Math.cos(ang) * r;
95
+ const y = Math.sin(ang) * r;
96
+ return {
97
+ ...node,
98
+ x,
99
+ y,
100
+ vx: 0,
101
+ vy: 0,
102
+ r: 8 + Math.sqrt(node.weight / maxW) * 20
103
+ };
104
+ });
105
+ }, [graph]);
106
+ react.default.useEffect(() => {
107
+ if (!canvasRef.current) return;
108
+ const fit = () => {
109
+ viewRef.current = {
110
+ zoom: 1,
111
+ panX: 0,
112
+ panY: 0
113
+ };
114
+ };
115
+ fit();
116
+ const onResize = () => fit();
117
+ window.addEventListener("resize", onResize);
118
+ return () => window.removeEventListener("resize", onResize);
119
+ }, [graph]);
120
+ react.default.useEffect(() => {
121
+ if (!graph || !canvasRef.current) return;
122
+ const canvas = canvasRef.current;
123
+ let raf = 0;
124
+ const render = () => {
125
+ drawGraph(canvas, graph, queryRef.current, layoutRef, viewRef, hoverRef);
126
+ raf = requestAnimationFrame(render);
127
+ };
128
+ raf = requestAnimationFrame(render);
129
+ return () => cancelAnimationFrame(raf);
130
+ }, [graph]);
131
+ const onWheel = (e) => {
132
+ e.preventDefault();
133
+ const v = viewRef.current;
134
+ const factor = e.deltaY < 0 ? 1.1 : .9;
135
+ v.zoom = Math.min(4, Math.max(.3, v.zoom * factor));
136
+ forceRender((x) => x + 1);
137
+ };
138
+ const onMouseDown = (e) => {
139
+ const canvas = canvasRef.current;
140
+ const rect = canvas.getBoundingClientRect();
141
+ const px = e.clientX - rect.left, py = e.clientY - rect.top;
142
+ const cw = canvas.clientWidth || rect.width, ch = canvas.clientHeight || rect.height;
143
+ const hit = hitTest(px, py, layoutRef.current, viewRef.current, cw, ch);
144
+ if (hit) dragRef.current = {
145
+ id: hit.id,
146
+ offX: hit.x - px,
147
+ offY: hit.y - py,
148
+ panning: false,
149
+ lastX: px,
150
+ lastY: py
151
+ };
152
+ else dragRef.current = {
153
+ id: null,
154
+ offX: 0,
155
+ offY: 0,
156
+ panning: true,
157
+ lastX: px,
158
+ lastY: py
159
+ };
160
+ };
161
+ const onMouseMove = (e) => {
162
+ const canvas = canvasRef.current;
163
+ const rect = canvas.getBoundingClientRect();
164
+ const px = e.clientX - rect.left, py = e.clientY - rect.top;
165
+ const cw = canvas.clientWidth || rect.width, ch = canvas.clientHeight || rect.height;
166
+ const d = dragRef.current;
167
+ if (d.id) {
168
+ const n = layoutRef.current.find((x) => x.id === d.id);
169
+ if (n) {
170
+ const wx = (px - cw / 2 - viewRef.current.panX) / viewRef.current.zoom;
171
+ const wy = (py - ch / 2 - viewRef.current.panY) / viewRef.current.zoom;
172
+ n.x = wx + d.offX;
173
+ n.y = wy + d.offY;
174
+ n.vx = 0;
175
+ n.vy = 0;
176
+ }
177
+ } else if (d.panning) {
178
+ viewRef.current.panX += px - d.lastX;
179
+ viewRef.current.panY += py - d.lastY;
180
+ d.lastX = px;
181
+ d.lastY = py;
182
+ }
183
+ const hover = hitTest(px, py, layoutRef.current, viewRef.current, cw, ch)?.id ?? null;
184
+ if (hover !== hoverRef.current) {
185
+ hoverRef.current = hover;
186
+ forceRender((x) => x + 1);
187
+ }
188
+ };
189
+ const onMouseUp = () => {
190
+ dragRef.current = {
191
+ id: null,
192
+ offX: 0,
193
+ offY: 0,
194
+ panning: false,
195
+ lastX: 0,
196
+ lastY: 0
197
+ };
198
+ };
199
+ if (error) return react.default.createElement("div", { style: p }, "记忆图谱加载失败: " + error);
200
+ if (!graph) return react.default.createElement("div", { style: p }, "加载记忆图谱…");
201
+ const hover = layoutRef.current.find((n) => n.id === hoverRef.current);
202
+ return react.default.createElement("div", { style: {
203
+ padding: "12px",
204
+ position: "relative"
205
+ } }, react.default.createElement("input", {
206
+ value: query,
207
+ onChange: (e) => setQuery(e.target.value),
208
+ placeholder: "🔍 命中记忆(搜标题/类型/标签)…",
209
+ style: {
210
+ width: "100%",
211
+ boxSizing: "border-box",
212
+ padding: "9px 12px",
213
+ marginBottom: "10px",
214
+ borderRadius: "8px",
215
+ border: "1px solid rgba(120,160,200,.3)",
216
+ background: "rgba(20,32,46,.8)",
217
+ color: "#dbe7f3",
218
+ fontSize: "13px",
219
+ outline: "none"
220
+ }
221
+ }), react.default.createElement("div", { style: {
222
+ color: "#8aa4bd",
223
+ fontSize: "12px",
224
+ marginBottom: "8px"
225
+ } }, `${graph.nodes.length} 节点 · ${graph.edges.length} 边 · 滚轮缩放 · 拖拽平移 · 悬停查看详情 · 搜索命中→神经传导`), react.default.createElement("canvas", {
226
+ ref: canvasRef,
227
+ onWheel,
228
+ onMouseDown,
229
+ onMouseMove,
230
+ onMouseUp,
231
+ onMouseLeave: () => {
232
+ hoverRef.current = null;
233
+ forceRender((x) => x + 1);
234
+ },
235
+ style: {
236
+ width: "100%",
237
+ height: "calc(100vh - 200px)",
238
+ display: "block",
239
+ cursor: "crosshair"
240
+ }
241
+ }), hover ? react.default.createElement("div", { style: {
242
+ position: "absolute",
243
+ top: "54px",
244
+ right: "12px",
245
+ background: "rgba(10,18,28,.97)",
246
+ border: "1px solid " + (TYPE_COLORS[hover.type] || "#3b5a77"),
247
+ borderRadius: "8px",
248
+ padding: "9px 12px",
249
+ fontSize: "12px",
250
+ color: "#eaf3fb",
251
+ maxWidth: "320px",
252
+ boxShadow: "0 6px 20px rgba(0,0,0,.45)",
253
+ zIndex: 10
254
+ } }, react.default.createElement("b", null, hover.title), react.default.createElement("span", { style: {
255
+ fontSize: "10px",
256
+ padding: "1px 6px",
257
+ borderRadius: "8px",
258
+ background: (TYPE_COLORS[hover.type] || "#66") + "66",
259
+ color: "#fff",
260
+ marginLeft: "6px"
261
+ } }, hover.type), react.default.createElement("div", { style: {
262
+ color: "#9db8cf",
263
+ marginTop: "4px"
264
+ } }, "权重 " + hover.weight + " · " + hover.state), hover.description ? react.default.createElement("div", { style: {
265
+ color: "#8aa4bd",
266
+ marginTop: "3px"
267
+ } }, hover.description) : null, hover.tags && hover.tags.length ? react.default.createElement("div", { style: {
268
+ color: "#6f8ba5",
269
+ marginTop: "3px",
270
+ fontSize: "11px"
271
+ } }, hover.tags.map((x) => "#" + x).join(" ")) : null) : null);
272
+ }
273
+ const p = {
274
+ padding: "24px",
275
+ color: "#8aa4bd",
276
+ fontFamily: "sans-serif"
277
+ };
278
+ function matches(n, q) {
279
+ const t = q.trim().toLowerCase();
280
+ if (!t) return false;
281
+ return (n.title + " " + n.type + " " + (n.tags || []).join(" ")).toLowerCase().includes(t);
282
+ }
283
+ function activateHits(nodes, edges, hits) {
284
+ const act = new Set(hits);
285
+ const adj = /* @__PURE__ */ new Map();
286
+ edges.forEach((e) => {
287
+ if (!adj.has(e.source)) adj.set(e.source, []);
288
+ if (!adj.has(e.target)) adj.set(e.target, []);
289
+ adj.get(e.source).push(e.target);
290
+ adj.get(e.target).push(e.source);
291
+ });
292
+ const q = [...hits];
293
+ while (q.length) {
294
+ const cur = q.shift();
295
+ (adj.get(cur) || []).forEach((nb) => {
296
+ if (!act.has(nb)) {
297
+ act.add(nb);
298
+ q.push(nb);
299
+ }
300
+ });
301
+ }
302
+ return act;
303
+ }
304
+ function hitTest(px, py, nodes, view, canvasW, canvasH) {
305
+ const wx = (px - canvasW / 2 - view.panX) / view.zoom, wy = (py - canvasH / 2 - view.panY) / view.zoom;
306
+ for (let i = nodes.length - 1; i >= 0; i--) {
307
+ const n = nodes[i];
308
+ const dx = n.x - wx, dy = n.y - wy;
309
+ if (dx * dx + dy * dy < (n.r + 6) * (n.r + 6)) return n;
310
+ }
311
+ return null;
312
+ }
313
+ function drawGraph(canvas, graph, query, layoutRef, viewRef, hoverRef) {
314
+ const dpr = window.devicePixelRatio || 1;
315
+ const W = canvas.clientWidth || 800, H = canvas.clientHeight || 500;
316
+ canvas.width = W * dpr;
317
+ canvas.height = H * dpr;
318
+ const ctx = canvas.getContext("2d");
319
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
320
+ const view = viewRef.current;
321
+ Math.max(...graph.nodes.map((n) => n.weight), 1);
322
+ const nodes = layoutRef.current;
323
+ const byId = new Map(nodes.map((n) => [n.id, n]));
324
+ const edges = graph.edges.filter((e) => byId.has(e.source) && byId.has(e.target));
325
+ const hits = /* @__PURE__ */ new Set();
326
+ if (query.trim()) graph.nodes.forEach((n) => {
327
+ if (matches(n, query)) hits.add(n.id);
328
+ });
329
+ const active = activateHits(graph.nodes, graph.edges, hits);
330
+ const tx = (x) => W / 2 + x * view.zoom + view.panX;
331
+ const ty = (y) => H / 2 + y * view.zoom + view.panY;
332
+ ctx.fillStyle = "#13233a";
333
+ ctx.fillRect(0, 0, W, H);
334
+ edges.forEach((e) => {
335
+ const a = byId.get(e.source), b = byId.get(e.target);
336
+ const isActive = active.has(e.source) || active.has(e.target);
337
+ ctx.beginPath();
338
+ ctx.moveTo(tx(a.x), ty(a.y));
339
+ ctx.lineTo(tx(b.x), ty(b.y));
340
+ ctx.strokeStyle = isActive ? "rgba(126,195,255,.5)" : "rgba(120,160,200,.18)";
341
+ ctx.lineWidth = 1 / view.zoom;
342
+ ctx.stroke();
343
+ });
344
+ const t = performance.now() / 700;
345
+ nodes.forEach((n) => {
346
+ const c = TYPE_COLORS[n.type] || TYPE_COLORS.Other;
347
+ const isHit = hits.has(n.id), isActive = active.has(n.id);
348
+ const rr = n.r * view.zoom;
349
+ const x = tx(n.x), y = ty(n.y);
350
+ if (isHit) {
351
+ const tp = (t + hash(n.id) % 10) % 1;
352
+ const pr = rr * (1.5 + tp * 1.8);
353
+ ctx.beginPath();
354
+ ctx.arc(x, y, pr, 0, Math.PI * 2);
355
+ ctx.strokeStyle = hexToRgba(c, .8 * (1 - tp));
356
+ ctx.lineWidth = 2.5 / view.zoom;
357
+ ctx.stroke();
358
+ }
359
+ if (isHit || isActive) {
360
+ const rg = ctx.createRadialGradient(x, y, rr * .2, x, y, rr * (isHit ? 2.9 : 2.1));
361
+ rg.addColorStop(0, hexToRgba(c, isHit ? .8 : .45));
362
+ rg.addColorStop(1, "transparent");
363
+ ctx.beginPath();
364
+ ctx.arc(x, y, rr * (isHit ? 2.9 : 2.1), 0, Math.PI * 2);
365
+ ctx.fillStyle = rg;
366
+ ctx.fill();
367
+ }
368
+ ctx.beginPath();
369
+ ctx.arc(x, y, rr, 0, Math.PI * 2);
370
+ ctx.fillStyle = isActive ? isHit ? "#fff" : c : "#13233a";
371
+ ctx.globalAlpha = isActive ? .95 : 1;
372
+ ctx.fill();
373
+ ctx.globalAlpha = 1;
374
+ ctx.beginPath();
375
+ ctx.arc(x, y, rr, 0, Math.PI * 2);
376
+ ctx.strokeStyle = isHit ? "#fff" : isActive ? c : "#33506a";
377
+ ctx.lineWidth = (isHit ? 3.2 : 1.2) / view.zoom;
378
+ ctx.stroke();
379
+ ctx.globalAlpha = 1;
380
+ ctx.fillStyle = isActive ? "#fff" : "#5f7d97";
381
+ ctx.font = `${11 * Math.min(1.4, Math.max(.8, view.zoom))}px sans-serif`;
382
+ ctx.textAlign = "center";
383
+ ctx.fillText(n.title.slice(0, 10), x, y + rr + 12);
384
+ if (isHit) {
385
+ ctx.fillStyle = "#fff";
386
+ ctx.font = `700 ${11 * Math.max(.8, view.zoom)}px sans-serif`;
387
+ ctx.fillText("⚡命中", x, y - rr - 9);
388
+ }
389
+ });
390
+ }
391
+ function hash(s) {
392
+ let h = 0;
393
+ for (let i = 0; i < s.length; i++) h = h * 31 + s.charCodeAt(i) >>> 0;
394
+ return h;
395
+ }
396
+ function hexToRgba(hex, a) {
397
+ const c = hex.replace("#", "");
398
+ return `rgba(${parseInt(c.slice(0, 2), 16)},${parseInt(c.slice(2, 4), 16)},${parseInt(c.slice(4, 6), 16)},${a})`;
399
+ }
400
+ function apply(ctx) {
401
+ ctx.locale.bind(NS);
402
+ ctx.slots.inject("conversation.view", () => ctx.slots.register({
403
+ name: "conversation.view",
404
+ id: "okf-memory",
405
+ order: 30,
406
+ locale: NS,
407
+ label: () => "记忆图谱"
408
+ }, MemoryGraphView));
409
+ }
410
+ //#endregion
411
+ exports.apply = apply;
412
+ exports.inject = inject;
413
+ return module.exports;
414
+ }
415
+ });
416
+
417
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["React"],"sources":["../src/client/index.tsx"],"sourcesContent":["/**\n * okf-memory client(浏览器半,dsh 专用) — 记忆图谱会话标签页。\n *\n * 契约:\n * - package.json 声明 dsh.client { platform:'web', inject:[client服务] }\n * - ctx.slots.inject(\"conversation.view\", ...) 注册对话视图标签\n * - fetch 后端 /okf-graph → 力导向渲染\n * - 交互:滚轮缩放 / 拖拽平移 / 拖节点 / 悬停显示详情 / 搜索命中+神经传导\n *\n * 只保留「记忆图谱」一个视图。\n */\nimport React from \"react\";\n\nexport const inject = [\"slots\", \"locale\"];\nconst NS = \"okf-memory\";\n\nconst TYPE_COLORS: Record<string, string> = {\n Fact: \"#2f7bff\", Preference: \"#ffd400\", Decision: \"#ff2d55\", Method: \"#00e66e\",\n Insight: \"#c04dff\", Idea: \"#ff7a00\", Lesson: \"#c8d1dd\", TechChoice: \"#00e5ff\", Other: \"#9aa7b8\",\n};\ntype GraphNode = { id: string; title: string; type: string; weight: number; state: string; description?: string; tags?: string[] };\ntype GraphEdge = { source: string; target: string };\n\ntype LayoutNode = GraphNode & { x: number; y: number; vx: number; vy: number; r: number };\n\nfunction MemoryGraphView() {\n const [graph, setGraph] = React.useState<{ nodes: GraphNode[]; edges: GraphEdge[] } | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n const [query, setQuery] = React.useState(\"\");\n const canvasRef = React.useRef<HTMLCanvasElement | null>(null);\n const layoutRef = React.useRef<LayoutNode[]>([]);\n const viewRef = React.useRef({ zoom: 1, panX: 0, panY: 0 });\n const dragRef = React.useRef<{ id: string | null; offX: number; offY: number; panning: boolean; lastX: number; lastY: number }>({ id: null, offX: 0, offY: 0, panning: false, lastX: 0, lastY: 0 });\n const hoverRef = React.useRef<string | null>(null);\n const [, forceRender] = React.useState(0); // 触发 tooltip 更新\n\n const queryRef = React.useRef(\"\");\n queryRef.current = query;\n\n React.useEffect(() => {\n fetch(\"/okf-graph\")\n .then((r) => r.json())\n .then((g) => { if (g.error) setError(g.error); else setGraph(g); })\n .catch((e) => setError(String(e.message || e)));\n }, []);\n\n // 初始化布局(一次,稳定):世界坐标以(0,0)为中心,节点分布半径随数量自适应\n React.useEffect(() => {\n if (!graph || layoutRef.current.length) return;\n const maxW = Math.max(...graph.nodes.map((n) => n.weight), 1);\n const n = graph.nodes.length;\n const R = Math.max(120, Math.min(300, 60 + n * 30));\n layoutRef.current = graph.nodes.map((node, i) => {\n const h = hash(node.id);\n const ang = (i / n) * Math.PI * 2; // 环形均布 + 轻微抖动\n const r = R * (0.6 + ((h % 100) / 100) * 0.5);\n const x = Math.cos(ang) * r;\n const y = Math.sin(ang) * r;\n return { ...node, x, y, vx: 0, vy: 0, r: 8 + Math.sqrt(node.weight / maxW) * 20 };\n });\n }, [graph]);\n\n // 缩放画布尺寸变化时重置 zoom\n React.useEffect(() => {\n const canvas = canvasRef.current; if (!canvas) return;\n const fit = () => { viewRef.current = { zoom: 1, panX: 0, panY: 0 }; };\n fit();\n const onResize = () => fit();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, [graph]);\n\n // rAF 动画循环\n React.useEffect(() => {\n if (!graph || !canvasRef.current) return;\n const canvas = canvasRef.current;\n let raf = 0;\n const render = () => { drawGraph(canvas, graph, queryRef.current, layoutRef, viewRef, hoverRef); raf = requestAnimationFrame(render); };\n raf = requestAnimationFrame(render);\n return () => cancelAnimationFrame(raf);\n }, [graph]);\n\n const onWheel = (e: React.WheelEvent) => {\n e.preventDefault();\n const v = viewRef.current;\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n v.zoom = Math.min(4, Math.max(0.3, v.zoom * factor));\n forceRender((x) => x + 1);\n };\n const onMouseDown = (e: React.MouseEvent) => {\n const canvas = canvasRef.current!; const rect = canvas.getBoundingClientRect();\n const px = (e.clientX - rect.left), py = (e.clientY - rect.top);\n const cw = canvas.clientWidth || rect.width, ch = canvas.clientHeight || rect.height;\n const hit = hitTest(px, py, layoutRef.current, viewRef.current, cw, ch);\n if (hit) { dragRef.current = { id: hit.id, offX: hit.x - px, offY: hit.y - py, panning: false, lastX: px, lastY: py }; }\n else { dragRef.current = { id: null, offX: 0, offY: 0, panning: true, lastX: px, lastY: py }; }\n };\n const onMouseMove = (e: React.MouseEvent) => {\n const canvas = canvasRef.current!; const rect = canvas.getBoundingClientRect();\n const px = (e.clientX - rect.left), py = (e.clientY - rect.top);\n const cw = canvas.clientWidth || rect.width, ch = canvas.clientHeight || rect.height;\n const d = dragRef.current;\n if (d.id) {\n const n = layoutRef.current.find((x) => x.id === d.id);\n if (n) {\n // 拖节点:用世界坐标(逆变换),offX 为世界坐标内偏移\n const wx = (px - cw / 2 - viewRef.current.panX) / viewRef.current.zoom;\n const wy = (py - ch / 2 - viewRef.current.panY) / viewRef.current.zoom;\n n.x = wx + d.offX; n.y = wy + d.offY; n.vx = 0; n.vy = 0;\n }\n } else if (d.panning) {\n viewRef.current.panX += px - d.lastX; viewRef.current.panY += py - d.lastY;\n d.lastX = px; d.lastY = py;\n }\n const hover = hitTest(px, py, layoutRef.current, viewRef.current, cw, ch)?.id ?? null;\n if (hover !== hoverRef.current) { hoverRef.current = hover; forceRender((x) => x + 1); }\n };\n const onMouseUp = () => { dragRef.current = { id: null, offX: 0, offY: 0, panning: false, lastX: 0, lastY: 0 }; };\n\n if (error) return React.createElement(\"div\", { style: p }, \"记忆图谱加载失败: \" + error);\n if (!graph) return React.createElement(\"div\", { style: p }, \"加载记忆图谱…\");\n\n const hover = layoutRef.current.find((n) => n.id === hoverRef.current);\n return React.createElement(\"div\", { style: { padding: \"12px\", position: \"relative\" } },\n React.createElement(\"input\", {\n value: query, onChange: (e) => setQuery(e.target.value),\n placeholder: \"🔍 命中记忆(搜标题/类型/标签)…\",\n style: { width: \"100%\", boxSizing: \"border-box\", padding: \"9px 12px\", marginBottom: \"10px\", borderRadius: \"8px\", border: \"1px solid rgba(120,160,200,.3)\", background: \"rgba(20,32,46,.8)\", color: \"#dbe7f3\", fontSize: \"13px\", outline: \"none\" },\n }),\n React.createElement(\"div\", { style: { color: \"#8aa4bd\", fontSize: \"12px\", marginBottom: \"8px\" } },\n `${graph.nodes.length} 节点 · ${graph.edges.length} 边 · 滚轮缩放 · 拖拽平移 · 悬停查看详情 · 搜索命中→神经传导`),\n React.createElement(\"canvas\", { ref: canvasRef, onWheel, onMouseDown, onMouseMove, onMouseUp, onMouseLeave: () => { hoverRef.current = null; forceRender((x) => x + 1); }, style: { width: \"100%\", height: \"calc(100vh - 200px)\", display: \"block\", cursor: \"crosshair\" } }),\n hover\n ? React.createElement(\"div\", { style: { position: \"absolute\", top: \"54px\", right: \"12px\", background: \"rgba(10,18,28,.97)\", border: \"1px solid \" + (TYPE_COLORS[hover.type] || \"#3b5a77\"), borderRadius: \"8px\", padding: \"9px 12px\", fontSize: \"12px\", color: \"#eaf3fb\", maxWidth: \"320px\", boxShadow: \"0 6px 20px rgba(0,0,0,.45)\", zIndex: 10 } },\n React.createElement(\"b\", null, hover.title), React.createElement(\"span\", { style: { fontSize: \"10px\", padding: \"1px 6px\", borderRadius: \"8px\", background: (TYPE_COLORS[hover.type] || \"#66\") + \"66\", color: \"#fff\", marginLeft: \"6px\" } }, hover.type),\n React.createElement(\"div\", { style: { color: \"#9db8cf\", marginTop: \"4px\" } }, \"权重 \" + hover.weight + \" · \" + hover.state),\n hover.description ? React.createElement(\"div\", { style: { color: \"#8aa4bd\", marginTop: \"3px\" } }, hover.description) : null,\n (hover.tags && hover.tags.length) ? React.createElement(\"div\", { style: { color: \"#6f8ba5\", marginTop: \"3px\", fontSize: \"11px\" } }, hover.tags.map((x) => \"#\" + x).join(\" \")) : null,\n )\n : null,\n );\n}\nconst p: React.CSSProperties = { padding: \"24px\", color: \"#8aa4bd\", fontFamily: \"sans-serif\" };\n\nfunction matches(n: GraphNode, q: string): boolean {\n const t = q.trim().toLowerCase(); if (!t) return false;\n return (n.title + \" \" + n.type + \" \" + (n.tags || []).join(\" \")).toLowerCase().includes(t);\n}\nfunction activateHits(nodes: GraphNode[], edges: GraphEdge[], hits: Set<string>): Set<string> {\n const act = new Set<string>(hits);\n const adj = new Map<string, string[]>();\n edges.forEach((e) => { if (!adj.has(e.source)) adj.set(e.source, []); if (!adj.has(e.target)) adj.set(e.target, []); adj.get(e.source)!.push(e.target); adj.get(e.target)!.push(e.source); });\n const q = [...hits];\n while (q.length) { const cur = q.shift()!; (adj.get(cur) || []).forEach((nb) => { if (!act.has(nb)) { act.add(nb); q.push(nb); } }); }\n return act;\n}\n\nfunction hitTest(px: number, py: number, nodes: LayoutNode[], view: { zoom: number; panX: number; panY: number }, canvasW: number, canvasH: number) {\n // 屏幕坐标 → 世界坐标(世界原点在画布中心 W/2,H/2)\n const wx = (px - canvasW / 2 - view.panX) / view.zoom, wy = (py - canvasH / 2 - view.panY) / view.zoom;\n for (let i = nodes.length - 1; i >= 0; i--) { const n = nodes[i]; const dx = n.x - wx, dy = n.y - wy; if (dx * dx + dy * dy < (n.r + 6) * (n.r + 6)) return n; }\n return null;\n}\n\nfunction drawGraph(canvas: HTMLCanvasElement, graph: { nodes: GraphNode[]; edges: GraphEdge[] }, query: string, layoutRef: React.MutableRefObject<LayoutNode[]>, viewRef: React.MutableRefObject<{ zoom: number; panX: number; panY: number }>, hoverRef: React.MutableRefObject<string | null>) {\n const dpr = window.devicePixelRatio || 1;\n const W = canvas.clientWidth || 800, H = canvas.clientHeight || 500;\n canvas.width = W * dpr; canvas.height = H * dpr;\n const ctx = canvas.getContext(\"2d\")!; ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n const view = viewRef.current;\n\n const maxW = Math.max(...graph.nodes.map((n) => n.weight), 1);\n const nodes = layoutRef.current;\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const edges = graph.edges.filter((e) => byId.has(e.source) && byId.has(e.target));\n\n const hits = new Set<string>();\n if (query.trim()) graph.nodes.forEach((n) => { if (matches(n, query)) hits.add(n.id); });\n const active = activateHits(graph.nodes, graph.edges, hits);\n\n // 世界原点在画布中心:tx(x)=W/2 + x*zoom + panX\n const tx = (x: number) => W / 2 + x * view.zoom + view.panX;\n const ty = (y: number) => H / 2 + y * view.zoom + view.panY;\n\n ctx.fillStyle = \"#13233a\"; ctx.fillRect(0, 0, W, H);\n\n // 边\n edges.forEach((e) => {\n const a = byId.get(e.source)!, b = byId.get(e.target)!;\n const isActive = active.has(e.source) || active.has(e.target);\n ctx.beginPath(); ctx.moveTo(tx(a.x), ty(a.y)); ctx.lineTo(tx(b.x), ty(b.y));\n ctx.strokeStyle = isActive ? \"rgba(126,195,255,.5)\" : \"rgba(120,160,200,.18)\"; ctx.lineWidth = 1 / view.zoom; ctx.stroke();\n });\n\n const t = performance.now() / 700;\n nodes.forEach((n) => {\n const c = TYPE_COLORS[n.type] || TYPE_COLORS.Other;\n const isHit = hits.has(n.id), isActive = active.has(n.id);\n const rr = n.r * view.zoom;\n const x = tx(n.x), y = ty(n.y);\n if (isHit) {\n const tp = (t + hash(n.id) % 10) % 1;\n const pr = rr * (1.5 + tp * 1.8);\n ctx.beginPath(); ctx.arc(x, y, pr, 0, Math.PI * 2); ctx.strokeStyle = hexToRgba(c, 0.8 * (1 - tp)); ctx.lineWidth = 2.5 / view.zoom; ctx.stroke();\n }\n if (isHit || isActive) {\n const rg = ctx.createRadialGradient(x, y, rr * 0.2, x, y, rr * (isHit ? 2.9 : 2.1));\n rg.addColorStop(0, hexToRgba(c, isHit ? 0.8 : 0.45)); rg.addColorStop(1, \"transparent\");\n ctx.beginPath(); ctx.arc(x, y, rr * (isHit ? 2.9 : 2.1), 0, Math.PI * 2); ctx.fillStyle = rg; ctx.fill();\n }\n ctx.beginPath(); ctx.arc(x, y, rr, 0, Math.PI * 2); ctx.fillStyle = isActive ? (isHit ? \"#fff\" : c) : \"#13233a\"; ctx.globalAlpha = isActive ? 0.95 : 1; ctx.fill(); ctx.globalAlpha = 1;\n ctx.beginPath(); ctx.arc(x, y, rr, 0, Math.PI * 2); ctx.strokeStyle = isHit ? \"#fff\" : (isActive ? c : \"#33506a\"); ctx.lineWidth = (isHit ? 3.2 : 1.2) / view.zoom; ctx.stroke();\n ctx.globalAlpha = 1;\n // 标签(缩放时字号随 zoom 微调,避免太小)\n ctx.fillStyle = isActive ? \"#fff\" : \"#5f7d97\"; ctx.font = `${11 * Math.min(1.4, Math.max(0.8, view.zoom))}px sans-serif`; ctx.textAlign = \"center\";\n ctx.fillText(n.title.slice(0, 10), x, y + rr + 12);\n if (isHit) { ctx.fillStyle = \"#fff\"; ctx.font = `700 ${11 * Math.max(0.8, view.zoom)}px sans-serif`; ctx.fillText(\"⚡命中\", x, y - rr - 9); }\n });\n}\n\nfunction hash(s: string): number { let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0; return h; }\nfunction hexToRgba(hex: string, a: number): string { const c = hex.replace(\"#\", \"\"); const r = parseInt(c.slice(0, 2), 16), g = parseInt(c.slice(2, 4), 16), b = parseInt(c.slice(4, 6), 16); return `rgba(${r},${g},${b},${a})`; }\n\nexport function apply(ctx: { slots: { inject: (name: string, factory: () => unknown) => void; register: (spec: Record<string, unknown>, component: unknown) => unknown }; locale: { bind: (ns: string) => (key: string) => string } }): void {\n ctx.locale.bind(NS);\n ctx.slots.inject(\"conversation.view\", () =>\n ctx.slots.register(\n { name: \"conversation.view\", id: \"okf-memory\", order: 30, locale: NS, label: () => \"记忆图谱\" },\n MemoryGraphView,\n ),\n );\n}\n"],"mappings":"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"}