mindgraph-mcp 0.14.2 → 0.14.4
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 +8 -2
- package/dist/cli.js +930 -26
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -151,8 +151,14 @@ mindgraph-mcp uninstall-hooks Remove MindGraph-owned hook entries
|
|
|
151
151
|
mindgraph-mcp status Show installation status
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
-
Options: `--api-key <key>`, `--base-url <url>`, `--
|
|
155
|
-
`--project-dir <dir>`, `--harness <name>`, `--help`.
|
|
154
|
+
Options: `--api-key <key>`, `--base-url <url>`, `--agent-id <id>`,
|
|
155
|
+
`--scope user|project`, `--project-dir <dir>`, `--harness <name>`, `--help`.
|
|
156
|
+
|
|
157
|
+
**Teams**: when several people share one org graph, give each member a
|
|
158
|
+
distinct identity — `--agent-id claude-code:<name>` on `install-code` /
|
|
159
|
+
`install-hooks`. Anchored knowledge is shared automatically; distinct agent
|
|
160
|
+
ids keep task leases and resume briefs per-person (identical ids make
|
|
161
|
+
teammates one logical agent, which claims each other's work).
|
|
156
162
|
|
|
157
163
|
## Environment
|
|
158
164
|
|
package/dist/cli.js
CHANGED
|
@@ -26,6 +26,895 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
|
|
29
|
+
// node_modules/mindgraph/dist/index.mjs
|
|
30
|
+
function seg(value) {
|
|
31
|
+
return encodeURIComponent(String(value));
|
|
32
|
+
}
|
|
33
|
+
function createRequestId() {
|
|
34
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
35
|
+
return globalThis.crypto.randomUUID();
|
|
36
|
+
}
|
|
37
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
38
|
+
}
|
|
39
|
+
var MindGraphError, MindGraph;
|
|
40
|
+
var init_dist = __esm({
|
|
41
|
+
"node_modules/mindgraph/dist/index.mjs"() {
|
|
42
|
+
"use strict";
|
|
43
|
+
MindGraphError = class extends Error {
|
|
44
|
+
constructor(message, status, body) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.status = status;
|
|
47
|
+
this.body = body;
|
|
48
|
+
this.name = "MindGraphError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
MindGraph = class {
|
|
52
|
+
constructor(config) {
|
|
53
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
54
|
+
this.headers = { "Content-Type": "application/json" };
|
|
55
|
+
if (config.apiKey) {
|
|
56
|
+
this.headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
57
|
+
} else if (config.jwt) {
|
|
58
|
+
this.headers["Authorization"] = `Bearer ${config.jwt}`;
|
|
59
|
+
}
|
|
60
|
+
if (config.orgId) {
|
|
61
|
+
this.headers["X-MindGraph-Org"] = config.orgId;
|
|
62
|
+
}
|
|
63
|
+
this.telemetrySurface = config.telemetrySurface;
|
|
64
|
+
this.maxRetries = config.maxRetries ?? 3;
|
|
65
|
+
this.retryBackoffMs = config.retryBackoffMs ?? 1e3;
|
|
66
|
+
}
|
|
67
|
+
// ---- HTTP helpers ----
|
|
68
|
+
async request(method, path6, body) {
|
|
69
|
+
const url = `${this.baseUrl}${path6}`;
|
|
70
|
+
const requestId = createRequestId();
|
|
71
|
+
const init = {
|
|
72
|
+
method,
|
|
73
|
+
headers: {
|
|
74
|
+
...this.headers,
|
|
75
|
+
"X-MindGraph-Request-ID": requestId,
|
|
76
|
+
...this.telemetrySurface ? { "X-MindGraph-Surface": this.telemetrySurface } : {}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
if (body !== void 0) {
|
|
80
|
+
init.body = JSON.stringify(body);
|
|
81
|
+
}
|
|
82
|
+
let lastError;
|
|
83
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
84
|
+
const res = await fetch(url, init);
|
|
85
|
+
if (!res.ok) {
|
|
86
|
+
const text2 = await res.text().catch(() => "");
|
|
87
|
+
let parsed;
|
|
88
|
+
try {
|
|
89
|
+
parsed = JSON.parse(text2);
|
|
90
|
+
} catch {
|
|
91
|
+
parsed = text2;
|
|
92
|
+
}
|
|
93
|
+
const err5 = new MindGraphError(
|
|
94
|
+
`${method} ${path6} failed: ${res.status}`,
|
|
95
|
+
res.status,
|
|
96
|
+
parsed
|
|
97
|
+
);
|
|
98
|
+
if (res.status === 503 && attempt < this.maxRetries) {
|
|
99
|
+
lastError = err5;
|
|
100
|
+
const delay = this.retryBackoffMs * 2 ** attempt;
|
|
101
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
throw err5;
|
|
105
|
+
}
|
|
106
|
+
const text = await res.text();
|
|
107
|
+
if (!text) return void 0;
|
|
108
|
+
return JSON.parse(text);
|
|
109
|
+
}
|
|
110
|
+
throw lastError;
|
|
111
|
+
}
|
|
112
|
+
get(path6) {
|
|
113
|
+
return this.request("GET", path6);
|
|
114
|
+
}
|
|
115
|
+
post(path6, body) {
|
|
116
|
+
return this.request("POST", path6, body);
|
|
117
|
+
}
|
|
118
|
+
patch(path6, body) {
|
|
119
|
+
return this.request("PATCH", path6, body);
|
|
120
|
+
}
|
|
121
|
+
del(path6) {
|
|
122
|
+
return this.request("DELETE", path6);
|
|
123
|
+
}
|
|
124
|
+
// ---- Health ----
|
|
125
|
+
async health() {
|
|
126
|
+
return this.get("/health");
|
|
127
|
+
}
|
|
128
|
+
async stats() {
|
|
129
|
+
return this.get("/stats");
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Schema fill-rate report (measure-first tiering): per live node type,
|
|
133
|
+
* the exact live count and sampled per-field fill rates; near-empty
|
|
134
|
+
* fields flagged below 5%. `sample` caps per-type sampling (default
|
|
135
|
+
* 1000); `layer` restricts (e.g. "epistemic").
|
|
136
|
+
*/
|
|
137
|
+
async schemaFillStats(params) {
|
|
138
|
+
const q = new URLSearchParams();
|
|
139
|
+
if (params?.sample !== void 0) q.set("sample", String(params.sample));
|
|
140
|
+
if (params?.layer) q.set("layer", params.layer);
|
|
141
|
+
const qs = q.toString();
|
|
142
|
+
return this.get(`/stats/schema-fill${qs ? `?${qs}` : ""}`);
|
|
143
|
+
}
|
|
144
|
+
// ---- Reality Layer ----
|
|
145
|
+
async capture(req) {
|
|
146
|
+
return this.post("/reality/capture", req);
|
|
147
|
+
}
|
|
148
|
+
async entity(req) {
|
|
149
|
+
return this.post("/reality/entity", req);
|
|
150
|
+
}
|
|
151
|
+
/** Convenience: create or find an entity by label. */
|
|
152
|
+
async findOrCreateEntity(label, props, agentId) {
|
|
153
|
+
return this.post("/reality/entity", {
|
|
154
|
+
action: "create",
|
|
155
|
+
label,
|
|
156
|
+
props: { entity_type: "other", ...props },
|
|
157
|
+
agent_id: agentId
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/** Convenience: create or find a Person entity by label. */
|
|
161
|
+
async findOrCreatePerson(label, props, agentId) {
|
|
162
|
+
return this.findOrCreateEntity(label, { entity_type: "person", ...props }, agentId);
|
|
163
|
+
}
|
|
164
|
+
/** Convenience: create or find an Organization entity by label. */
|
|
165
|
+
async findOrCreateOrganization(label, props, agentId) {
|
|
166
|
+
return this.findOrCreateEntity(label, { entity_type: "organization", ...props }, agentId);
|
|
167
|
+
}
|
|
168
|
+
/** Convenience: create or find a Nation entity by label. */
|
|
169
|
+
async findOrCreateNation(label, props, agentId) {
|
|
170
|
+
return this.findOrCreateEntity(label, { entity_type: "nation", ...props }, agentId);
|
|
171
|
+
}
|
|
172
|
+
/** Convenience: create or find an Event entity by label. */
|
|
173
|
+
async findOrCreateEvent(label, props, agentId) {
|
|
174
|
+
return this.findOrCreateEntity(label, { entity_type: "event", ...props }, agentId);
|
|
175
|
+
}
|
|
176
|
+
/** Convenience: create or find a Place entity by label. */
|
|
177
|
+
async findOrCreatePlace(label, props, agentId) {
|
|
178
|
+
return this.findOrCreateEntity(label, { entity_type: "place", ...props }, agentId);
|
|
179
|
+
}
|
|
180
|
+
/** Convenience: create or find a Concept entity by label. */
|
|
181
|
+
async findOrCreateConcept(label, props, agentId) {
|
|
182
|
+
return this.findOrCreateEntity(label, { entity_type: "concept", ...props }, agentId);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Resolve text to an existing entity via alias matching.
|
|
186
|
+
* Returns `{ uid: string | null }`.
|
|
187
|
+
*/
|
|
188
|
+
async resolveEntity(text, agentId) {
|
|
189
|
+
return this.post("/reality/entity", {
|
|
190
|
+
action: "resolve",
|
|
191
|
+
text,
|
|
192
|
+
agent_id: agentId
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Fuzzy-match text against existing entities.
|
|
197
|
+
* Returns `{ matches: [{ uid, label, score }] }`.
|
|
198
|
+
*/
|
|
199
|
+
async fuzzyResolveEntity(text, limit = 5, agentId) {
|
|
200
|
+
return this.post("/reality/entity", {
|
|
201
|
+
action: "fuzzy_resolve",
|
|
202
|
+
text,
|
|
203
|
+
limit,
|
|
204
|
+
agent_id: agentId
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
// ---- Epistemic Layer ----
|
|
208
|
+
async argue(req) {
|
|
209
|
+
return this.post("/epistemic/argument", req);
|
|
210
|
+
}
|
|
211
|
+
async inquire(req) {
|
|
212
|
+
return this.post("/epistemic/inquiry", req);
|
|
213
|
+
}
|
|
214
|
+
async structure(req) {
|
|
215
|
+
return this.post("/epistemic/structure", req);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Convenience: create a Claim node via the argument endpoint.
|
|
219
|
+
* Returns the full argument response including `claim_uid`.
|
|
220
|
+
*/
|
|
221
|
+
async addClaim(label, content, confidence, agentId) {
|
|
222
|
+
return this.post("/epistemic/argument", {
|
|
223
|
+
claim: {
|
|
224
|
+
label,
|
|
225
|
+
confidence,
|
|
226
|
+
props: { content }
|
|
227
|
+
},
|
|
228
|
+
agent_id: agentId
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Convenience: create an Evidence node attached to a claim via the argument endpoint.
|
|
233
|
+
* If `claimLabel` and `claimConfidence` are provided, also creates the claim.
|
|
234
|
+
*/
|
|
235
|
+
async addEvidence(label, description, agentId) {
|
|
236
|
+
return this.post("/epistemic/argument", {
|
|
237
|
+
claim: { label: `Claim for: ${label}` },
|
|
238
|
+
evidence: [{ label, props: { description } }],
|
|
239
|
+
agent_id: agentId
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
/** Convenience: create an Observation node via the reality capture endpoint. */
|
|
243
|
+
async addObservation(label, description, agentId) {
|
|
244
|
+
return this.post("/reality/capture", {
|
|
245
|
+
action: "observation",
|
|
246
|
+
label,
|
|
247
|
+
summary: description,
|
|
248
|
+
agent_id: agentId
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
// ---- Intent Layer ----
|
|
252
|
+
async commit(req) {
|
|
253
|
+
return this.post("/intent/commitment", req);
|
|
254
|
+
}
|
|
255
|
+
async deliberate(req) {
|
|
256
|
+
return this.post("/intent/deliberation", req);
|
|
257
|
+
}
|
|
258
|
+
/** Open a new decision for deliberation. Returns the Decision node. */
|
|
259
|
+
async openDecision(label, opts) {
|
|
260
|
+
return this.post("/intent/deliberation", {
|
|
261
|
+
action: "open_decision",
|
|
262
|
+
label,
|
|
263
|
+
...opts
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
/** Add an option to an open decision. Returns the Option node. */
|
|
267
|
+
async addOption(decisionUid, label, opts) {
|
|
268
|
+
return this.post("/intent/deliberation", {
|
|
269
|
+
action: "add_option",
|
|
270
|
+
decision_uid: decisionUid,
|
|
271
|
+
label,
|
|
272
|
+
...opts
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Resolve a decision by choosing an option.
|
|
277
|
+
* `chosenOptionUid` must be the uid of an option added via `addOption()`.
|
|
278
|
+
*/
|
|
279
|
+
async resolveDecision(decisionUid, chosenOptionUid, opts) {
|
|
280
|
+
return this.post("/intent/deliberation", {
|
|
281
|
+
action: "resolve",
|
|
282
|
+
decision_uid: decisionUid,
|
|
283
|
+
chosen_option_uid: chosenOptionUid,
|
|
284
|
+
...opts
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
// ---- Action Layer ----
|
|
288
|
+
async procedure(req) {
|
|
289
|
+
return this.post("/action/procedure", req);
|
|
290
|
+
}
|
|
291
|
+
async risk(req) {
|
|
292
|
+
return this.post("/action/risk", req);
|
|
293
|
+
}
|
|
294
|
+
// ---- Memory Layer ----
|
|
295
|
+
async session(req) {
|
|
296
|
+
return this.post("/memory/session", req);
|
|
297
|
+
}
|
|
298
|
+
async journal(label, props, options) {
|
|
299
|
+
return this.post("/memory/session", {
|
|
300
|
+
action: "journal",
|
|
301
|
+
label,
|
|
302
|
+
props,
|
|
303
|
+
...options
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
async distill(req) {
|
|
307
|
+
return this.post("/memory/distill", req);
|
|
308
|
+
}
|
|
309
|
+
async memoryConfig(req) {
|
|
310
|
+
return this.post("/memory/config", req);
|
|
311
|
+
}
|
|
312
|
+
async memorySync(req) {
|
|
313
|
+
return this.post("/memory/sync", req);
|
|
314
|
+
}
|
|
315
|
+
// ---- Agent Layer ----
|
|
316
|
+
async plan(req) {
|
|
317
|
+
return this.post("/agent/plan", req);
|
|
318
|
+
}
|
|
319
|
+
async governance(req) {
|
|
320
|
+
return this.post("/agent/governance", req);
|
|
321
|
+
}
|
|
322
|
+
async execution(req) {
|
|
323
|
+
return this.post("/agent/execution", req);
|
|
324
|
+
}
|
|
325
|
+
// ---- Cross-cutting ----
|
|
326
|
+
/** Returns an array of results. Shape varies by action. */
|
|
327
|
+
async retrieve(req) {
|
|
328
|
+
return this.post("/retrieve", req);
|
|
329
|
+
}
|
|
330
|
+
async traverse(req) {
|
|
331
|
+
return this.post("/traverse", req);
|
|
332
|
+
}
|
|
333
|
+
async evolve(req) {
|
|
334
|
+
return this.post("/evolve", req);
|
|
335
|
+
}
|
|
336
|
+
// ---- Node CRUD ----
|
|
337
|
+
async getNode(uid) {
|
|
338
|
+
return this.get(`/node/${seg(uid)}`);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Create a node via the low-level CRUD endpoint.
|
|
342
|
+
*
|
|
343
|
+
* The server requires `props._type` to determine the node variant.
|
|
344
|
+
* If `node_type` is provided and `_type` is not already in `props`,
|
|
345
|
+
* it is injected automatically.
|
|
346
|
+
*/
|
|
347
|
+
async addNode(body) {
|
|
348
|
+
const props = { ...body.props };
|
|
349
|
+
if (body.node_type && !("_type" in props)) {
|
|
350
|
+
props._type = body.node_type;
|
|
351
|
+
}
|
|
352
|
+
return this.post("/node", { ...body, props });
|
|
353
|
+
}
|
|
354
|
+
async updateNode(uid, body) {
|
|
355
|
+
return this.patch(`/node/${seg(uid)}`, body);
|
|
356
|
+
}
|
|
357
|
+
async deleteNode(uid) {
|
|
358
|
+
await this.del(`/node/${seg(uid)}`);
|
|
359
|
+
}
|
|
360
|
+
async batchDeleteNodes(params) {
|
|
361
|
+
const body = {};
|
|
362
|
+
if (params.uids) body.uids = params.uids;
|
|
363
|
+
if (params.agentId) body.agent_id = params.agentId;
|
|
364
|
+
if (params.filter) {
|
|
365
|
+
body.filter = {
|
|
366
|
+
node_type: params.filter.nodeType,
|
|
367
|
+
node_types: params.filter.nodeTypes,
|
|
368
|
+
layer: params.filter.layer,
|
|
369
|
+
label_contains: params.filter.labelContains,
|
|
370
|
+
prop_equals: params.filter.propEquals
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
if (params.reason) body.reason = params.reason;
|
|
374
|
+
if (params.by) body.by = params.by;
|
|
375
|
+
if (params.hardPurge) body.hard_purge = params.hardPurge;
|
|
376
|
+
return this.post("/nodes/delete", body);
|
|
377
|
+
}
|
|
378
|
+
async getNodeHistory(uid) {
|
|
379
|
+
return this.get(`/node/${seg(uid)}/history`);
|
|
380
|
+
}
|
|
381
|
+
async getNodeAtVersion(uid, version) {
|
|
382
|
+
return this.get(`/node/${seg(uid)}/history/${seg(version)}`);
|
|
383
|
+
}
|
|
384
|
+
// ---- Edge CRUD ----
|
|
385
|
+
async addLink(body) {
|
|
386
|
+
return this.post("/link", body);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Create an edge via the low-level CRUD endpoint.
|
|
390
|
+
*
|
|
391
|
+
* The server requires `props._type` to determine the edge variant.
|
|
392
|
+
* If `edge_type` is provided and `_type` is not already in `props`,
|
|
393
|
+
* it is injected automatically.
|
|
394
|
+
*/
|
|
395
|
+
async addEdge(body) {
|
|
396
|
+
const props = { ...body.props };
|
|
397
|
+
if (body.edge_type && !("_type" in props)) {
|
|
398
|
+
props._type = body.edge_type;
|
|
399
|
+
}
|
|
400
|
+
return this.post("/edge", { ...body, props });
|
|
401
|
+
}
|
|
402
|
+
async updateEdge(uid, body) {
|
|
403
|
+
return this.patch(`/edge/${seg(uid)}`, body);
|
|
404
|
+
}
|
|
405
|
+
async deleteEdge(uid) {
|
|
406
|
+
await this.del(`/edge/${seg(uid)}`);
|
|
407
|
+
}
|
|
408
|
+
async getEdgeHistory(uid) {
|
|
409
|
+
return this.get(`/edge/${seg(uid)}/history`);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* List edges filtered by source and/or target node.
|
|
413
|
+
* At least one of `from_uid` or `to_uid` is **required** —
|
|
414
|
+
* the server returns 400 if neither is provided.
|
|
415
|
+
*/
|
|
416
|
+
async getEdges(params) {
|
|
417
|
+
if (!params.from_uid && !params.to_uid) {
|
|
418
|
+
throw new Error("at least one of from_uid or to_uid is required");
|
|
419
|
+
}
|
|
420
|
+
const qs = new URLSearchParams();
|
|
421
|
+
if (params.from_uid) qs.set("from_uid", params.from_uid);
|
|
422
|
+
if (params.to_uid) qs.set("to_uid", params.to_uid);
|
|
423
|
+
return this.get(`/edges?${qs}`);
|
|
424
|
+
}
|
|
425
|
+
async getEdgeBetween(params) {
|
|
426
|
+
const qs = new URLSearchParams();
|
|
427
|
+
qs.set("from_uid", params.from_uid);
|
|
428
|
+
qs.set("to_uid", params.to_uid);
|
|
429
|
+
if (params.edge_type) qs.set("edge_type", params.edge_type);
|
|
430
|
+
return this.get(`/edge/between?${qs}`);
|
|
431
|
+
}
|
|
432
|
+
// ---- Search ----
|
|
433
|
+
async search(query, opts) {
|
|
434
|
+
return this.post("/search", { query, ...opts });
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Hybrid BM25 + vector search with reciprocal rank fusion. Pass
|
|
438
|
+
* `explain: true` to get per-leg contributions (`legs`) on each result —
|
|
439
|
+
* the "why retrieved" detail (server ≥ 1.2.0; older servers ignore it).
|
|
440
|
+
*/
|
|
441
|
+
async hybridSearch(query, opts) {
|
|
442
|
+
return this.post("/retrieve", {
|
|
443
|
+
action: "hybrid",
|
|
444
|
+
query,
|
|
445
|
+
...opts
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
// ---- Nodes listing ----
|
|
449
|
+
async getNodes(params) {
|
|
450
|
+
const qs = new URLSearchParams();
|
|
451
|
+
if (params?.node_type) qs.set("node_type", params.node_type);
|
|
452
|
+
if (params?.layer) qs.set("layer", params.layer);
|
|
453
|
+
if (params?.limit != null) qs.set("limit", String(params.limit));
|
|
454
|
+
if (params?.offset != null) qs.set("offset", String(params.offset));
|
|
455
|
+
return this.get(`/nodes?${qs}`);
|
|
456
|
+
}
|
|
457
|
+
async getAgentNodes(agentId) {
|
|
458
|
+
return this.get(`/agent/${seg(agentId)}/nodes`);
|
|
459
|
+
}
|
|
460
|
+
// ---- Batch ----
|
|
461
|
+
async batch(req) {
|
|
462
|
+
return this.post("/batch", req);
|
|
463
|
+
}
|
|
464
|
+
/** Fetch multiple nodes by UID in a single request. */
|
|
465
|
+
async getNodesBatch(uids) {
|
|
466
|
+
return this.post("/nodes/batch", { uids });
|
|
467
|
+
}
|
|
468
|
+
/** Fetch all edges between a set of node UIDs. */
|
|
469
|
+
async getEdgesBatch(uids) {
|
|
470
|
+
return this.post("/edges/batch", { uids });
|
|
471
|
+
}
|
|
472
|
+
// ---- Embeddings ----
|
|
473
|
+
async configureEmbeddings(body) {
|
|
474
|
+
return this.post("/embeddings/configure", body);
|
|
475
|
+
}
|
|
476
|
+
async embeddingSearch(body) {
|
|
477
|
+
return this.post("/embeddings/search", body);
|
|
478
|
+
}
|
|
479
|
+
async embeddingSearchText(body) {
|
|
480
|
+
return this.post("/embeddings/search-text", body);
|
|
481
|
+
}
|
|
482
|
+
async getEmbedding(uid) {
|
|
483
|
+
return this.get(`/node/${seg(uid)}/embedding`);
|
|
484
|
+
}
|
|
485
|
+
async setEmbedding(uid, vector) {
|
|
486
|
+
await this.request("PUT", `/node/${seg(uid)}/embedding`, { vector });
|
|
487
|
+
}
|
|
488
|
+
async deleteEmbedding(uid) {
|
|
489
|
+
await this.del(`/node/${seg(uid)}/embedding`);
|
|
490
|
+
}
|
|
491
|
+
// ---- Entity resolution ----
|
|
492
|
+
async mergeEntities(body) {
|
|
493
|
+
return this.post("/entities/merge", body);
|
|
494
|
+
}
|
|
495
|
+
async addAlias(body) {
|
|
496
|
+
return this.post("/alias", body);
|
|
497
|
+
}
|
|
498
|
+
async getAliases(uid) {
|
|
499
|
+
return this.get(`/aliases/${seg(uid)}`);
|
|
500
|
+
}
|
|
501
|
+
async resolveAlias(text) {
|
|
502
|
+
return this.get(`/resolve?text=${encodeURIComponent(text)}`);
|
|
503
|
+
}
|
|
504
|
+
// ---- Export / Import ----
|
|
505
|
+
async exportGraph() {
|
|
506
|
+
return this.get("/export");
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Export one document's extraction provenance as JSON-LD: PROV-O
|
|
510
|
+
* entities/agents, CiTO relations between extracted claims, and the
|
|
511
|
+
* citation anchors as W3C Web Annotations (TextQuoteSelector +
|
|
512
|
+
* TextPositionSelector; positions are chunk-relative UTF-8 byte offsets,
|
|
513
|
+
* flagged via `mg:offsetUnit`).
|
|
514
|
+
*/
|
|
515
|
+
async exportProvenance(documentUid) {
|
|
516
|
+
return this.get(
|
|
517
|
+
`/export/prov?document_uid=${encodeURIComponent(documentUid)}`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
async importGraph(data) {
|
|
521
|
+
return this.post("/import", data);
|
|
522
|
+
}
|
|
523
|
+
// ---- Lifecycle ----
|
|
524
|
+
async decay(req) {
|
|
525
|
+
return this.post("/decay", req);
|
|
526
|
+
}
|
|
527
|
+
async purge(req) {
|
|
528
|
+
return this.post("/purge", req ?? {});
|
|
529
|
+
}
|
|
530
|
+
// ---- Traversal shortcuts ----
|
|
531
|
+
async reasoningChain(uid, maxDepth = 5) {
|
|
532
|
+
const r = await this.post("/traverse", {
|
|
533
|
+
action: "chain",
|
|
534
|
+
start_uid: uid,
|
|
535
|
+
max_depth: maxDepth
|
|
536
|
+
});
|
|
537
|
+
return r?.steps ?? r;
|
|
538
|
+
}
|
|
539
|
+
async neighborhood(uid, maxDepth = 1) {
|
|
540
|
+
const r = await this.post("/traverse", {
|
|
541
|
+
action: "neighborhood",
|
|
542
|
+
start_uid: uid,
|
|
543
|
+
max_depth: maxDepth
|
|
544
|
+
});
|
|
545
|
+
return r?.steps ?? r;
|
|
546
|
+
}
|
|
547
|
+
async subgraph(uid, opts) {
|
|
548
|
+
return this.post("/subgraph", { start_uids: [uid], ...opts });
|
|
549
|
+
}
|
|
550
|
+
// ---- Lifecycle shortcuts ----
|
|
551
|
+
async tombstone(uid, reason, agentId) {
|
|
552
|
+
return this.post("/evolve", {
|
|
553
|
+
action: "tombstone",
|
|
554
|
+
uid,
|
|
555
|
+
reason,
|
|
556
|
+
agent_id: agentId
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
async restore(uid, agentId) {
|
|
560
|
+
return this.post("/evolve", {
|
|
561
|
+
action: "restore",
|
|
562
|
+
uid,
|
|
563
|
+
agent_id: agentId
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
// ---- Epistemic queries ----
|
|
567
|
+
async getGoals() {
|
|
568
|
+
return this.get("/goals");
|
|
569
|
+
}
|
|
570
|
+
async getOpenDecisions() {
|
|
571
|
+
return this.get("/decisions");
|
|
572
|
+
}
|
|
573
|
+
async getOpenQuestions() {
|
|
574
|
+
return this.get("/questions");
|
|
575
|
+
}
|
|
576
|
+
async getWeakClaims() {
|
|
577
|
+
return this.get("/claims/weak");
|
|
578
|
+
}
|
|
579
|
+
async getContradictions() {
|
|
580
|
+
return this.get("/contradictions");
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Pending merge candidates: suspected duplicate pairs recorded by the dedup
|
|
584
|
+
* pipeline's ambiguous zone as PossibleDuplicate edges, awaiting a human
|
|
585
|
+
* merge/dismiss decision (server >= 1.3).
|
|
586
|
+
*/
|
|
587
|
+
async getMergeCandidates() {
|
|
588
|
+
return this.post("/retrieve", { action: "merge_candidates" });
|
|
589
|
+
}
|
|
590
|
+
/** Load-bearing conclusions awaiting repair after a premise changed. */
|
|
591
|
+
async getStaleDerivations(limit = 50, offset = 0) {
|
|
592
|
+
return this.post("/retrieve", { action: "stale_derivations", limit, offset });
|
|
593
|
+
}
|
|
594
|
+
async getPendingApprovals() {
|
|
595
|
+
return this.get("/approvals/pending");
|
|
596
|
+
}
|
|
597
|
+
// ---- Ingestion & Retrieval ----
|
|
598
|
+
async ingestChunk(req) {
|
|
599
|
+
return this.post("/ingest/chunk", req);
|
|
600
|
+
}
|
|
601
|
+
async ingestDocument(req) {
|
|
602
|
+
return this.post("/ingest/document", req);
|
|
603
|
+
}
|
|
604
|
+
async ingestSession(req) {
|
|
605
|
+
return this.post("/ingest/session", req);
|
|
606
|
+
}
|
|
607
|
+
async retrieveContext(req) {
|
|
608
|
+
return this.post("/retrieve/context", req);
|
|
609
|
+
}
|
|
610
|
+
/** Backfill node_source provenance for existing graphs. */
|
|
611
|
+
async backfillNodeSources() {
|
|
612
|
+
return this.post("/backfill/node-sources", {});
|
|
613
|
+
}
|
|
614
|
+
/** Backfill citation anchors (source_chunks spans) for existing graphs. Returns a background job id. */
|
|
615
|
+
async backfillAnchors() {
|
|
616
|
+
return this.post("/backfill/anchors", {});
|
|
617
|
+
}
|
|
618
|
+
async listJobs() {
|
|
619
|
+
return this.get("/jobs");
|
|
620
|
+
}
|
|
621
|
+
async getJob(id) {
|
|
622
|
+
return this.get(`/jobs/${seg(id)}`);
|
|
623
|
+
}
|
|
624
|
+
async cancelJob(id) {
|
|
625
|
+
return this.post(`/jobs/${seg(id)}/cancel`, {});
|
|
626
|
+
}
|
|
627
|
+
/** Resume ingestion of a document that has failed chunks. */
|
|
628
|
+
async resumeDocument(docUid, opts) {
|
|
629
|
+
return this.post(`/ingest/resume/${seg(docUid)}`, opts ?? {});
|
|
630
|
+
}
|
|
631
|
+
/** Delete a document and all its chunks and extracted nodes. */
|
|
632
|
+
async deleteDocument(uid) {
|
|
633
|
+
return this.del(`/ingest/document/${seg(uid)}`);
|
|
634
|
+
}
|
|
635
|
+
async cleanupOrphans() {
|
|
636
|
+
return this.post("/ingest/cleanup", {});
|
|
637
|
+
}
|
|
638
|
+
async embedAll() {
|
|
639
|
+
return this.post("/ingest/embed-all", {});
|
|
640
|
+
}
|
|
641
|
+
async clearGraph() {
|
|
642
|
+
return this.post("/clear", {});
|
|
643
|
+
}
|
|
644
|
+
// ── Wiki ──────────────────────────────────────────────────────────────
|
|
645
|
+
/** List wiki articles with optional filters. */
|
|
646
|
+
async listArticles(params) {
|
|
647
|
+
const q = new URLSearchParams();
|
|
648
|
+
if (params?.article_type) q.set("article_type", params.article_type);
|
|
649
|
+
if (params?.covers_node_type) q.set("covers_node_type", params.covers_node_type);
|
|
650
|
+
if (params?.search) q.set("search", params.search);
|
|
651
|
+
if (params?.limit) q.set("limit", String(params.limit));
|
|
652
|
+
if (params?.offset) q.set("offset", String(params.offset));
|
|
653
|
+
return this.get(`/wiki/articles?${q}`);
|
|
654
|
+
}
|
|
655
|
+
/** Get a single wiki article by UID. */
|
|
656
|
+
async getArticle(uid) {
|
|
657
|
+
return this.get(`/wiki/article/${seg(uid)}`);
|
|
658
|
+
}
|
|
659
|
+
/** Find the article that covers or summarizes a given entity/document UID. */
|
|
660
|
+
async getArticleBySubject(subjectUid) {
|
|
661
|
+
try {
|
|
662
|
+
return await this.get(`/wiki/article/by-subject/${seg(subjectUid)}`);
|
|
663
|
+
} catch {
|
|
664
|
+
return null;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
/** Update an article's markdown content (user editing). */
|
|
668
|
+
async updateArticle(uid, content) {
|
|
669
|
+
return this.patch(`/wiki/article/${seg(uid)}`, { content });
|
|
670
|
+
}
|
|
671
|
+
/** Trigger wiki compilation for a specific document. */
|
|
672
|
+
async compileDocument(docUid) {
|
|
673
|
+
return this.post(`/wiki/compile/${seg(docUid)}`, {});
|
|
674
|
+
}
|
|
675
|
+
/** Trigger wiki compilation for a specific entity. */
|
|
676
|
+
async compileEntity(entityUid) {
|
|
677
|
+
return this.post(`/wiki/compile/entity/${seg(entityUid)}`, {});
|
|
678
|
+
}
|
|
679
|
+
/** Backfill: compile articles for all documents and eligible entities. */
|
|
680
|
+
async compileAll() {
|
|
681
|
+
return this.post("/wiki/compile/all", {});
|
|
682
|
+
}
|
|
683
|
+
// ── Synthesis (Projects) ──────────────────────────────────────────────
|
|
684
|
+
/**
|
|
685
|
+
* Mine structural synthesis signals for a project's document corpus.
|
|
686
|
+
*
|
|
687
|
+
* Returns candidate surface for downstream synthesis — entity bridges
|
|
688
|
+
* across documents, claim hubs, clustered claim hubs, theory support
|
|
689
|
+
* gaps, concept clusters, analogy candidates, and dialectical pairs.
|
|
690
|
+
*
|
|
691
|
+
* Blocking operation. No LLM calls; Datalog + embedding clustering only.
|
|
692
|
+
*/
|
|
693
|
+
async signals(projectUid, opts) {
|
|
694
|
+
const q = new URLSearchParams();
|
|
695
|
+
if (opts?.signals) q.set("signals", opts.signals);
|
|
696
|
+
if (opts?.target_types) q.set("target_types", opts.target_types);
|
|
697
|
+
const qs = q.toString();
|
|
698
|
+
return this.get(`/synthesis/signals/${seg(projectUid)}${qs ? `?${qs}` : ""}`);
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Spawn a background synthesis job for a project: mines signals,
|
|
702
|
+
* selects top idea clusters, runs LLM synthesis, and persists
|
|
703
|
+
* candidate Article nodes linked via `Covers` edges.
|
|
704
|
+
*
|
|
705
|
+
* Returns a `job_id` immediately; poll `getJob(id)` for progress.
|
|
706
|
+
*/
|
|
707
|
+
async runSynthesis(projectUid) {
|
|
708
|
+
return this.post(`/synthesis/run/${seg(projectUid)}`, {});
|
|
709
|
+
}
|
|
710
|
+
// ============================================================================
|
|
711
|
+
// Operational Ontology Layer (Layer 7)
|
|
712
|
+
// ============================================================================
|
|
713
|
+
// ---- Schema management (cloud Postgres) ----
|
|
714
|
+
async listOntologySchemas() {
|
|
715
|
+
return this.get("/v1/ontology/schemas");
|
|
716
|
+
}
|
|
717
|
+
async getOntologySchema(id) {
|
|
718
|
+
return this.get(`/v1/ontology/schemas/${seg(id)}`);
|
|
719
|
+
}
|
|
720
|
+
async createOntologySchema(req) {
|
|
721
|
+
return this.post("/v1/ontology/schemas", req);
|
|
722
|
+
}
|
|
723
|
+
async updateOntologySchema(id, req) {
|
|
724
|
+
return this.patch(`/v1/ontology/schemas/${seg(id)}`, req);
|
|
725
|
+
}
|
|
726
|
+
async activateOntologySchema(id) {
|
|
727
|
+
return this.post(`/v1/ontology/schemas/${seg(id)}/activate`, {});
|
|
728
|
+
}
|
|
729
|
+
async deprecateOntologySchema(id) {
|
|
730
|
+
return this.post(`/v1/ontology/schemas/${seg(id)}/deprecate`, {});
|
|
731
|
+
}
|
|
732
|
+
async archiveOntologySchema(id) {
|
|
733
|
+
return this.del(`/v1/ontology/schemas/${seg(id)}`);
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Kick off an LLM-driven schema proposal job.
|
|
737
|
+
* Returns immediately with `{ schema_id, job_id }`; poll
|
|
738
|
+
* `getOntologySchema(schema_id)` for streaming progress.
|
|
739
|
+
*/
|
|
740
|
+
async proposeOntologySchema(req) {
|
|
741
|
+
return this.post("/v1/ontology/propose-schema", req);
|
|
742
|
+
}
|
|
743
|
+
async testOntologySchema(id, opts) {
|
|
744
|
+
return this.post(`/v1/ontology/schemas/${seg(id)}/test`, opts ?? {});
|
|
745
|
+
}
|
|
746
|
+
// ---- Schema sub-resources ----
|
|
747
|
+
async addOntologyObjectType(schemaId, req) {
|
|
748
|
+
return this.post(`/v1/ontology/schemas/${seg(schemaId)}/object-types`, req);
|
|
749
|
+
}
|
|
750
|
+
async updateOntologyObjectType(schemaId, typeId, req) {
|
|
751
|
+
return this.patch(
|
|
752
|
+
`/v1/ontology/schemas/${seg(schemaId)}/object-types/${seg(typeId)}`,
|
|
753
|
+
req
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
async deleteOntologyObjectType(schemaId, typeId) {
|
|
757
|
+
return this.del(
|
|
758
|
+
`/v1/ontology/schemas/${seg(schemaId)}/object-types/${seg(typeId)}`
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
async addOntologyRelationType(schemaId, req) {
|
|
762
|
+
return this.post(`/v1/ontology/schemas/${seg(schemaId)}/relation-types`, req);
|
|
763
|
+
}
|
|
764
|
+
async updateOntologyRelationType(schemaId, typeId, req) {
|
|
765
|
+
return this.patch(
|
|
766
|
+
`/v1/ontology/schemas/${seg(schemaId)}/relation-types/${seg(typeId)}`,
|
|
767
|
+
req
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
async deleteOntologyRelationType(schemaId, typeId) {
|
|
771
|
+
return this.del(
|
|
772
|
+
`/v1/ontology/schemas/${seg(schemaId)}/relation-types/${seg(typeId)}`
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
/** Generate inert semantic classifications for individual human review. */
|
|
776
|
+
async analyzeOntologySemanticGuidance(schemaId) {
|
|
777
|
+
return this.post(
|
|
778
|
+
`/v1/ontology/schemas/${seg(schemaId)}/semantic-guidance/analyze`,
|
|
779
|
+
{}
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
/** Read-only exact-identity collision audit; never merges graph data. */
|
|
783
|
+
async auditOntologyDuplicates(schemaId) {
|
|
784
|
+
return this.post(`/v1/ontology/schemas/${seg(schemaId)}/duplicates/audit`, {});
|
|
785
|
+
}
|
|
786
|
+
// ---- Proposals ----
|
|
787
|
+
async listOntologyProposals(opts) {
|
|
788
|
+
const q = new URLSearchParams();
|
|
789
|
+
if (opts?.status) q.set("status", opts.status);
|
|
790
|
+
if (opts?.schema_id) q.set("schema_id", opts.schema_id);
|
|
791
|
+
if (opts?.object_type) q.set("object_type", opts.object_type);
|
|
792
|
+
if (opts?.proposal_type) q.set("proposal_type", opts.proposal_type);
|
|
793
|
+
if (opts?.extract_job_id) q.set("extract_job_id", opts.extract_job_id);
|
|
794
|
+
if (opts?.limit != null) q.set("limit", String(opts.limit));
|
|
795
|
+
if (opts?.offset != null) q.set("offset", String(opts.offset));
|
|
796
|
+
const qs = q.toString();
|
|
797
|
+
return this.get(`/v1/ontology/proposals${qs ? `?${qs}` : ""}`);
|
|
798
|
+
}
|
|
799
|
+
async getOntologyProposal(id) {
|
|
800
|
+
return this.get(`/v1/ontology/proposals/${seg(id)}`);
|
|
801
|
+
}
|
|
802
|
+
async patchOntologyProposal(id, req) {
|
|
803
|
+
return this.patch(`/v1/ontology/proposals/${seg(id)}`, req);
|
|
804
|
+
}
|
|
805
|
+
async approveOntologyProposal(id, opts) {
|
|
806
|
+
return this.post(`/v1/ontology/proposals/${seg(id)}/approve`, opts ?? {});
|
|
807
|
+
}
|
|
808
|
+
async rejectOntologyProposal(id, reason) {
|
|
809
|
+
return this.post(`/v1/ontology/proposals/${seg(id)}/reject`, { reason });
|
|
810
|
+
}
|
|
811
|
+
async applyOntologyProposal(id) {
|
|
812
|
+
return this.post(`/v1/ontology/proposals/${seg(id)}/apply`, {});
|
|
813
|
+
}
|
|
814
|
+
async batchApproveOntologyProposals(ids, feedback) {
|
|
815
|
+
return this.post("/v1/ontology/proposals/batch-approve", { ids, feedback });
|
|
816
|
+
}
|
|
817
|
+
async batchRejectOntologyProposals(ids, reason) {
|
|
818
|
+
return this.post("/v1/ontology/proposals/batch-reject", { ids, reason });
|
|
819
|
+
}
|
|
820
|
+
// ---- Retrieval (graph server) ----
|
|
821
|
+
async queryOntology(req) {
|
|
822
|
+
return this.post("/ontology/query", req);
|
|
823
|
+
}
|
|
824
|
+
async queryDomainStructured(req) {
|
|
825
|
+
return this.post("/ontology/query/structured", req);
|
|
826
|
+
}
|
|
827
|
+
async queryRelatedDomainObjects(req) {
|
|
828
|
+
return this.queryDomainStructured({
|
|
829
|
+
schema_id: req.schema_id,
|
|
830
|
+
select: req.far_type,
|
|
831
|
+
...req.project_uid ? { project_uid: req.project_uid } : {},
|
|
832
|
+
anchor: { type: req.entry_type, uid: req.uid },
|
|
833
|
+
path: [{
|
|
834
|
+
relation: req.relation,
|
|
835
|
+
entry_role: req.entry_role
|
|
836
|
+
}],
|
|
837
|
+
...req.where ? { where: req.where } : {},
|
|
838
|
+
...req.include_provenance ? { include: { provenance: true } } : {},
|
|
839
|
+
page: {
|
|
840
|
+
...req.limit != null ? { limit: req.limit } : {},
|
|
841
|
+
...req.offset != null ? { offset: req.offset } : {}
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Schema-qualified read-tool descriptors generated from every active
|
|
847
|
+
* ontology. Includes per-object discovery/point/context tools,
|
|
848
|
+
* relation-and-role-specific related tools, and one structured composite.
|
|
849
|
+
*/
|
|
850
|
+
async listOntologyTools() {
|
|
851
|
+
return this.get("/v1/ontology/tools");
|
|
852
|
+
}
|
|
853
|
+
async getDomainObject(uid, binding) {
|
|
854
|
+
const query = new URLSearchParams();
|
|
855
|
+
if (binding) {
|
|
856
|
+
query.set("schema_id", binding.schema_id);
|
|
857
|
+
query.set("object_type", binding.object_type);
|
|
858
|
+
if (binding.project_uid) query.set("project_uid", binding.project_uid);
|
|
859
|
+
}
|
|
860
|
+
const suffix = query.size > 0 ? `?${query.toString()}` : "";
|
|
861
|
+
return this.get(`/ontology/object/${seg(uid)}${suffix}`);
|
|
862
|
+
}
|
|
863
|
+
async getDomainObjectContext(uid, depth, binding) {
|
|
864
|
+
const query = new URLSearchParams();
|
|
865
|
+
if (depth != null) query.set("depth", String(depth));
|
|
866
|
+
if (binding) {
|
|
867
|
+
query.set("schema_id", binding.schema_id);
|
|
868
|
+
query.set("object_type", binding.object_type);
|
|
869
|
+
if (binding.project_uid) query.set("project_uid", binding.project_uid);
|
|
870
|
+
}
|
|
871
|
+
const suffix = query.size > 0 ? `?${query.toString()}` : "";
|
|
872
|
+
return this.get(`/ontology/object/${seg(uid)}/context${suffix}`);
|
|
873
|
+
}
|
|
874
|
+
async getDomainObjectHistory(uid) {
|
|
875
|
+
return this.get(`/ontology/object/${seg(uid)}/history`);
|
|
876
|
+
}
|
|
877
|
+
async listDomainObjects(opts) {
|
|
878
|
+
const q = new URLSearchParams();
|
|
879
|
+
q.set("schema_id", opts.schema_id);
|
|
880
|
+
if (opts.object_type) q.set("object_type", opts.object_type);
|
|
881
|
+
if (opts.limit != null) q.set("limit", String(opts.limit));
|
|
882
|
+
if (opts.offset != null) q.set("offset", String(opts.offset));
|
|
883
|
+
if (opts.sort) q.set("sort", opts.sort);
|
|
884
|
+
return this.get(`/ontology/objects?${q.toString()}`);
|
|
885
|
+
}
|
|
886
|
+
async searchDomainObjects(query, opts) {
|
|
887
|
+
return this.post("/ontology/objects/search", { query, ...opts ?? {} });
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Per-object-type coverage stats for a schema (C2f): field fill rates
|
|
891
|
+
* (with a `near_empty` flag < 5%) and identity collisions, over a bounded
|
|
892
|
+
* per-type sample (default 500, max 2000).
|
|
893
|
+
*/
|
|
894
|
+
async ontologyStats(schemaId, sample) {
|
|
895
|
+
const q = new URLSearchParams({ schema_id: schemaId });
|
|
896
|
+
if (sample != null) q.set("sample", String(sample));
|
|
897
|
+
return this.get(`/ontology/stats?${q.toString()}`);
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Create a domain object by hand (auto-approved). Returns the created node
|
|
901
|
+
* uid + the audit proposal id. Throws 409 if an object of the same type +
|
|
902
|
+
* canonical_name already exists, unless `allow_duplicate` is set.
|
|
903
|
+
*/
|
|
904
|
+
async createDomainObject(req) {
|
|
905
|
+
return this.post("/v1/ontology/objects", req);
|
|
906
|
+
}
|
|
907
|
+
async linkDomainObjects(req) {
|
|
908
|
+
return this.post("/ontology/relation", { action: "create", ...req });
|
|
909
|
+
}
|
|
910
|
+
// ---- Extraction ----
|
|
911
|
+
async extractOntology(req) {
|
|
912
|
+
return this.post("/ontology/extract", req);
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
});
|
|
917
|
+
|
|
29
918
|
// src/codegraph.ts
|
|
30
919
|
function normalizePath(path6) {
|
|
31
920
|
return path6.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
@@ -712,17 +1601,16 @@ var init_codegraph = __esm({
|
|
|
712
1601
|
|
|
713
1602
|
// src/error-detail.ts
|
|
714
1603
|
function errorDetail(e) {
|
|
715
|
-
if (e instanceof
|
|
1604
|
+
if (e instanceof MindGraphError && e.body !== void 0) {
|
|
716
1605
|
const detail = typeof e.body === "string" ? e.body : JSON.stringify(e.body);
|
|
717
1606
|
return `${e.message} \u2014 ${detail}`;
|
|
718
1607
|
}
|
|
719
1608
|
return e instanceof Error ? e.message : String(e);
|
|
720
1609
|
}
|
|
721
|
-
var import_mindgraph;
|
|
722
1610
|
var init_error_detail = __esm({
|
|
723
1611
|
"src/error-detail.ts"() {
|
|
724
1612
|
"use strict";
|
|
725
|
-
|
|
1613
|
+
init_dist();
|
|
726
1614
|
}
|
|
727
1615
|
});
|
|
728
1616
|
|
|
@@ -3874,14 +4762,14 @@ async function main() {
|
|
|
3874
4762
|
`MindGraph MCP server v0.7.1 running on stdio (${BASE_URL})`
|
|
3875
4763
|
);
|
|
3876
4764
|
}
|
|
3877
|
-
var import_server, import_stdio, import_types,
|
|
4765
|
+
var import_server, import_stdio, import_types, API_KEY, BASE_URL, AGENT_ID, ORG_ID, PROFILE, HARNESS, client, INSTRUCTIONS, server, GOVERNANCE_CONFIG, PROMPTS;
|
|
3878
4766
|
var init_src = __esm({
|
|
3879
4767
|
"src/index.ts"() {
|
|
3880
4768
|
"use strict";
|
|
3881
4769
|
import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
3882
4770
|
import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
3883
4771
|
import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
3884
|
-
|
|
4772
|
+
init_dist();
|
|
3885
4773
|
init_tools();
|
|
3886
4774
|
init_generated_tools();
|
|
3887
4775
|
init_governance();
|
|
@@ -3898,7 +4786,7 @@ var init_src = __esm({
|
|
|
3898
4786
|
);
|
|
3899
4787
|
process.exit(1);
|
|
3900
4788
|
}
|
|
3901
|
-
client = new
|
|
4789
|
+
client = new MindGraph({
|
|
3902
4790
|
baseUrl: BASE_URL,
|
|
3903
4791
|
apiKey: API_KEY,
|
|
3904
4792
|
orgId: ORG_ID,
|
|
@@ -4005,7 +4893,7 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
4005
4893
|
server = new import_server.Server(
|
|
4006
4894
|
{
|
|
4007
4895
|
name: "mindgraph",
|
|
4008
|
-
version: "0.14.
|
|
4896
|
+
version: "0.14.4"
|
|
4009
4897
|
},
|
|
4010
4898
|
{
|
|
4011
4899
|
capabilities: {
|
|
@@ -4228,7 +5116,7 @@ var path5 = __toESM(require("path"));
|
|
|
4228
5116
|
var os4 = __toESM(require("os"));
|
|
4229
5117
|
var crypto4 = __toESM(require("crypto"));
|
|
4230
5118
|
var import_child_process = require("child_process");
|
|
4231
|
-
|
|
5119
|
+
init_dist();
|
|
4232
5120
|
|
|
4233
5121
|
// src/hook-env.ts
|
|
4234
5122
|
var import_node_fs = __toESM(require("fs"));
|
|
@@ -4243,7 +5131,8 @@ function loadHookEnv(dir) {
|
|
|
4243
5131
|
const parsed = JSON.parse(raw);
|
|
4244
5132
|
return {
|
|
4245
5133
|
baseUrl: typeof parsed.baseUrl === "string" ? parsed.baseUrl : void 0,
|
|
4246
|
-
apiKey: typeof parsed.apiKey === "string" ? parsed.apiKey : void 0
|
|
5134
|
+
apiKey: typeof parsed.apiKey === "string" ? parsed.apiKey : void 0,
|
|
5135
|
+
agentId: typeof parsed.agentId === "string" ? parsed.agentId : void 0
|
|
4247
5136
|
};
|
|
4248
5137
|
} catch {
|
|
4249
5138
|
return {};
|
|
@@ -4255,7 +5144,8 @@ function saveHookEnv(env, dir) {
|
|
|
4255
5144
|
const existing = loadHookEnv(dir);
|
|
4256
5145
|
const merged = {
|
|
4257
5146
|
baseUrl: env.baseUrl ?? existing.baseUrl,
|
|
4258
|
-
apiKey: env.apiKey ?? existing.apiKey
|
|
5147
|
+
apiKey: env.apiKey ?? existing.apiKey,
|
|
5148
|
+
agentId: env.agentId ?? existing.agentId
|
|
4259
5149
|
};
|
|
4260
5150
|
import_node_fs.default.writeFileSync(file, `${JSON.stringify(merged, null, 2)}
|
|
4261
5151
|
`, {
|
|
@@ -4275,6 +5165,7 @@ function parseArgs(argv) {
|
|
|
4275
5165
|
let projectDir;
|
|
4276
5166
|
let harness;
|
|
4277
5167
|
let hooks = false;
|
|
5168
|
+
let agentId = process.env.MINDGRAPH_AGENT_ID;
|
|
4278
5169
|
for (let i = 0; i < args.length; i++) {
|
|
4279
5170
|
const arg = args[i];
|
|
4280
5171
|
switch (arg) {
|
|
@@ -4298,6 +5189,9 @@ function parseArgs(argv) {
|
|
|
4298
5189
|
case "--harness":
|
|
4299
5190
|
harness = args[++i];
|
|
4300
5191
|
break;
|
|
5192
|
+
case "--agent-id":
|
|
5193
|
+
agentId = args[++i];
|
|
5194
|
+
break;
|
|
4301
5195
|
case "--hooks":
|
|
4302
5196
|
hooks = true;
|
|
4303
5197
|
break;
|
|
@@ -4315,7 +5209,7 @@ function parseArgs(argv) {
|
|
|
4315
5209
|
break;
|
|
4316
5210
|
}
|
|
4317
5211
|
}
|
|
4318
|
-
return { command, apiKey, baseUrl, scope, projectDir, harness, hooks };
|
|
5212
|
+
return { command, apiKey, baseUrl, scope, projectDir, harness, hooks, agentId };
|
|
4319
5213
|
}
|
|
4320
5214
|
function mcpAddFailureOutput(e) {
|
|
4321
5215
|
const err5 = e;
|
|
@@ -4960,7 +5854,7 @@ function installClaudeDesktop(apiKey, baseUrl) {
|
|
|
4960
5854
|
}
|
|
4961
5855
|
console.log("Restart Claude Desktop to activate.");
|
|
4962
5856
|
}
|
|
4963
|
-
function installClaudeCode(apiKey, baseUrl) {
|
|
5857
|
+
function installClaudeCode(apiKey, baseUrl, agentId) {
|
|
4964
5858
|
const envArgs = [
|
|
4965
5859
|
`--env`,
|
|
4966
5860
|
`MINDGRAPH_API_KEY=${apiKey}`,
|
|
@@ -4969,7 +5863,7 @@ function installClaudeCode(apiKey, baseUrl) {
|
|
|
4969
5863
|
"--env",
|
|
4970
5864
|
"MINDGRAPH_HARNESS=claude-code",
|
|
4971
5865
|
"--env",
|
|
4972
|
-
"
|
|
5866
|
+
`MINDGRAPH_AGENT_ID=${agentId || "claude-code"}`
|
|
4973
5867
|
];
|
|
4974
5868
|
if (baseUrl) {
|
|
4975
5869
|
envArgs.push("--env", `MINDGRAPH_BASE_URL=${baseUrl}`);
|
|
@@ -5063,7 +5957,7 @@ function printStatus() {
|
|
|
5063
5957
|
function withHooksFlag() {
|
|
5064
5958
|
return process.argv.includes("--hooks");
|
|
5065
5959
|
}
|
|
5066
|
-
function finishCodeInstall(apiKey, baseUrl, withHooks) {
|
|
5960
|
+
function finishCodeInstall(apiKey, baseUrl, withHooks, agentId) {
|
|
5067
5961
|
if (withHooks) {
|
|
5068
5962
|
const runner = installHookRunner(__filename);
|
|
5069
5963
|
console.log(`Installed pinned hook runner at ${runner}`);
|
|
@@ -5071,7 +5965,7 @@ function finishCodeInstall(apiKey, baseUrl, withHooks) {
|
|
|
5071
5965
|
console.log(
|
|
5072
5966
|
`Installed ${result.added} and refreshed ${result.updated} MindGraph Claude Code hook entries in ${result.path}`
|
|
5073
5967
|
);
|
|
5074
|
-
const envPath = saveHookEnv({ apiKey, baseUrl });
|
|
5968
|
+
const envPath = saveHookEnv({ apiKey, baseUrl, agentId });
|
|
5075
5969
|
console.log(`Saved hook connection settings to ${envPath} (mode 600)`);
|
|
5076
5970
|
} else {
|
|
5077
5971
|
console.log(
|
|
@@ -5223,13 +6117,23 @@ async function interactiveInit(baseUrl) {
|
|
|
5223
6117
|
installClaudeDesktop(apiKey, baseUrl);
|
|
5224
6118
|
break;
|
|
5225
6119
|
case "2":
|
|
5226
|
-
installClaudeCode(apiKey, baseUrl);
|
|
5227
|
-
finishCodeInstall(
|
|
6120
|
+
installClaudeCode(apiKey, baseUrl, process.env.MINDGRAPH_AGENT_ID);
|
|
6121
|
+
finishCodeInstall(
|
|
6122
|
+
apiKey,
|
|
6123
|
+
baseUrl,
|
|
6124
|
+
withHooksFlag(),
|
|
6125
|
+
process.env.MINDGRAPH_AGENT_ID
|
|
6126
|
+
);
|
|
5228
6127
|
break;
|
|
5229
6128
|
case "3":
|
|
5230
6129
|
installClaudeDesktop(apiKey, baseUrl);
|
|
5231
|
-
installClaudeCode(apiKey, baseUrl);
|
|
5232
|
-
finishCodeInstall(
|
|
6130
|
+
installClaudeCode(apiKey, baseUrl, process.env.MINDGRAPH_AGENT_ID);
|
|
6131
|
+
finishCodeInstall(
|
|
6132
|
+
apiKey,
|
|
6133
|
+
baseUrl,
|
|
6134
|
+
withHooksFlag(),
|
|
6135
|
+
process.env.MINDGRAPH_AGENT_ID
|
|
6136
|
+
);
|
|
5233
6137
|
break;
|
|
5234
6138
|
default:
|
|
5235
6139
|
console.error("Invalid choice.");
|
|
@@ -5238,7 +6142,7 @@ async function interactiveInit(baseUrl) {
|
|
|
5238
6142
|
console.log("\nDone! Your knowledge graph is now connected.");
|
|
5239
6143
|
}
|
|
5240
6144
|
async function main2() {
|
|
5241
|
-
const { command, apiKey, baseUrl, scope, projectDir, harness, hooks } = parseArgs(process.argv);
|
|
6145
|
+
const { command, apiKey, baseUrl, scope, projectDir, harness, hooks, agentId } = parseArgs(process.argv);
|
|
5242
6146
|
switch (command) {
|
|
5243
6147
|
case "help":
|
|
5244
6148
|
printUsage();
|
|
@@ -5262,8 +6166,8 @@ async function main2() {
|
|
|
5262
6166
|
);
|
|
5263
6167
|
process.exit(1);
|
|
5264
6168
|
}
|
|
5265
|
-
installClaudeCode(apiKey, baseUrl);
|
|
5266
|
-
finishCodeInstall(apiKey, baseUrl, withHooksFlag());
|
|
6169
|
+
installClaudeCode(apiKey, baseUrl, agentId);
|
|
6170
|
+
finishCodeInstall(apiKey, baseUrl, withHooksFlag(), agentId);
|
|
5267
6171
|
break;
|
|
5268
6172
|
case "uninstall":
|
|
5269
6173
|
uninstallClaudeDesktop();
|
|
@@ -5281,8 +6185,8 @@ async function main2() {
|
|
|
5281
6185
|
console.log(
|
|
5282
6186
|
`Installed ${result.added} and refreshed ${result.updated} MindGraph Claude Code hook entries in ${result.path}`
|
|
5283
6187
|
);
|
|
5284
|
-
if (apiKey || baseUrl) {
|
|
5285
|
-
const envPath = saveHookEnv({ apiKey, baseUrl });
|
|
6188
|
+
if (apiKey || baseUrl || agentId) {
|
|
6189
|
+
const envPath = saveHookEnv({ apiKey, baseUrl, agentId });
|
|
5286
6190
|
console.log(`Saved hook connection settings to ${envPath} (mode 600)`);
|
|
5287
6191
|
} else {
|
|
5288
6192
|
console.log(
|
|
@@ -5312,7 +6216,7 @@ async function main2() {
|
|
|
5312
6216
|
}
|
|
5313
6217
|
try {
|
|
5314
6218
|
const input = await readHookInput();
|
|
5315
|
-
const client2 = new
|
|
6219
|
+
const client2 = new MindGraph({
|
|
5316
6220
|
baseUrl: hookBaseUrl || "https://api.mindgraph.cloud",
|
|
5317
6221
|
apiKey: hookApiKey,
|
|
5318
6222
|
orgId: process.env.MINDGRAPH_ORG_ID,
|
|
@@ -5320,7 +6224,7 @@ async function main2() {
|
|
|
5320
6224
|
telemetrySurface: "mcp"
|
|
5321
6225
|
});
|
|
5322
6226
|
const output = await runClaudeHook(input, client2, {
|
|
5323
|
-
agentId: process.env.MINDGRAPH_AGENT_ID || "claude-code"
|
|
6227
|
+
agentId: process.env.MINDGRAPH_AGENT_ID || stored.agentId || "claude-code"
|
|
5324
6228
|
});
|
|
5325
6229
|
process.stdout.write(`${JSON.stringify(output)}
|
|
5326
6230
|
`);
|
package/dist/index.js
CHANGED