@mastra/rag 2.5.0 → 2.6.0-alpha.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/CHANGELOG.md +26 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-rag-chunking-and-embedding.md +1 -1
- package/dist/docs/references/reference-rag-graph-rag.md +71 -8
- package/dist/docs/references/reference-tools-bedrock-kb-tool.md +1 -1
- package/dist/docs/references/reference-tools-vector-query-tool.md +1 -1
- package/dist/graph-rag/index.d.ts +28 -0
- package/dist/graph-rag/index.d.ts.map +1 -1
- package/dist/index.cjs +45 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @mastra/rag
|
|
2
2
|
|
|
3
|
+
## 2.6.0-alpha.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added `serialize()` and `GraphRAG.deserialize()` so a knowledge graph can be saved and restored instead of rebuilt on every process start. Building a graph compares every chunk against every other chunk, which is slow for large document sets; now you can do that work once and reload the result. ([#21704](https://github.com/mastra-ai/mastra/pull/21704))
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// Before: the graph had to be rebuilt every time
|
|
11
|
+
const graphRag = new GraphRAG(1536, 0.7);
|
|
12
|
+
graphRag.createGraph(documentChunks, embeddings);
|
|
13
|
+
|
|
14
|
+
// After: build once, save the snapshot, and reload it later
|
|
15
|
+
const snapshot = graphRag.serialize();
|
|
16
|
+
await writeFile('./graph.json', JSON.stringify(snapshot));
|
|
17
|
+
|
|
18
|
+
const restored = GraphRAG.deserialize(JSON.parse(await readFile('./graph.json', 'utf8')));
|
|
19
|
+
restored.query({ query: queryEmbedding, topK: 10 });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
A snapshot is plain JSON, so you can store it in any database, file, or cache you already use. Loading a snapshot that does not match the graph's embedding dimension now fails immediately with a clear error instead of later during a query. Closes #3926.
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [[`b0a2a07`](https://github.com/mastra-ai/mastra/commit/b0a2a07800d42bd9823292e7db832374ed084c9c), [`ccbbcd9`](https://github.com/mastra-ai/mastra/commit/ccbbcd974eedff4367a54ed0e24c9ee742ab2f61), [`3f5c6f7`](https://github.com/mastra-ai/mastra/commit/3f5c6f728ea35da344248de9aa070f12849f3aa0), [`77e6b1b`](https://github.com/mastra-ai/mastra/commit/77e6b1bc4c46ce94fe501023fb4393c812ec6be3), [`2e1d098`](https://github.com/mastra-ai/mastra/commit/2e1d0984e325fd319d32ea182f596b3170be3847)]:
|
|
27
|
+
- @mastra/core@1.60.0-alpha.9
|
|
28
|
+
|
|
3
29
|
## 2.5.0
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -127,7 +127,7 @@ const { embeddings } = await embedMany({
|
|
|
127
127
|
})
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
> **Vector Database Compatibility:** When storing embeddings, the vector database index
|
|
130
|
+
> **Vector Database Compatibility:** When storing embeddings, configure the vector database index to match the output size of your embedding model to avoid errors or data corruption from mismatched dimensions.
|
|
131
131
|
|
|
132
132
|
## Example: Complete pipeline
|
|
133
133
|
|
|
@@ -9,10 +9,7 @@ The `GraphRAG` class implements a graph-based approach to retrieval augmented ge
|
|
|
9
9
|
```typescript
|
|
10
10
|
import { GraphRAG } from '@mastra/rag'
|
|
11
11
|
|
|
12
|
-
const graphRag = new GraphRAG(
|
|
13
|
-
dimension: 1536,
|
|
14
|
-
threshold: 0.7,
|
|
15
|
-
})
|
|
12
|
+
const graphRag = new GraphRAG(1536, 0.7)
|
|
16
13
|
|
|
17
14
|
// Create the graph from chunks and embeddings
|
|
18
15
|
graphRag.createGraph(documentChunks, embeddings)
|
|
@@ -88,13 +85,79 @@ Returns an array of `RankedNode` objects, where each node contains:
|
|
|
88
85
|
|
|
89
86
|
**score** (`number`): Combined relevance score from graph traversal
|
|
90
87
|
|
|
88
|
+
### `serialize`
|
|
89
|
+
|
|
90
|
+
Returns a JSON-safe snapshot of the graph so it can be persisted and restored later instead of rebuilt with `createGraph`.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
serialize(): GraphRAGSnapshot
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Returns
|
|
97
|
+
|
|
98
|
+
Returns a `GraphRAGSnapshot` object containing:
|
|
99
|
+
|
|
100
|
+
**version** (`number`): Snapshot format version, used to reject snapshots this version of the class can't load
|
|
101
|
+
|
|
102
|
+
**dimension** (`number`): Dimension of the embedding vectors the graph was built with
|
|
103
|
+
|
|
104
|
+
**threshold** (`number`): Similarity threshold the graph was built with
|
|
105
|
+
|
|
106
|
+
**nodes** (`GraphNode[]`): All nodes in the graph, each including its full embedding
|
|
107
|
+
|
|
108
|
+
**edges** (`GraphEdge[]`): All edges in the graph
|
|
109
|
+
|
|
110
|
+
The snapshot is a deep copy, so mutating it doesn't affect the graph it came from. Every node carries its full embedding, so snapshots are large: a 1,000-node graph built with 1536-dimension embeddings serializes to about 20 MB of JSON. Size your storage column accordingly.
|
|
111
|
+
|
|
112
|
+
### `deserialize`
|
|
113
|
+
|
|
114
|
+
Rebuilds a `GraphRAG` instance from a snapshot produced by `serialize`.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
static deserialize(snapshot: GraphRAGSnapshot): GraphRAG
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Parameters
|
|
121
|
+
|
|
122
|
+
**snapshot** (`GraphRAGSnapshot`): A snapshot previously returned by serialize
|
|
123
|
+
|
|
124
|
+
Throws if the snapshot version is unsupported, if a node embedding doesn't match the snapshot dimension, or if an edge references a node that isn't in the snapshot. A bad snapshot therefore fails at load time instead of during a later query.
|
|
125
|
+
|
|
126
|
+
## Persisting a graph
|
|
127
|
+
|
|
128
|
+
Building a graph is O(n²) in the number of chunks, so rebuilding it on every process start is wasteful. Serialize the graph once and store the snapshot wherever you already keep state. A snapshot is plain JSON, so any store works (a file, a blob column, a key-value cache), and `GraphRAG` doesn't depend on a storage backend.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
132
|
+
import { GraphRAG } from '@mastra/rag'
|
|
133
|
+
import type { GraphRAGSnapshot } from '@mastra/rag'
|
|
134
|
+
|
|
135
|
+
const SNAPSHOT_PATH = './docs-graph.json'
|
|
136
|
+
|
|
137
|
+
async function loadOrBuildGraph() {
|
|
138
|
+
try {
|
|
139
|
+
const snapshot = JSON.parse(await readFile(SNAPSHOT_PATH, 'utf8')) as GraphRAGSnapshot
|
|
140
|
+
return GraphRAG.deserialize(snapshot)
|
|
141
|
+
} catch {
|
|
142
|
+
// No usable snapshot yet, so build the graph from scratch
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const graphRag = new GraphRAG(1536, 0.7)
|
|
146
|
+
graphRag.createGraph(documentChunks, embeddings)
|
|
147
|
+
|
|
148
|
+
await writeFile(SNAPSHOT_PATH, JSON.stringify(graphRag.serialize()))
|
|
149
|
+
|
|
150
|
+
return graphRag
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
A snapshot reflects the chunks it was built from and isn't updated incrementally. When the underlying documents change, build the graph again and store a new snapshot.
|
|
155
|
+
|
|
91
156
|
## Advanced example
|
|
92
157
|
|
|
93
158
|
```typescript
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
threshold: 0.8, // Stricter similarity threshold
|
|
97
|
-
})
|
|
159
|
+
// Stricter similarity threshold
|
|
160
|
+
const graphRag = new GraphRAG(1536, 0.8)
|
|
98
161
|
|
|
99
162
|
// Create graph from chunks and embeddings
|
|
100
163
|
graphRag.createGraph(documentChunks, embeddings)
|
|
@@ -65,7 +65,7 @@ The tool returns an object with:
|
|
|
65
65
|
| ---------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
66
66
|
| `content` | `string` | The text content of the retrieved passage. |
|
|
67
67
|
| `source` | `string \| undefined` | The source URI when Bedrock provides one. Agentic retrieval only includes this field when the result metadata contains `_source_uri`. |
|
|
68
|
-
| `score` | `number \| undefined` | The relevance score returned by standard retrieval
|
|
68
|
+
| `score` | `number \| undefined` | The relevance score returned by standard retrieval, which the agentic API omits from result items. |
|
|
69
69
|
| `metadata` | `Record<string, unknown>` | Additional metadata from the retrieval result. |
|
|
70
70
|
|
|
71
71
|
## Retrieval Modes
|
|
@@ -353,7 +353,7 @@ const response = await agent.generate('Find information about deployment', {
|
|
|
353
353
|
})
|
|
354
354
|
```
|
|
355
355
|
|
|
356
|
-
|
|
356
|
+
Runtime configuration supports these use cases:
|
|
357
357
|
|
|
358
358
|
- Switch between environments (dev/staging/prod)
|
|
359
359
|
- Adjust performance parameters based on load
|
|
@@ -29,6 +29,17 @@ export interface GraphChunk {
|
|
|
29
29
|
export interface GraphEmbedding {
|
|
30
30
|
vector: number[];
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* JSON-safe snapshot of a GraphRAG instance, produced by `serialize()` and
|
|
34
|
+
* restored with `GraphRAG.deserialize()`.
|
|
35
|
+
*/
|
|
36
|
+
export interface GraphRAGSnapshot {
|
|
37
|
+
version: 1;
|
|
38
|
+
dimension: number;
|
|
39
|
+
threshold: number;
|
|
40
|
+
nodes: GraphNode[];
|
|
41
|
+
edges: GraphEdge[];
|
|
42
|
+
}
|
|
32
43
|
export declare class GraphRAG {
|
|
33
44
|
private nodes;
|
|
34
45
|
private edges;
|
|
@@ -40,6 +51,23 @@ export declare class GraphRAG {
|
|
|
40
51
|
getNodes(): GraphNode[];
|
|
41
52
|
getEdges(): GraphEdge[];
|
|
42
53
|
getEdgesByType(type: string): GraphEdge[];
|
|
54
|
+
/**
|
|
55
|
+
* Produce a JSON-safe snapshot of the graph so it can be persisted and
|
|
56
|
+
* restored later instead of rebuilt with `createGraph`.
|
|
57
|
+
*
|
|
58
|
+
* The snapshot is a deep copy, including nested node metadata, so mutating it
|
|
59
|
+
* does not affect this instance.
|
|
60
|
+
* Note that every node carries its full embedding, so snapshots of large
|
|
61
|
+
* graphs can be several megabytes of JSON.
|
|
62
|
+
*/
|
|
63
|
+
serialize(): GraphRAGSnapshot;
|
|
64
|
+
/**
|
|
65
|
+
* Rebuild a GraphRAG instance from a snapshot produced by `serialize()`.
|
|
66
|
+
*
|
|
67
|
+
* @throws if the snapshot version is unsupported, a node embedding does not
|
|
68
|
+
* match the snapshot dimension, or an edge references an unknown node.
|
|
69
|
+
*/
|
|
70
|
+
static deserialize(snapshot: GraphRAGSnapshot): GraphRAG;
|
|
43
71
|
clear(): void;
|
|
44
72
|
updateNodeContent(id: string, newContent: string): void;
|
|
45
73
|
private getNeighbors;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graph-rag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,KAAK,iBAAiB,GAAG,UAAU,CAAC;AACpC,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAGzC,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,GAAE,MAAa,EAAE,SAAS,GAAE,MAAY;IAQ7D,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAW9B,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAe9B,QAAQ,IAAI,SAAS,EAAE;IAKvB,QAAQ,IAAI,SAAS,EAAE;IAIvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAIzC,KAAK,IAAI,IAAI;IAKb,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IASvD,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,gBAAgB;IAgCxB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE;IAuC9D,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,qBAAqB;IA2C7B;;;;;;;;OAQG;IAEH,KAAK,CAAC,EACJ,KAAK,EACL,IAAS,EACT,eAAqB,EACrB,WAAkB,EAClB,MAAM,GACP,EAAE;QACD,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;KACjC,GAAG,UAAU,EAAE;CA+DjB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graph-rag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,KAAK,iBAAiB,GAAG,UAAU,CAAC;AACpC,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAGzC,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAID,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,GAAE,MAAa,EAAE,SAAS,GAAE,MAAY;IAQ7D,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAW9B,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAe9B,QAAQ,IAAI,SAAS,EAAE;IAKvB,QAAQ,IAAI,SAAS,EAAE;IAIvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAIzC;;;;;;;;OAQG;IACH,SAAS,IAAI,gBAAgB;IAc7B;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,QAAQ;IAiCxD,KAAK,IAAI,IAAI;IAKb,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IASvD,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,gBAAgB;IAgCxB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE;IAuC9D,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,qBAAqB;IA2C7B;;;;;;;;OAQG;IAEH,KAAK,CAAC,EACJ,KAAK,EACL,IAAS,EACT,eAAqB,EACrB,WAAkB,EAClB,MAAM,GACP,EAAE;QACD,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;KACjC,GAAG,UAAU,EAAE;CA+DjB"}
|
package/dist/index.cjs
CHANGED
|
@@ -6224,7 +6224,8 @@ async function rerank(results, query, model, options) {
|
|
|
6224
6224
|
}
|
|
6225
6225
|
//#endregion
|
|
6226
6226
|
//#region src/graph-rag/index.ts
|
|
6227
|
-
|
|
6227
|
+
const GRAPH_RAG_SNAPSHOT_VERSION = 1;
|
|
6228
|
+
var GraphRAG = class GraphRAG {
|
|
6228
6229
|
nodes;
|
|
6229
6230
|
edges;
|
|
6230
6231
|
dimension;
|
|
@@ -6259,6 +6260,49 @@ var GraphRAG = class {
|
|
|
6259
6260
|
getEdgesByType(type) {
|
|
6260
6261
|
return this.edges.filter((edge) => edge.type === type);
|
|
6261
6262
|
}
|
|
6263
|
+
/**
|
|
6264
|
+
* Produce a JSON-safe snapshot of the graph so it can be persisted and
|
|
6265
|
+
* restored later instead of rebuilt with `createGraph`.
|
|
6266
|
+
*
|
|
6267
|
+
* The snapshot is a deep copy, including nested node metadata, so mutating it
|
|
6268
|
+
* does not affect this instance.
|
|
6269
|
+
* Note that every node carries its full embedding, so snapshots of large
|
|
6270
|
+
* graphs can be several megabytes of JSON.
|
|
6271
|
+
*/
|
|
6272
|
+
serialize() {
|
|
6273
|
+
return {
|
|
6274
|
+
version: GRAPH_RAG_SNAPSHOT_VERSION,
|
|
6275
|
+
dimension: this.dimension,
|
|
6276
|
+
threshold: this.threshold,
|
|
6277
|
+
nodes: Array.from(this.nodes.values()).map((node) => ({
|
|
6278
|
+
...node,
|
|
6279
|
+
...node.embedding ? { embedding: [...node.embedding] } : {},
|
|
6280
|
+
...node.metadata ? { metadata: structuredClone(node.metadata) } : {}
|
|
6281
|
+
})),
|
|
6282
|
+
edges: this.edges.map((edge) => ({ ...edge }))
|
|
6283
|
+
};
|
|
6284
|
+
}
|
|
6285
|
+
/**
|
|
6286
|
+
* Rebuild a GraphRAG instance from a snapshot produced by `serialize()`.
|
|
6287
|
+
*
|
|
6288
|
+
* @throws if the snapshot version is unsupported, a node embedding does not
|
|
6289
|
+
* match the snapshot dimension, or an edge references an unknown node.
|
|
6290
|
+
*/
|
|
6291
|
+
static deserialize(snapshot) {
|
|
6292
|
+
if (snapshot?.version !== GRAPH_RAG_SNAPSHOT_VERSION) throw new Error(`Unsupported GraphRAG snapshot version: ${snapshot?.version}`);
|
|
6293
|
+
const graph = new GraphRAG(snapshot.dimension, snapshot.threshold);
|
|
6294
|
+
for (const node of snapshot.nodes ?? []) graph.addNode({
|
|
6295
|
+
...node,
|
|
6296
|
+
...node.embedding ? { embedding: [...node.embedding] } : {},
|
|
6297
|
+
...node.metadata ? { metadata: structuredClone(node.metadata) } : {}
|
|
6298
|
+
});
|
|
6299
|
+
for (const edge of snapshot.edges ?? []) {
|
|
6300
|
+
if (!graph.nodes.has(edge.source)) throw new Error(`Edge references unknown node: ${edge.source}`);
|
|
6301
|
+
if (!graph.nodes.has(edge.target)) throw new Error(`Edge references unknown node: ${edge.target}`);
|
|
6302
|
+
}
|
|
6303
|
+
graph.edges = (snapshot.edges ?? []).map((edge) => ({ ...edge }));
|
|
6304
|
+
return graph;
|
|
6305
|
+
}
|
|
6262
6306
|
clear() {
|
|
6263
6307
|
this.nodes.clear();
|
|
6264
6308
|
this.edges = [];
|