memorix 1.2.0 → 1.2.2
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 +30 -1
- package/README.md +18 -4
- package/README.zh-CN.md +18 -4
- package/TEAM.md +86 -86
- package/dist/cli/index.js +15919 -14055
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1997 -1021
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.d.ts +1 -1
- package/dist/maintenance-runner.js +8481 -8005
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +30 -1
- package/dist/sdk.d.ts +7 -2
- package/dist/sdk.js +2022 -1024
- package/dist/sdk.js.map +1 -1
- package/dist/types.d.ts +49 -1
- package/dist/types.js.map +1 -1
- package/docs/1.2.2-MEMORY-CONTROL-PLANE.md +434 -0
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +4 -0
- package/docs/API_REFERENCE.md +27 -5
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/DEVELOPMENT.md +4 -0
- package/docs/README.md +1 -1
- package/docs/SETUP.md +7 -1
- package/docs/dev-log/progress.txt +91 -11
- package/docs/knowledge/workflows/memorix-release.md +57 -0
- package/package.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/src/audit/index.ts +156 -156
- package/src/cli/command-guide.ts +192 -0
- package/src/cli/commands/audit-list.ts +89 -89
- package/src/cli/commands/audit.ts +9 -4
- package/src/cli/commands/background.ts +659 -659
- package/src/cli/commands/cleanup.ts +5 -1
- package/src/cli/commands/codegraph.ts +17 -8
- package/src/cli/commands/context.ts +3 -2
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/explain.ts +9 -3
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +75 -61
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/identity.ts +116 -0
- package/src/cli/commands/ingest-commit.ts +153 -153
- package/src/cli/commands/ingest-image.ts +71 -69
- package/src/cli/commands/ingest-log.ts +180 -180
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/knowledge.ts +40 -0
- package/src/cli/commands/lock.ts +93 -92
- package/src/cli/commands/memory.ts +58 -21
- package/src/cli/commands/message.ts +123 -118
- package/src/cli/commands/operator-shared.ts +98 -3
- package/src/cli/commands/poll.ts +74 -64
- package/src/cli/commands/purge-all-memory.ts +85 -85
- package/src/cli/commands/purge-project-memory.ts +83 -83
- package/src/cli/commands/reasoning.ts +135 -121
- package/src/cli/commands/retention.ts +9 -4
- package/src/cli/commands/serve-http.ts +22 -43
- package/src/cli/commands/serve-shared.ts +118 -118
- package/src/cli/commands/session.ts +29 -3
- package/src/cli/commands/setup.ts +9 -3
- package/src/cli/commands/skills.ts +124 -119
- package/src/cli/commands/status.ts +4 -3
- package/src/cli/commands/task.ts +193 -184
- package/src/cli/commands/team.ts +14 -10
- package/src/cli/commands/transfer.ts +108 -55
- package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
- package/src/cli/identity.ts +89 -0
- package/src/cli/index.ts +96 -19
- package/src/cli/invocation.ts +115 -0
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/Sidebar.tsx +179 -179
- package/src/cli/tui/chat-service.ts +41 -18
- package/src/cli/tui/data.ts +23 -44
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/tui/markdown-render.tsx +371 -371
- package/src/cli/tui/operator-context.ts +60 -0
- package/src/cli/tui/use-mouse.ts +157 -157
- package/src/cli/tui/useNavigation.ts +56 -56
- package/src/cli/tui/views/MemoryView.tsx +10 -8
- package/src/cli/update-checker.ts +211 -211
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/codegraph/auto-context.ts +34 -17
- package/src/codegraph/context-pack.ts +1 -0
- package/src/codegraph/current-facts.ts +19 -1
- package/src/codegraph/project-context.ts +2 -0
- package/src/codegraph/task-lens.ts +49 -5
- package/src/compact/engine.ts +26 -10
- package/src/compact/index-format.ts +25 -2
- package/src/compact/token-budget.ts +74 -74
- package/src/dashboard/project-classification.ts +64 -64
- package/src/dashboard/server.ts +58 -52
- package/src/embedding/fastembed-provider.ts +142 -142
- package/src/embedding/transformers-provider.ts +111 -111
- package/src/git/extractor.ts +209 -209
- package/src/git/hooks-path.ts +85 -85
- package/src/hooks/admission.ts +117 -0
- package/src/hooks/handler.ts +98 -91
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/significance-filter.ts +250 -250
- package/src/knowledge/claims.ts +51 -1
- package/src/knowledge/context-assembly.ts +97 -0
- package/src/knowledge/types.ts +1 -0
- package/src/knowledge/workflows.ts +34 -3
- package/src/knowledge/workset.ts +179 -10
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/provider.ts +885 -885
- package/src/llm/quality.ts +248 -248
- package/src/memory/admission.ts +57 -0
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/auto-relations.ts +21 -0
- package/src/memory/consolidation.ts +13 -2
- package/src/memory/disclosure-policy.ts +140 -135
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/export-import.ts +11 -3
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/formation/extract.ts +361 -361
- package/src/memory/formation/index.ts +417 -417
- package/src/memory/formation/resolve.ts +344 -344
- package/src/memory/formation/types.ts +315 -315
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph-context.ts +8 -2
- package/src/memory/graph-scope.ts +46 -0
- package/src/memory/graph.ts +197 -197
- package/src/memory/observations.ts +162 -4
- package/src/memory/quality-audit.ts +2 -0
- package/src/memory/refs.ts +94 -94
- package/src/memory/retention.ts +22 -2
- package/src/memory/secret-filter.ts +79 -79
- package/src/memory/session.ts +5 -2
- package/src/memory/visibility.ts +80 -0
- package/src/multimodal/image-loader.ts +143 -143
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/spawn-helper.ts +286 -286
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/context-compact.ts +188 -188
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +378 -340
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/orchestrate/verify-gate.ts +33 -10
- package/src/orchestrate/worktree.ts +232 -232
- package/src/project/aliases.ts +374 -374
- package/src/project/detector.ts +268 -268
- package/src/rules/adapters/claude-code.ts +99 -99
- package/src/rules/adapters/codex.ts +97 -97
- package/src/rules/adapters/copilot.ts +124 -124
- package/src/rules/adapters/cursor.ts +114 -114
- package/src/rules/adapters/kiro.ts +126 -126
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/adapters/windsurf.ts +83 -83
- package/src/rules/syncer.ts +235 -235
- package/src/runtime/control-plane-maintenance.ts +1 -0
- package/src/runtime/isolated-maintenance.ts +1 -0
- package/src/runtime/lifecycle.ts +18 -0
- package/src/runtime/maintenance-jobs.ts +1 -0
- package/src/runtime/maintenance-runner.ts +2 -0
- package/src/runtime/project-maintenance.ts +89 -0
- package/src/sdk.ts +334 -304
- package/src/search/intent-detector.ts +289 -289
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/server.ts +334 -93
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/orama-store.ts +61 -6
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/store/sqlite-db.ts +23 -1
- package/src/store/sqlite-store.ts +12 -2
- package/src/team/event-bus.ts +76 -76
- package/src/team/file-locks.ts +173 -173
- package/src/team/handoff.ts +168 -161
- package/src/team/messages.ts +203 -203
- package/src/team/poll.ts +132 -132
- package/src/team/tasks.ts +211 -211
- package/src/types.ts +51 -0
- package/src/wiki/generator.ts +2 -0
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
- package/src/workspace/workflow-sync.ts +131 -131
package/src/memory/graph.ts
CHANGED
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Knowledge Graph Manager
|
|
3
|
-
*
|
|
4
|
-
* Manages the Entity-Relation knowledge graph.
|
|
5
|
-
* Source: MCP Official Memory Server v0.6.3 (complete rewrite with same API).
|
|
6
|
-
*
|
|
7
|
-
* Key differences from official implementation:
|
|
8
|
-
* - Uses per-project JSONL files (official uses single file)
|
|
9
|
-
* - Async initialization with persistence layer
|
|
10
|
-
* - Project-scoped operations
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import type { Entity, Relation, KnowledgeGraph } from '../types.js';
|
|
14
|
-
import { initGraphStore, getGraphStore } from '../store/graph-store.js';
|
|
15
|
-
|
|
16
|
-
export class KnowledgeGraphManager {
|
|
17
|
-
private entities: Entity[] = [];
|
|
18
|
-
private relations: Relation[] = [];
|
|
19
|
-
private projectDir: string;
|
|
20
|
-
private initialized = false;
|
|
21
|
-
/** Index: lowercase entity name → Entity for O(1) lookups */
|
|
22
|
-
private entityIndex = new Map<string, Entity>();
|
|
23
|
-
|
|
24
|
-
constructor(projectDir: string) {
|
|
25
|
-
this.projectDir = projectDir;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Rebuild the entity name index */
|
|
29
|
-
private rebuildIndex(): void {
|
|
30
|
-
this.entityIndex.clear();
|
|
31
|
-
for (const e of this.entities) {
|
|
32
|
-
this.entityIndex.set(e.name.toLowerCase(), e);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Load graph from SQLite on first access */
|
|
37
|
-
async init(): Promise<void> {
|
|
38
|
-
if (this.initialized) return;
|
|
39
|
-
await initGraphStore(this.projectDir);
|
|
40
|
-
const store = getGraphStore();
|
|
41
|
-
this.entities = store.loadEntities();
|
|
42
|
-
this.relations = store.loadRelations();
|
|
43
|
-
this.rebuildIndex();
|
|
44
|
-
this.initialized = true;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Find entity by name (case-insensitive, O(1)) */
|
|
48
|
-
findEntityByName(name: string): Entity | undefined {
|
|
49
|
-
return this.entityIndex.get(name.toLowerCase());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** Get all entity names as a Set (lowercase, for fast membership checks) */
|
|
53
|
-
getEntityNameSet(): Set<string> {
|
|
54
|
-
return new Set(this.entityIndex.keys());
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Persist current state to SQLite */
|
|
58
|
-
private async save(): Promise<void> {
|
|
59
|
-
const store = getGraphStore();
|
|
60
|
-
store.replaceAll(this.entities, this.relations);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Create new entities (skip duplicates by name) */
|
|
64
|
-
async createEntities(entities: Entity[]): Promise<Entity[]> {
|
|
65
|
-
await this.init();
|
|
66
|
-
const newEntities = entities.filter(
|
|
67
|
-
(e) => !this.entityIndex.has(e.name.toLowerCase()),
|
|
68
|
-
);
|
|
69
|
-
this.entities.push(...newEntities);
|
|
70
|
-
if (newEntities.length > 0) this.rebuildIndex();
|
|
71
|
-
await this.save();
|
|
72
|
-
return newEntities;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Create new relations (skip duplicates) */
|
|
76
|
-
async createRelations(relations: Relation[]): Promise<Relation[]> {
|
|
77
|
-
await this.init();
|
|
78
|
-
const newRelations = relations.filter(
|
|
79
|
-
(r) =>
|
|
80
|
-
!this.relations.some(
|
|
81
|
-
(existing) =>
|
|
82
|
-
existing.from === r.from &&
|
|
83
|
-
existing.to === r.to &&
|
|
84
|
-
existing.relationType === r.relationType,
|
|
85
|
-
),
|
|
86
|
-
);
|
|
87
|
-
this.relations.push(...newRelations);
|
|
88
|
-
await this.save();
|
|
89
|
-
return newRelations;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Add observations to existing entities */
|
|
93
|
-
async addObservations(
|
|
94
|
-
observations: { entityName: string; contents: string[] }[],
|
|
95
|
-
): Promise<{ entityName: string; addedObservations: string[] }[]> {
|
|
96
|
-
await this.init();
|
|
97
|
-
const results = observations.map((o) => {
|
|
98
|
-
const entity = this.entities.find((e) => e.name === o.entityName);
|
|
99
|
-
if (!entity) {
|
|
100
|
-
throw new Error(`Entity with name ${o.entityName} not found`);
|
|
101
|
-
}
|
|
102
|
-
const newObs = o.contents.filter((c) => !entity.observations.includes(c));
|
|
103
|
-
entity.observations.push(...newObs);
|
|
104
|
-
return { entityName: o.entityName, addedObservations: newObs };
|
|
105
|
-
});
|
|
106
|
-
await this.save();
|
|
107
|
-
return results;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** Delete entities and their associated relations */
|
|
111
|
-
async deleteEntities(entityNames: string[]): Promise<void> {
|
|
112
|
-
await this.init();
|
|
113
|
-
this.entities = this.entities.filter((e) => !entityNames.includes(e.name));
|
|
114
|
-
this.relations = this.relations.filter(
|
|
115
|
-
(r) => !entityNames.includes(r.from) && !entityNames.includes(r.to),
|
|
116
|
-
);
|
|
117
|
-
this.rebuildIndex();
|
|
118
|
-
await this.save();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Delete specific observations from entities */
|
|
122
|
-
async deleteObservations(
|
|
123
|
-
deletions: { entityName: string; observations: string[] }[],
|
|
124
|
-
): Promise<void> {
|
|
125
|
-
await this.init();
|
|
126
|
-
for (const d of deletions) {
|
|
127
|
-
const entity = this.entities.find((e) => e.name === d.entityName);
|
|
128
|
-
if (entity) {
|
|
129
|
-
entity.observations = entity.observations.filter(
|
|
130
|
-
(o) => !d.observations.includes(o),
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
await this.save();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** Delete specific relations */
|
|
138
|
-
async deleteRelations(relations: Relation[]): Promise<void> {
|
|
139
|
-
await this.init();
|
|
140
|
-
this.relations = this.relations.filter(
|
|
141
|
-
(r) =>
|
|
142
|
-
!relations.some(
|
|
143
|
-
(del) =>
|
|
144
|
-
r.from === del.from &&
|
|
145
|
-
r.to === del.to &&
|
|
146
|
-
r.relationType === del.relationType,
|
|
147
|
-
),
|
|
148
|
-
);
|
|
149
|
-
await this.save();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** Get all entity names (for Formation Pipeline entity resolution) */
|
|
153
|
-
getEntityNames(): string[] {
|
|
154
|
-
return this.entities.map(e => e.name);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** Read the entire graph */
|
|
158
|
-
async readGraph(): Promise<KnowledgeGraph> {
|
|
159
|
-
await this.init();
|
|
160
|
-
return { entities: this.entities, relations: this.relations };
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** Search nodes by query string (upgraded from official's basic includes) */
|
|
164
|
-
async searchNodes(query: string): Promise<KnowledgeGraph> {
|
|
165
|
-
await this.init();
|
|
166
|
-
const lowerQuery = query.toLowerCase();
|
|
167
|
-
|
|
168
|
-
const filteredEntities = this.entities.filter(
|
|
169
|
-
(e) =>
|
|
170
|
-
e.name.toLowerCase().includes(lowerQuery) ||
|
|
171
|
-
e.entityType.toLowerCase().includes(lowerQuery) ||
|
|
172
|
-
e.observations.some((o) => o.toLowerCase().includes(lowerQuery)),
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
const filteredNames = new Set(filteredEntities.map((e) => e.name));
|
|
176
|
-
|
|
177
|
-
const filteredRelations = this.relations.filter(
|
|
178
|
-
(r) => filteredNames.has(r.from) && filteredNames.has(r.to),
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
return { entities: filteredEntities, relations: filteredRelations };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/** Open specific nodes by name */
|
|
185
|
-
async openNodes(names: string[]): Promise<KnowledgeGraph> {
|
|
186
|
-
await this.init();
|
|
187
|
-
|
|
188
|
-
const filteredEntities = this.entities.filter((e) => names.includes(e.name));
|
|
189
|
-
const filteredNames = new Set(filteredEntities.map((e) => e.name));
|
|
190
|
-
|
|
191
|
-
const filteredRelations = this.relations.filter(
|
|
192
|
-
(r) => filteredNames.has(r.from) && filteredNames.has(r.to),
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
return { entities: filteredEntities, relations: filteredRelations };
|
|
196
|
-
}
|
|
197
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Knowledge Graph Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages the Entity-Relation knowledge graph.
|
|
5
|
+
* Source: MCP Official Memory Server v0.6.3 (complete rewrite with same API).
|
|
6
|
+
*
|
|
7
|
+
* Key differences from official implementation:
|
|
8
|
+
* - Uses per-project JSONL files (official uses single file)
|
|
9
|
+
* - Async initialization with persistence layer
|
|
10
|
+
* - Project-scoped operations
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { Entity, Relation, KnowledgeGraph } from '../types.js';
|
|
14
|
+
import { initGraphStore, getGraphStore } from '../store/graph-store.js';
|
|
15
|
+
|
|
16
|
+
export class KnowledgeGraphManager {
|
|
17
|
+
private entities: Entity[] = [];
|
|
18
|
+
private relations: Relation[] = [];
|
|
19
|
+
private projectDir: string;
|
|
20
|
+
private initialized = false;
|
|
21
|
+
/** Index: lowercase entity name → Entity for O(1) lookups */
|
|
22
|
+
private entityIndex = new Map<string, Entity>();
|
|
23
|
+
|
|
24
|
+
constructor(projectDir: string) {
|
|
25
|
+
this.projectDir = projectDir;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Rebuild the entity name index */
|
|
29
|
+
private rebuildIndex(): void {
|
|
30
|
+
this.entityIndex.clear();
|
|
31
|
+
for (const e of this.entities) {
|
|
32
|
+
this.entityIndex.set(e.name.toLowerCase(), e);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Load graph from SQLite on first access */
|
|
37
|
+
async init(): Promise<void> {
|
|
38
|
+
if (this.initialized) return;
|
|
39
|
+
await initGraphStore(this.projectDir);
|
|
40
|
+
const store = getGraphStore();
|
|
41
|
+
this.entities = store.loadEntities();
|
|
42
|
+
this.relations = store.loadRelations();
|
|
43
|
+
this.rebuildIndex();
|
|
44
|
+
this.initialized = true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Find entity by name (case-insensitive, O(1)) */
|
|
48
|
+
findEntityByName(name: string): Entity | undefined {
|
|
49
|
+
return this.entityIndex.get(name.toLowerCase());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Get all entity names as a Set (lowercase, for fast membership checks) */
|
|
53
|
+
getEntityNameSet(): Set<string> {
|
|
54
|
+
return new Set(this.entityIndex.keys());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Persist current state to SQLite */
|
|
58
|
+
private async save(): Promise<void> {
|
|
59
|
+
const store = getGraphStore();
|
|
60
|
+
store.replaceAll(this.entities, this.relations);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Create new entities (skip duplicates by name) */
|
|
64
|
+
async createEntities(entities: Entity[]): Promise<Entity[]> {
|
|
65
|
+
await this.init();
|
|
66
|
+
const newEntities = entities.filter(
|
|
67
|
+
(e) => !this.entityIndex.has(e.name.toLowerCase()),
|
|
68
|
+
);
|
|
69
|
+
this.entities.push(...newEntities);
|
|
70
|
+
if (newEntities.length > 0) this.rebuildIndex();
|
|
71
|
+
await this.save();
|
|
72
|
+
return newEntities;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Create new relations (skip duplicates) */
|
|
76
|
+
async createRelations(relations: Relation[]): Promise<Relation[]> {
|
|
77
|
+
await this.init();
|
|
78
|
+
const newRelations = relations.filter(
|
|
79
|
+
(r) =>
|
|
80
|
+
!this.relations.some(
|
|
81
|
+
(existing) =>
|
|
82
|
+
existing.from === r.from &&
|
|
83
|
+
existing.to === r.to &&
|
|
84
|
+
existing.relationType === r.relationType,
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
this.relations.push(...newRelations);
|
|
88
|
+
await this.save();
|
|
89
|
+
return newRelations;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Add observations to existing entities */
|
|
93
|
+
async addObservations(
|
|
94
|
+
observations: { entityName: string; contents: string[] }[],
|
|
95
|
+
): Promise<{ entityName: string; addedObservations: string[] }[]> {
|
|
96
|
+
await this.init();
|
|
97
|
+
const results = observations.map((o) => {
|
|
98
|
+
const entity = this.entities.find((e) => e.name === o.entityName);
|
|
99
|
+
if (!entity) {
|
|
100
|
+
throw new Error(`Entity with name ${o.entityName} not found`);
|
|
101
|
+
}
|
|
102
|
+
const newObs = o.contents.filter((c) => !entity.observations.includes(c));
|
|
103
|
+
entity.observations.push(...newObs);
|
|
104
|
+
return { entityName: o.entityName, addedObservations: newObs };
|
|
105
|
+
});
|
|
106
|
+
await this.save();
|
|
107
|
+
return results;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Delete entities and their associated relations */
|
|
111
|
+
async deleteEntities(entityNames: string[]): Promise<void> {
|
|
112
|
+
await this.init();
|
|
113
|
+
this.entities = this.entities.filter((e) => !entityNames.includes(e.name));
|
|
114
|
+
this.relations = this.relations.filter(
|
|
115
|
+
(r) => !entityNames.includes(r.from) && !entityNames.includes(r.to),
|
|
116
|
+
);
|
|
117
|
+
this.rebuildIndex();
|
|
118
|
+
await this.save();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Delete specific observations from entities */
|
|
122
|
+
async deleteObservations(
|
|
123
|
+
deletions: { entityName: string; observations: string[] }[],
|
|
124
|
+
): Promise<void> {
|
|
125
|
+
await this.init();
|
|
126
|
+
for (const d of deletions) {
|
|
127
|
+
const entity = this.entities.find((e) => e.name === d.entityName);
|
|
128
|
+
if (entity) {
|
|
129
|
+
entity.observations = entity.observations.filter(
|
|
130
|
+
(o) => !d.observations.includes(o),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
await this.save();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Delete specific relations */
|
|
138
|
+
async deleteRelations(relations: Relation[]): Promise<void> {
|
|
139
|
+
await this.init();
|
|
140
|
+
this.relations = this.relations.filter(
|
|
141
|
+
(r) =>
|
|
142
|
+
!relations.some(
|
|
143
|
+
(del) =>
|
|
144
|
+
r.from === del.from &&
|
|
145
|
+
r.to === del.to &&
|
|
146
|
+
r.relationType === del.relationType,
|
|
147
|
+
),
|
|
148
|
+
);
|
|
149
|
+
await this.save();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Get all entity names (for Formation Pipeline entity resolution) */
|
|
153
|
+
getEntityNames(): string[] {
|
|
154
|
+
return this.entities.map(e => e.name);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Read the entire graph */
|
|
158
|
+
async readGraph(): Promise<KnowledgeGraph> {
|
|
159
|
+
await this.init();
|
|
160
|
+
return { entities: this.entities, relations: this.relations };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Search nodes by query string (upgraded from official's basic includes) */
|
|
164
|
+
async searchNodes(query: string): Promise<KnowledgeGraph> {
|
|
165
|
+
await this.init();
|
|
166
|
+
const lowerQuery = query.toLowerCase();
|
|
167
|
+
|
|
168
|
+
const filteredEntities = this.entities.filter(
|
|
169
|
+
(e) =>
|
|
170
|
+
e.name.toLowerCase().includes(lowerQuery) ||
|
|
171
|
+
e.entityType.toLowerCase().includes(lowerQuery) ||
|
|
172
|
+
e.observations.some((o) => o.toLowerCase().includes(lowerQuery)),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const filteredNames = new Set(filteredEntities.map((e) => e.name));
|
|
176
|
+
|
|
177
|
+
const filteredRelations = this.relations.filter(
|
|
178
|
+
(r) => filteredNames.has(r.from) && filteredNames.has(r.to),
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
return { entities: filteredEntities, relations: filteredRelations };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Open specific nodes by name */
|
|
185
|
+
async openNodes(names: string[]): Promise<KnowledgeGraph> {
|
|
186
|
+
await this.init();
|
|
187
|
+
|
|
188
|
+
const filteredEntities = this.entities.filter((e) => names.includes(e.name));
|
|
189
|
+
const filteredNames = new Set(filteredEntities.map((e) => e.name));
|
|
190
|
+
|
|
191
|
+
const filteredRelations = this.relations.filter(
|
|
192
|
+
(r) => filteredNames.has(r.from) && filteredNames.has(r.to),
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
return { entities: filteredEntities, relations: filteredRelations };
|
|
196
|
+
}
|
|
197
|
+
}
|