@jshookmcp/jshook 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -5
- package/README.zh.md +36 -5
- package/dist/{AntiCheatDetector-S8VRj-dD.mjs → AntiCheatDetector-BNk-EoBt.mjs} +3 -3
- package/dist/{CodeInjector-4Z3ngPoX.mjs → CodeInjector-Cq8q01kp.mjs} +5 -5
- package/dist/ConsoleMonitor-CPVQW1Y-.mjs +2201 -0
- package/dist/{DarwinAPI-B8hg_yhz.mjs → DarwinAPI-BNPxu0RH.mjs} +1 -1
- package/dist/DetailedDataManager-BQQcxh64.mjs +217 -0
- package/dist/EventBus-DgPmwpeu.mjs +141 -0
- package/dist/EvidenceGraphBridge-SFesNera.mjs +153 -0
- package/dist/{ExtensionManager-CZ6IveoV.mjs → ExtensionManager-CWYgw0YW.mjs} +13 -6
- package/dist/{FingerprintManager-BVxFJL2-.mjs → FingerprintManager-gzWtkKuf.mjs} +1 -1
- package/dist/{HardwareBreakpoint-DK1yjWkV.mjs → HardwareBreakpoint-B9gZCdFP.mjs} +3 -3
- package/dist/{HeapAnalyzer-CEbo10xU.mjs → HeapAnalyzer-BLDH0dCv.mjs} +4 -4
- package/dist/HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs +639 -0
- package/dist/InstrumentationSession-CvPC7Jwy.mjs +244 -0
- package/dist/{MemoryController-DdtnBdD4.mjs → MemoryController-CbVdCIJF.mjs} +3 -3
- package/dist/{MemoryScanSession-RMixN3bX.mjs → MemoryScanSession-BsDZbLYm.mjs} +81 -78
- package/dist/{MemoryScanner-QjK4ld0B.mjs → MemoryScanner-Bcpml6II.mjs} +44 -18
- package/dist/{NativeMemoryManager.impl-CB6gJ0NM.mjs → NativeMemoryManager.impl-dZtA1ZGn.mjs} +14 -53
- package/dist/{NativeMemoryManager.utils-BML4q1ry.mjs → NativeMemoryManager.utils-B-FjA2mJ.mjs} +1 -1
- package/dist/{PEAnalyzer-CK0xe0Fs.mjs → PEAnalyzer-D1lzJ_VG.mjs} +2 -2
- package/dist/PageController-Bqm2kZ_X.mjs +417 -0
- package/dist/{PointerChainEngine-Cd73qu5b.mjs → PointerChainEngine-BOhyVsjx.mjs} +4 -4
- package/dist/PrerequisiteError-Dl33Svkz.mjs +20 -0
- package/dist/ResponseBuilder-D3iFYx2N.mjs +143 -0
- package/dist/ReverseEvidenceGraph-Dlsk94LC.mjs +269 -0
- package/dist/ScriptManager-aHHq0X7U.mjs +3000 -0
- package/dist/{Speedhack-CeF0XmEz.mjs → Speedhack-CqdIFlQl.mjs} +2 -2
- package/dist/{StructureAnalyzer-D4GkMduU.mjs → StructureAnalyzer-DhFaPvRO.mjs} +3 -3
- package/dist/ToolCatalog-C0JGZoOm.mjs +582 -0
- package/dist/ToolError-jh9whhMd.mjs +15 -0
- package/dist/ToolProbe-oC7aPrkv.mjs +45 -0
- package/dist/ToolRegistry-BjaF4oNz.mjs +131 -0
- package/dist/ToolRouter.policy-BWV67ZK-.mjs +304 -0
- package/dist/TraceRecorder-DgxyVbdQ.mjs +519 -0
- package/dist/{Win32API-Bc0QnQsN.mjs → Win32API-CePkipZY.mjs} +1 -1
- package/dist/{Win32Debug-DUHt9XUn.mjs → Win32Debug-BvKs-gxc.mjs} +2 -2
- package/dist/WorkflowEngine-CuvkZtWu.mjs +598 -0
- package/dist/analysis-CL9uACt9.mjs +463 -0
- package/dist/antidebug-CqDTB_uk.mjs +1081 -0
- package/dist/artifactRetention-CFEprwPw.mjs +591 -0
- package/dist/artifacts-Bk2-_uPq.mjs +59 -0
- package/dist/betterSqlite3-0pqusHHH.mjs +74 -0
- package/dist/binary-instrument-CXfpx6fT.mjs +979 -0
- package/dist/bind-helpers-xFfRF-qm.mjs +22 -0
- package/dist/boringssl-inspector-BH2D3VKc.mjs +180 -0
- package/dist/browser-BpOr5PEx.mjs +4082 -0
- package/dist/concurrency-Bt0yv1kJ.mjs +41 -0
- package/dist/{constants-CCvsN80K.mjs → constants-B0OANIBL.mjs} +88 -46
- package/dist/coordination-qUbyF8KU.mjs +259 -0
- package/dist/debugger-gnKxRSN0.mjs +1271 -0
- package/dist/definitions-6M-eejaT.mjs +53 -0
- package/dist/definitions-B18eyf0B.mjs +18 -0
- package/dist/definitions-B3QdlrHv.mjs +34 -0
- package/dist/definitions-B4rAvHNZ.mjs +63 -0
- package/dist/definitions-BB_4jnmy.mjs +37 -0
- package/dist/definitions-BMfYXoNC.mjs +43 -0
- package/dist/definitions-Beid2EB3.mjs +27 -0
- package/dist/definitions-C1UvM5Iy.mjs +126 -0
- package/dist/definitions-CXEI7QC72.mjs +216 -0
- package/dist/definitions-C_4r7Fo-2.mjs +14 -0
- package/dist/definitions-CkFDALoa.mjs +26 -0
- package/dist/definitions-Cke7zEb8.mjs +94 -0
- package/dist/definitions-ClJLzsJQ.mjs +25 -0
- package/dist/definitions-Cq-zroAU.mjs +28 -0
- package/dist/definitions-Cy3Sl6gV.mjs +34 -0
- package/dist/definitions-D3VsGcvz.mjs +47 -0
- package/dist/definitions-DVGfrn7y.mjs +96 -0
- package/dist/definitions-LKpC3-nL.mjs +9 -0
- package/dist/definitions-bAhHQJq9.mjs +359 -0
- package/dist/encoding-Bvz5jLRv.mjs +1065 -0
- package/dist/evidence-graph-bridge-C_fv9PuC.mjs +135 -0
- package/dist/{factory-CibqTNC8.mjs → factory-DxlGh9Xf.mjs} +37 -52
- package/dist/graphql-DYWzJ29s.mjs +1026 -0
- package/dist/handlers-9sAbfIg-.mjs +2552 -0
- package/dist/handlers-Bl8zkwz1.mjs +2716 -0
- package/dist/handlers-C67ktuRN.mjs +710 -0
- package/dist/handlers-C87g8oCe.mjs +276 -0
- package/dist/handlers-CTsDAO6p.mjs +681 -0
- package/dist/handlers-Cgyg6c0U.mjs +645 -0
- package/dist/handlers-D6j6yka7.mjs +2124 -0
- package/dist/handlers-DdFzXLvF.mjs +446 -0
- package/dist/handlers-DeLOCd5m.mjs +799 -0
- package/dist/handlers-DlCJN4Td.mjs +757 -0
- package/dist/handlers-DxGIq15_2.mjs +917 -0
- package/dist/handlers-U6L4xhuF.mjs +585 -0
- package/dist/handlers-tB9Mp9ZK.mjs +84 -0
- package/dist/handlers-tiy7EIBp.mjs +572 -0
- package/dist/handlers.impl-DS0d9fUw.mjs +761 -0
- package/dist/hooks-CzCWByww.mjs +898 -0
- package/dist/index.mjs +384 -155
- package/dist/{logger-BmWzC2lM.mjs → logger-Dh_xb7_2.mjs} +14 -6
- package/dist/maintenance-P7ePRXQC.mjs +830 -0
- package/dist/manifest-2ToTpjv8.mjs +106 -0
- package/dist/manifest-3g71z6Bg.mjs +79 -0
- package/dist/manifest-82baTv4U.mjs +45 -0
- package/dist/manifest-B3QVVeBS.mjs +82 -0
- package/dist/manifest-BB2J8IMJ.mjs +149 -0
- package/dist/manifest-BKbgbSiY.mjs +60 -0
- package/dist/manifest-Bcf-TJzH.mjs +848 -0
- package/dist/manifest-BmtZzQiQ2.mjs +45 -0
- package/dist/manifest-Bnd7kqEY.mjs +55 -0
- package/dist/manifest-BqQX6OQC2.mjs +65 -0
- package/dist/manifest-BqrQ4Tpj.mjs +81 -0
- package/dist/manifest-Br4RPFt5.mjs +370 -0
- package/dist/manifest-C5qDjysN.mjs +107 -0
- package/dist/manifest-C9RT5nk32.mjs +34 -0
- package/dist/manifest-CAhOuvSl.mjs +204 -0
- package/dist/manifest-CBYWCUBJ.mjs +51 -0
- package/dist/manifest-CFADCRa1.mjs +37 -0
- package/dist/manifest-CQVhavRF.mjs +114 -0
- package/dist/manifest-CT7zZBV1.mjs +48 -0
- package/dist/manifest-CV12bcrF.mjs +121 -0
- package/dist/manifest-CXsRWjjI.mjs +224 -0
- package/dist/manifest-CZLUCfG02.mjs +95 -0
- package/dist/manifest-D6phHKFd.mjs +131 -0
- package/dist/manifest-DCyjf4n2.mjs +294 -0
- package/dist/manifest-DHsnKgP6.mjs +60 -0
- package/dist/manifest-Df_dliIe.mjs +55 -0
- package/dist/manifest-Dh8WBmEW.mjs +129 -0
- package/dist/manifest-DhKRAT8_.mjs +92 -0
- package/dist/manifest-DlpTj4ic2.mjs +193 -0
- package/dist/manifest-DrbmZcFl2.mjs +253 -0
- package/dist/manifest-DuwHjUa5.mjs +70 -0
- package/dist/manifest-DzwvxPJX.mjs +38 -0
- package/dist/manifest-NXctwWQq.mjs +68 -0
- package/dist/manifest-Sc_0JQ13.mjs +418 -0
- package/dist/manifest-gZ4s_UtG.mjs +96 -0
- package/dist/manifest-qSleDqdO.mjs +1023 -0
- package/dist/modules-C184v-S9.mjs +11365 -0
- package/dist/mojo-ipc-B_H61Afw.mjs +525 -0
- package/dist/network-671Cw6hV.mjs +3346 -0
- package/dist/{artifacts-BbdOMET5.mjs → outputPaths-B1uGmrWZ.mjs} +219 -212
- package/dist/parse-args-BlRjqlkL.mjs +39 -0
- package/dist/platform-WmNn8Sxb.mjs +2070 -0
- package/dist/process-QcbIy5Zq.mjs +1401 -0
- package/dist/proxy-DqNs0bAd.mjs +170 -0
- package/dist/registry-D-6e18lB.mjs +34 -0
- package/dist/response-BQVP-xUn.mjs +28 -0
- package/dist/server/plugin-api.mjs +2 -2
- package/dist/shared-state-board-DV-dpHFJ.mjs +586 -0
- package/dist/sourcemap-Dq8ez8vS.mjs +650 -0
- package/dist/ssrf-policy-ZaUfvhq7.mjs +166 -0
- package/dist/streaming-BUQ0VJsg.mjs +725 -0
- package/dist/tool-builder-DCbIC5Eo.mjs +186 -0
- package/dist/transform-CiYJfNX0.mjs +1007 -0
- package/dist/types-Bx92KJfT.mjs +4 -0
- package/dist/wasm-DQTnHDs4.mjs +531 -0
- package/dist/workflow-f3xJOcjx.mjs +725 -0
- package/package.json +48 -78
- package/dist/ExtensionManager-DqUSOamB.mjs +0 -2
- package/dist/ToolCatalog-CnwmMIw3.mjs +0 -61483
- package/dist/{CacheAdapters-CzFNpD9a.mjs → CacheAdapters-CDe5WPSV.mjs} +0 -0
- package/dist/{StealthVerifier-BzBCFiwx.mjs → StealthVerifier-Bo4T3bz8.mjs} +0 -0
- package/dist/{VersionDetector-CNXcvD46.mjs → VersionDetector-CwVLVdDM.mjs} +0 -0
- package/dist/{formatAddress-ChCSIRWT.mjs → formatAddress-DVkj9kpI.mjs} +0 -0
- package/dist/{types-BBjOqye-.mjs → types-CPhOReNX.mjs} +1 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-CjcI7cDX.mjs";
|
|
2
|
+
//#region src/server/evidence/ReverseEvidenceGraph.ts
|
|
3
|
+
var ReverseEvidenceGraph_exports = /* @__PURE__ */ __exportAll({ ReverseEvidenceGraph: () => ReverseEvidenceGraph });
|
|
4
|
+
let nextId = 1;
|
|
5
|
+
function generateId(prefix) {
|
|
6
|
+
return `${prefix}-${nextId++}`;
|
|
7
|
+
}
|
|
8
|
+
var ReverseEvidenceGraph = class {
|
|
9
|
+
nodes = /* @__PURE__ */ new Map();
|
|
10
|
+
edges = /* @__PURE__ */ new Map();
|
|
11
|
+
eventBus;
|
|
12
|
+
isDirty = false;
|
|
13
|
+
mutationSeq = 0;
|
|
14
|
+
lastPersistedSeq = 0;
|
|
15
|
+
persistNotifier;
|
|
16
|
+
setEventBus(eventBus) {
|
|
17
|
+
this.eventBus = eventBus;
|
|
18
|
+
}
|
|
19
|
+
setPersistNotifier(notify) {
|
|
20
|
+
this.persistNotifier = notify;
|
|
21
|
+
}
|
|
22
|
+
markDirty() {
|
|
23
|
+
this.isDirty = true;
|
|
24
|
+
this.mutationSeq++;
|
|
25
|
+
this.persistNotifier?.();
|
|
26
|
+
}
|
|
27
|
+
commit() {
|
|
28
|
+
if (this.isDirty && this.eventBus) {
|
|
29
|
+
this.isDirty = false;
|
|
30
|
+
this.eventBus.emit("evidence:updated", {
|
|
31
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32
|
+
reason: "Tool execution committed changes"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Add a node to the graph. */
|
|
37
|
+
addNode(type, label, metadata = {}) {
|
|
38
|
+
const node = {
|
|
39
|
+
id: generateId(type),
|
|
40
|
+
type,
|
|
41
|
+
label,
|
|
42
|
+
metadata,
|
|
43
|
+
createdAt: Date.now()
|
|
44
|
+
};
|
|
45
|
+
this.nodes.set(node.id, node);
|
|
46
|
+
this.markDirty();
|
|
47
|
+
return node;
|
|
48
|
+
}
|
|
49
|
+
/** Add a directed edge between two nodes. */
|
|
50
|
+
addEdge(sourceId, targetId, type, metadata) {
|
|
51
|
+
if (!this.nodes.has(sourceId)) throw new Error(`Source node "${sourceId}" not found`);
|
|
52
|
+
if (!this.nodes.has(targetId)) throw new Error(`Target node "${targetId}" not found`);
|
|
53
|
+
const edge = {
|
|
54
|
+
id: generateId("edge"),
|
|
55
|
+
source: sourceId,
|
|
56
|
+
target: targetId,
|
|
57
|
+
type,
|
|
58
|
+
metadata
|
|
59
|
+
};
|
|
60
|
+
this.edges.set(edge.id, edge);
|
|
61
|
+
this.markDirty();
|
|
62
|
+
return edge;
|
|
63
|
+
}
|
|
64
|
+
/** Get a node by ID. */
|
|
65
|
+
getNode(id) {
|
|
66
|
+
return this.nodes.get(id);
|
|
67
|
+
}
|
|
68
|
+
/** Remove a node and all connected edges. */
|
|
69
|
+
removeNode(id) {
|
|
70
|
+
if (!this.nodes.has(id)) return false;
|
|
71
|
+
this.nodes.delete(id);
|
|
72
|
+
for (const [edgeId, edge] of this.edges) if (edge.source === id || edge.target === id) this.edges.delete(edgeId);
|
|
73
|
+
this.markDirty();
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
/** Get all edges originating from a node. */
|
|
77
|
+
getEdgesFrom(nodeId) {
|
|
78
|
+
return [...this.edges.values()].filter((e) => e.source === nodeId);
|
|
79
|
+
}
|
|
80
|
+
/** Get all edges pointing to a node. */
|
|
81
|
+
getEdgesTo(nodeId) {
|
|
82
|
+
return [...this.edges.values()].filter((e) => e.target === nodeId);
|
|
83
|
+
}
|
|
84
|
+
/** Get total node count. */
|
|
85
|
+
get nodeCount() {
|
|
86
|
+
return this.nodes.size;
|
|
87
|
+
}
|
|
88
|
+
/** Get total edge count. */
|
|
89
|
+
get edgeCount() {
|
|
90
|
+
return this.edges.size;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* BFS traversal from a node, following edges in the given direction.
|
|
94
|
+
* Returns all reachable nodes (including the start node).
|
|
95
|
+
*/
|
|
96
|
+
getEvidenceChain(nodeId, direction = "forward") {
|
|
97
|
+
if (!this.nodes.get(nodeId)) return [];
|
|
98
|
+
const visited = /* @__PURE__ */ new Set();
|
|
99
|
+
const queue = [nodeId];
|
|
100
|
+
const result = [];
|
|
101
|
+
while (queue.length > 0) {
|
|
102
|
+
const current = queue.shift();
|
|
103
|
+
if (visited.has(current)) continue;
|
|
104
|
+
visited.add(current);
|
|
105
|
+
const node = this.nodes.get(current);
|
|
106
|
+
if (node) result.push(node);
|
|
107
|
+
const connectedEdges = direction === "forward" ? this.getEdgesFrom(current) : this.getEdgesTo(current);
|
|
108
|
+
for (const edge of connectedEdges) {
|
|
109
|
+
const nextNodeId = direction === "forward" ? edge.target : edge.source;
|
|
110
|
+
if (!visited.has(nextNodeId)) queue.push(nextNodeId);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Find all nodes associated with a URL.
|
|
117
|
+
* Searches request nodes by URL metadata, then returns connected subgraph.
|
|
118
|
+
*/
|
|
119
|
+
queryByUrl(url) {
|
|
120
|
+
const matchingNodes = [...this.nodes.values()].filter((n) => {
|
|
121
|
+
if (n.type === "request" && typeof n.metadata.url === "string") return n.metadata.url.includes(url);
|
|
122
|
+
if (typeof n.metadata.url === "string") return n.metadata.url.includes(url);
|
|
123
|
+
return false;
|
|
124
|
+
});
|
|
125
|
+
const allNodes = /* @__PURE__ */ new Set();
|
|
126
|
+
for (const node of matchingNodes) {
|
|
127
|
+
for (const n of this.getEvidenceChain(node.id, "forward")) allNodes.add(n.id);
|
|
128
|
+
for (const n of this.getEvidenceChain(node.id, "backward")) allNodes.add(n.id);
|
|
129
|
+
}
|
|
130
|
+
return [...allNodes].map((id) => this.nodes.get(id)).filter(Boolean);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find all nodes associated with a function name.
|
|
134
|
+
* Searches function nodes, then returns connected subgraph.
|
|
135
|
+
*/
|
|
136
|
+
queryByFunction(name) {
|
|
137
|
+
const matchingNodes = [...this.nodes.values()].filter((n) => {
|
|
138
|
+
if (n.type === "function" && typeof n.metadata.functionName === "string") return n.metadata.functionName.includes(name);
|
|
139
|
+
if (n.label.includes(name) && (n.type === "function" || n.type === "breakpoint-hook")) return true;
|
|
140
|
+
return false;
|
|
141
|
+
});
|
|
142
|
+
const allNodes = /* @__PURE__ */ new Set();
|
|
143
|
+
for (const node of matchingNodes) {
|
|
144
|
+
for (const n of this.getEvidenceChain(node.id, "forward")) allNodes.add(n.id);
|
|
145
|
+
for (const n of this.getEvidenceChain(node.id, "backward")) allNodes.add(n.id);
|
|
146
|
+
}
|
|
147
|
+
return [...allNodes].map((id) => this.nodes.get(id)).filter(Boolean);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Find all nodes associated with a script ID.
|
|
151
|
+
* Searches script nodes by scriptId metadata, then returns connected subgraph.
|
|
152
|
+
*/
|
|
153
|
+
queryByScriptId(scriptId) {
|
|
154
|
+
const matchingNodes = [...this.nodes.values()].filter((n) => {
|
|
155
|
+
if (n.type === "script" && n.metadata.scriptId === scriptId) return true;
|
|
156
|
+
return false;
|
|
157
|
+
});
|
|
158
|
+
const allNodes = /* @__PURE__ */ new Set();
|
|
159
|
+
for (const node of matchingNodes) {
|
|
160
|
+
for (const n of this.getEvidenceChain(node.id, "forward")) allNodes.add(n.id);
|
|
161
|
+
for (const n of this.getEvidenceChain(node.id, "backward")) allNodes.add(n.id);
|
|
162
|
+
}
|
|
163
|
+
return [...allNodes].map((id) => this.nodes.get(id)).filter(Boolean);
|
|
164
|
+
}
|
|
165
|
+
/** Export the full graph as a JSON snapshot. */
|
|
166
|
+
exportJson() {
|
|
167
|
+
return {
|
|
168
|
+
version: 1,
|
|
169
|
+
nodes: [...this.nodes.values()],
|
|
170
|
+
edges: [...this.edges.values()],
|
|
171
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** Export the graph as a readable Markdown report. */
|
|
175
|
+
exportMarkdown() {
|
|
176
|
+
const lines = [];
|
|
177
|
+
lines.push("# Reverse Evidence Graph Report");
|
|
178
|
+
lines.push("");
|
|
179
|
+
lines.push(`**Exported:** ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
180
|
+
lines.push(`**Nodes:** ${this.nodes.size} | **Edges:** ${this.edges.size}`);
|
|
181
|
+
lines.push("");
|
|
182
|
+
const byType = /* @__PURE__ */ new Map();
|
|
183
|
+
for (const node of this.nodes.values()) {
|
|
184
|
+
const list = byType.get(node.type) ?? [];
|
|
185
|
+
list.push(node);
|
|
186
|
+
byType.set(node.type, list);
|
|
187
|
+
}
|
|
188
|
+
for (const type of [
|
|
189
|
+
"request",
|
|
190
|
+
"initiator-stack",
|
|
191
|
+
"script",
|
|
192
|
+
"function",
|
|
193
|
+
"breakpoint-hook",
|
|
194
|
+
"captured-data",
|
|
195
|
+
"replay-artifact",
|
|
196
|
+
"v8-heap-object",
|
|
197
|
+
"v8-hidden-class",
|
|
198
|
+
"network-request",
|
|
199
|
+
"network-response",
|
|
200
|
+
"canvas-scene-node",
|
|
201
|
+
"canvas-render-node",
|
|
202
|
+
"skia-draw-call",
|
|
203
|
+
"syscall-event",
|
|
204
|
+
"mojo-message",
|
|
205
|
+
"mojo-interface",
|
|
206
|
+
"binary-symbol",
|
|
207
|
+
"binary-function",
|
|
208
|
+
"binary-module",
|
|
209
|
+
"proto-message",
|
|
210
|
+
"proto-state"
|
|
211
|
+
]) {
|
|
212
|
+
const nodes = byType.get(type);
|
|
213
|
+
if (!nodes || nodes.length === 0) continue;
|
|
214
|
+
lines.push(`## ${type} (${nodes.length})`);
|
|
215
|
+
lines.push("");
|
|
216
|
+
for (const node of nodes) {
|
|
217
|
+
lines.push(`### ${node.label}`);
|
|
218
|
+
lines.push(`- **ID:** \`${node.id}\``);
|
|
219
|
+
lines.push(`- **Created:** ${new Date(node.createdAt).toISOString()}`);
|
|
220
|
+
const metaKeys = Object.keys(node.metadata);
|
|
221
|
+
if (metaKeys.length > 0) for (const key of metaKeys) {
|
|
222
|
+
const val = node.metadata[key];
|
|
223
|
+
const display = typeof val === "string" ? val : JSON.stringify(val);
|
|
224
|
+
lines.push(`- **${key}:** ${display}`);
|
|
225
|
+
}
|
|
226
|
+
const outEdges = this.getEdgesFrom(node.id);
|
|
227
|
+
const inEdges = this.getEdgesTo(node.id);
|
|
228
|
+
if (outEdges.length > 0) lines.push(`- **→ Out:** ${outEdges.map((e) => `${e.type} → \`${e.target}\``).join(", ")}`);
|
|
229
|
+
if (inEdges.length > 0) lines.push(`- **← In:** ${inEdges.map((e) => `\`${e.source}\` ${e.type} →`).join(", ")}`);
|
|
230
|
+
lines.push("");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return lines.join("\n");
|
|
234
|
+
}
|
|
235
|
+
getSnapshotSeq() {
|
|
236
|
+
return this.mutationSeq;
|
|
237
|
+
}
|
|
238
|
+
getLastPersistedSeq() {
|
|
239
|
+
return this.lastPersistedSeq;
|
|
240
|
+
}
|
|
241
|
+
markPersisted() {
|
|
242
|
+
this.lastPersistedSeq = this.mutationSeq;
|
|
243
|
+
}
|
|
244
|
+
isPersistDirty() {
|
|
245
|
+
return this.mutationSeq !== this.lastPersistedSeq;
|
|
246
|
+
}
|
|
247
|
+
exportSnapshot() {
|
|
248
|
+
return {
|
|
249
|
+
schemaVersion: 1,
|
|
250
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
251
|
+
graph: this.exportJson()
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
restoreSnapshot(data) {
|
|
255
|
+
if (!data || typeof data !== "object") return;
|
|
256
|
+
const snapshot = data;
|
|
257
|
+
if (snapshot.schemaVersion !== 1 || !snapshot.graph) return;
|
|
258
|
+
const { nodes, edges } = snapshot.graph;
|
|
259
|
+
this.nodes.clear();
|
|
260
|
+
this.edges.clear();
|
|
261
|
+
for (const node of nodes) this.nodes.set(node.id, node);
|
|
262
|
+
for (const edge of edges) this.edges.set(edge.id, edge);
|
|
263
|
+
this.mutationSeq = nodes.length + edges.length;
|
|
264
|
+
this.lastPersistedSeq = this.mutationSeq;
|
|
265
|
+
this.isDirty = false;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
//#endregion
|
|
269
|
+
export { ReverseEvidenceGraph_exports as t };
|