@graph-tl/graph 0.1.10 → 0.1.14
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 +1 -0
- package/dist/{chunk-TWT5GUXW.js → chunk-CCGKUMCW.js} +63 -10
- package/dist/chunk-CCGKUMCW.js.map +1 -0
- package/dist/{chunk-ILTJI4ZN.js → chunk-JRMFXD5I.js} +20 -4
- package/dist/chunk-JRMFXD5I.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{init-RQFGF5BB.js → init-VII7APUJ.js} +19 -4
- package/dist/init-VII7APUJ.js.map +1 -0
- package/dist/{nodes-4OJBNDHG.js → nodes-YNM6KEK2.js} +4 -2
- package/dist/{server-VKTFTBXC.js → server-X36DXLEG.js} +144 -37
- package/dist/server-X36DXLEG.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-ILTJI4ZN.js.map +0 -1
- package/dist/chunk-TWT5GUXW.js.map +0 -1
- package/dist/init-RQFGF5BB.js.map +0 -1
- package/dist/server-VKTFTBXC.js.map +0 -1
- /package/dist/{nodes-4OJBNDHG.js.map → nodes-YNM6KEK2.js.map} +0 -0
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-WKOEKYTF.js";
|
|
5
5
|
import {
|
|
6
6
|
handleAgentConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JRMFXD5I.js";
|
|
8
8
|
import {
|
|
9
9
|
EngineError,
|
|
10
10
|
ValidationError,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
getNodeOrThrow,
|
|
20
20
|
getProjectRoot,
|
|
21
21
|
getProjectSummary,
|
|
22
|
+
getSubtreeProgress,
|
|
22
23
|
listProjects,
|
|
23
24
|
logEvent,
|
|
24
25
|
optionalBoolean,
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
requireString,
|
|
29
30
|
setDbPath,
|
|
30
31
|
updateNode
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-CCGKUMCW.js";
|
|
32
33
|
|
|
33
34
|
// src/server.ts
|
|
34
35
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -54,15 +55,17 @@ function handleOpen(input, agent) {
|
|
|
54
55
|
root = createNode({
|
|
55
56
|
project,
|
|
56
57
|
summary: goal ?? project,
|
|
57
|
-
discovery: "pending",
|
|
58
|
+
discovery: input?.skip_discovery ? "done" : "pending",
|
|
58
59
|
agent
|
|
59
60
|
});
|
|
60
61
|
isNew = true;
|
|
61
62
|
}
|
|
62
63
|
const summary = getProjectSummary(project);
|
|
63
64
|
const result = { project, root, summary };
|
|
64
|
-
if (isNew) {
|
|
65
|
+
if (isNew && root.discovery === "pending") {
|
|
65
66
|
result.hint = `New project created. Discovery is pending \u2014 interview the user to understand scope and goals, then set discovery to "done" via graph_update before decomposing with graph_plan.`;
|
|
67
|
+
} else if (isNew) {
|
|
68
|
+
result.hint = `New project created. Ready to decompose \u2014 use graph_plan to add tasks.`;
|
|
66
69
|
} else if (root.discovery === "pending") {
|
|
67
70
|
result.hint = `Discovery is still pending on this project. Complete the discovery interview, then set discovery to "done" via graph_update.`;
|
|
68
71
|
} else if (summary.actionable > 0) {
|
|
@@ -216,7 +219,7 @@ function handlePlan(input, agent) {
|
|
|
216
219
|
const refs = /* @__PURE__ */ new Set();
|
|
217
220
|
for (const node of nodes) {
|
|
218
221
|
if (refs.has(node.ref)) {
|
|
219
|
-
throw new
|
|
222
|
+
throw new EngineError("duplicate_ref", `Duplicate ref in batch: ${node.ref}`);
|
|
220
223
|
}
|
|
221
224
|
refs.add(node.ref);
|
|
222
225
|
}
|
|
@@ -230,7 +233,8 @@ function handlePlan(input, agent) {
|
|
|
230
233
|
if (existing) {
|
|
231
234
|
parentId = existing.id;
|
|
232
235
|
} else {
|
|
233
|
-
throw new
|
|
236
|
+
throw new EngineError(
|
|
237
|
+
"invalid_parent_ref",
|
|
234
238
|
`parent_ref "${nodeInput.parent_ref}" is neither a batch ref nor an existing node ID`
|
|
235
239
|
);
|
|
236
240
|
}
|
|
@@ -247,7 +251,8 @@ function handlePlan(input, agent) {
|
|
|
247
251
|
}
|
|
248
252
|
project = parentNode.project;
|
|
249
253
|
} else {
|
|
250
|
-
throw new
|
|
254
|
+
throw new EngineError(
|
|
255
|
+
"missing_parent",
|
|
251
256
|
`Node "${nodeInput.ref}" has no parent_ref. All planned nodes must have a parent (an existing node or a batch ref).`
|
|
252
257
|
);
|
|
253
258
|
}
|
|
@@ -272,7 +277,8 @@ function handlePlan(input, agent) {
|
|
|
272
277
|
if (existing) {
|
|
273
278
|
toId = existing.id;
|
|
274
279
|
} else {
|
|
275
|
-
throw new
|
|
280
|
+
throw new EngineError(
|
|
281
|
+
"invalid_depends_on",
|
|
276
282
|
`depends_on "${dep}" in node "${nodeInput.ref}" is neither a batch ref nor an existing node ID`
|
|
277
283
|
);
|
|
278
284
|
}
|
|
@@ -284,7 +290,8 @@ function handlePlan(input, agent) {
|
|
|
284
290
|
agent
|
|
285
291
|
});
|
|
286
292
|
if (result.rejected) {
|
|
287
|
-
throw new
|
|
293
|
+
throw new EngineError(
|
|
294
|
+
"edge_rejected",
|
|
288
295
|
`Dependency edge from "${nodeInput.ref}" to "${dep}" rejected: ${result.reason}`
|
|
289
296
|
);
|
|
290
297
|
}
|
|
@@ -311,6 +318,15 @@ function handleUpdate(input, agent) {
|
|
|
311
318
|
const resolvedIds = [];
|
|
312
319
|
const resolvedProjects = /* @__PURE__ */ new Set();
|
|
313
320
|
for (const entry of updates) {
|
|
321
|
+
if (entry.expected_rev !== void 0) {
|
|
322
|
+
const current = getNodeOrThrow(entry.node_id);
|
|
323
|
+
if (current.rev !== entry.expected_rev) {
|
|
324
|
+
throw new EngineError(
|
|
325
|
+
"rev_mismatch",
|
|
326
|
+
`Node ${entry.node_id} has rev ${current.rev}, expected ${entry.expected_rev}. Another agent may have modified it. Re-read and retry.`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
314
330
|
let evidence = entry.add_evidence;
|
|
315
331
|
if (entry.resolved_reason) {
|
|
316
332
|
evidence = [...evidence ?? [], { type: "note", ref: entry.resolved_reason }];
|
|
@@ -320,6 +336,8 @@ function handleUpdate(input, agent) {
|
|
|
320
336
|
agent,
|
|
321
337
|
resolved: entry.resolved,
|
|
322
338
|
discovery: entry.discovery,
|
|
339
|
+
blocked: entry.blocked,
|
|
340
|
+
blocked_reason: entry.blocked_reason,
|
|
323
341
|
state: entry.state,
|
|
324
342
|
summary: entry.summary,
|
|
325
343
|
properties: entry.properties,
|
|
@@ -445,6 +463,7 @@ function buildNodeTree(nodeId, currentDepth, maxDepth) {
|
|
|
445
463
|
if (children.length === 0) {
|
|
446
464
|
return tree;
|
|
447
465
|
}
|
|
466
|
+
tree.progress = getSubtreeProgress(nodeId);
|
|
448
467
|
if (currentDepth < maxDepth) {
|
|
449
468
|
tree.children = children.map(
|
|
450
469
|
(child) => buildNodeTree(child.id, currentDepth + 1, maxDepth)
|
|
@@ -517,8 +536,10 @@ function handleQuery(input) {
|
|
|
517
536
|
params.push(...descendantIds);
|
|
518
537
|
}
|
|
519
538
|
if (filter?.has_evidence_type) {
|
|
520
|
-
conditions.push(
|
|
521
|
-
|
|
539
|
+
conditions.push(
|
|
540
|
+
`EXISTS (SELECT 1 FROM json_each(n.evidence) WHERE json_extract(value, '$.type') = ?)`
|
|
541
|
+
);
|
|
542
|
+
params.push(filter.has_evidence_type);
|
|
522
543
|
}
|
|
523
544
|
if (filter?.is_leaf) {
|
|
524
545
|
conditions.push(
|
|
@@ -527,6 +548,7 @@ function handleQuery(input) {
|
|
|
527
548
|
}
|
|
528
549
|
if (filter?.is_actionable) {
|
|
529
550
|
conditions.push("n.resolved = 0");
|
|
551
|
+
conditions.push("n.blocked = 0");
|
|
530
552
|
conditions.push(
|
|
531
553
|
"NOT EXISTS (SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0)"
|
|
532
554
|
);
|
|
@@ -541,11 +563,11 @@ function handleQuery(input) {
|
|
|
541
563
|
if (filter?.is_blocked) {
|
|
542
564
|
conditions.push("n.resolved = 0");
|
|
543
565
|
conditions.push(
|
|
544
|
-
`EXISTS (
|
|
566
|
+
`(n.blocked = 1 OR EXISTS (
|
|
545
567
|
SELECT 1 FROM edges e
|
|
546
568
|
JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0
|
|
547
569
|
WHERE e.from_node = n.id AND e.type = 'depends_on'
|
|
548
|
-
)`
|
|
570
|
+
))`
|
|
549
571
|
);
|
|
550
572
|
}
|
|
551
573
|
if (filter?.properties) {
|
|
@@ -637,7 +659,7 @@ function handleNext(input, agent, claimTtlMinutes = 60) {
|
|
|
637
659
|
}
|
|
638
660
|
let query = `
|
|
639
661
|
SELECT n.* FROM nodes n
|
|
640
|
-
WHERE n.project = ? AND n.resolved = 0
|
|
662
|
+
WHERE n.project = ? AND n.resolved = 0 AND n.blocked = 0
|
|
641
663
|
${scopeFilter}
|
|
642
664
|
AND NOT EXISTS (
|
|
643
665
|
SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0
|
|
@@ -716,7 +738,23 @@ function handleNext(input, agent, claimTtlMinutes = 60) {
|
|
|
716
738
|
resolved_deps
|
|
717
739
|
};
|
|
718
740
|
});
|
|
719
|
-
|
|
741
|
+
const claimRows = db.prepare(
|
|
742
|
+
`SELECT id, summary, json_extract(properties, '$._claimed_at') as claimed_at
|
|
743
|
+
FROM nodes
|
|
744
|
+
WHERE project = ? AND resolved = 0
|
|
745
|
+
AND json_extract(properties, '$._claimed_by') = ?
|
|
746
|
+
AND json_extract(properties, '$._claimed_at') > ?
|
|
747
|
+
ORDER BY json_extract(properties, '$._claimed_at') DESC`
|
|
748
|
+
).all(project, agent, claimCutoff);
|
|
749
|
+
const result = { nodes: results };
|
|
750
|
+
if (claimRows.length > 0) {
|
|
751
|
+
result.your_claims = claimRows.map((r) => ({
|
|
752
|
+
id: r.id,
|
|
753
|
+
summary: r.summary,
|
|
754
|
+
claimed_at: r.claimed_at
|
|
755
|
+
}));
|
|
756
|
+
}
|
|
757
|
+
return result;
|
|
720
758
|
}
|
|
721
759
|
|
|
722
760
|
// src/tools/restructure.ts
|
|
@@ -755,8 +793,12 @@ function handleMove(op, agent) {
|
|
|
755
793
|
const db = getDb();
|
|
756
794
|
const node = getNodeOrThrow(op.node_id);
|
|
757
795
|
const newParent = getNodeOrThrow(op.new_parent);
|
|
796
|
+
if (node.project !== newParent.project) {
|
|
797
|
+
throw new EngineError("cross_project", `Cannot move node across projects: "${node.project}" \u2192 "${newParent.project}"`);
|
|
798
|
+
}
|
|
758
799
|
if (wouldCreateParentCycle(op.node_id, op.new_parent)) {
|
|
759
|
-
throw new
|
|
800
|
+
throw new EngineError(
|
|
801
|
+
"cycle_detected",
|
|
760
802
|
`Move would create cycle: ${op.node_id} cannot be moved under ${op.new_parent}`
|
|
761
803
|
);
|
|
762
804
|
}
|
|
@@ -777,6 +819,9 @@ function handleMerge(op, agent) {
|
|
|
777
819
|
const db = getDb();
|
|
778
820
|
const source = getNodeOrThrow(op.source);
|
|
779
821
|
const target = getNodeOrThrow(op.target);
|
|
822
|
+
if (source.project !== target.project) {
|
|
823
|
+
throw new EngineError("cross_project", `Cannot merge nodes across projects: "${source.project}" \u2192 "${target.project}"`);
|
|
824
|
+
}
|
|
780
825
|
const movedChildren = db.prepare("SELECT id FROM nodes WHERE parent = ?").all(op.source);
|
|
781
826
|
db.prepare("UPDATE nodes SET parent = ?, updated_at = ? WHERE parent = ?").run(
|
|
782
827
|
op.target,
|
|
@@ -821,9 +866,7 @@ function handleMerge(op, agent) {
|
|
|
821
866
|
logEvent(op.target, agent, "merged", [
|
|
822
867
|
{ field: "merged_from", before: null, after: op.source }
|
|
823
868
|
]);
|
|
824
|
-
|
|
825
|
-
{ field: "merged_into", before: null, after: op.target }
|
|
826
|
-
]);
|
|
869
|
+
db.prepare("DELETE FROM events WHERE node_id = ?").run(op.source);
|
|
827
870
|
db.prepare("DELETE FROM edges WHERE from_node = ? OR to_node = ?").run(
|
|
828
871
|
op.source,
|
|
829
872
|
op.source
|
|
@@ -854,6 +897,20 @@ function handleDrop(op, agent) {
|
|
|
854
897
|
result: `dropped ${allIds.length} node(s): ${op.reason}`
|
|
855
898
|
};
|
|
856
899
|
}
|
|
900
|
+
function handleDelete(op, agent) {
|
|
901
|
+
const db = getDb();
|
|
902
|
+
getNodeOrThrow(op.node_id);
|
|
903
|
+
const descendants = getAllDescendants(op.node_id);
|
|
904
|
+
const allIds = [op.node_id, ...descendants];
|
|
905
|
+
const placeholders = allIds.map(() => "?").join(",");
|
|
906
|
+
db.prepare(`DELETE FROM events WHERE node_id IN (${placeholders})`).run(...allIds);
|
|
907
|
+
db.prepare(`DELETE FROM edges WHERE from_node IN (${placeholders}) OR to_node IN (${placeholders})`).run(...allIds, ...allIds);
|
|
908
|
+
db.prepare(`DELETE FROM nodes WHERE id IN (${placeholders})`).run(...allIds);
|
|
909
|
+
return {
|
|
910
|
+
node_id: op.node_id,
|
|
911
|
+
result: `deleted ${allIds.length} node(s)`
|
|
912
|
+
};
|
|
913
|
+
}
|
|
857
914
|
function handleRestructure(input, agent) {
|
|
858
915
|
const operations = requireArray(input?.operations, "operations");
|
|
859
916
|
for (let i = 0; i < operations.length; i++) {
|
|
@@ -868,8 +925,10 @@ function handleRestructure(input, agent) {
|
|
|
868
925
|
} else if (op.op === "drop") {
|
|
869
926
|
requireString(op.node_id, `operations[${i}].node_id`);
|
|
870
927
|
requireString(op.reason, `operations[${i}].reason`);
|
|
928
|
+
} else if (op.op === "delete") {
|
|
929
|
+
requireString(op.node_id, `operations[${i}].node_id`);
|
|
871
930
|
} else {
|
|
872
|
-
throw new
|
|
931
|
+
throw new EngineError("unknown_op", `Unknown operation: ${op.op}`);
|
|
873
932
|
}
|
|
874
933
|
}
|
|
875
934
|
const db = getDb();
|
|
@@ -892,6 +951,10 @@ function handleRestructure(input, agent) {
|
|
|
892
951
|
detail = handleDrop(op, agent);
|
|
893
952
|
project = getNode(op.node_id)?.project ?? project;
|
|
894
953
|
break;
|
|
954
|
+
case "delete":
|
|
955
|
+
project = getNode(op.node_id)?.project ?? project;
|
|
956
|
+
detail = handleDelete(op, agent);
|
|
957
|
+
break;
|
|
895
958
|
default:
|
|
896
959
|
throw new Error(`Unknown operation: ${op.op}`);
|
|
897
960
|
}
|
|
@@ -1082,15 +1145,25 @@ function buildTree(node, currentDepth, maxDepth, stats) {
|
|
|
1082
1145
|
resolved: node.resolved,
|
|
1083
1146
|
properties: node.properties
|
|
1084
1147
|
};
|
|
1085
|
-
|
|
1148
|
+
let subtotal = 1;
|
|
1149
|
+
let subresolved = node.resolved ? 1 : 0;
|
|
1150
|
+
if (children.length === 0) return { treeNode, subtotal, subresolved };
|
|
1086
1151
|
if (currentDepth < maxDepth) {
|
|
1087
|
-
treeNode.children =
|
|
1088
|
-
|
|
1089
|
-
|
|
1152
|
+
treeNode.children = [];
|
|
1153
|
+
for (const child of children) {
|
|
1154
|
+
const result = buildTree(child, currentDepth + 1, maxDepth, stats);
|
|
1155
|
+
treeNode.children.push(result.treeNode);
|
|
1156
|
+
subtotal += result.subtotal;
|
|
1157
|
+
subresolved += result.subresolved;
|
|
1158
|
+
}
|
|
1090
1159
|
} else {
|
|
1091
1160
|
treeNode.child_count = children.length;
|
|
1161
|
+
const progress = getSubtreeProgress(node.id);
|
|
1162
|
+
subtotal = progress.total;
|
|
1163
|
+
subresolved = progress.resolved;
|
|
1092
1164
|
}
|
|
1093
|
-
|
|
1165
|
+
treeNode.progress = { resolved: subresolved, total: subtotal };
|
|
1166
|
+
return { treeNode, subtotal, subresolved };
|
|
1094
1167
|
}
|
|
1095
1168
|
function handleTree(input) {
|
|
1096
1169
|
const project = requireString(input?.project, "project");
|
|
@@ -1100,10 +1173,10 @@ function handleTree(input) {
|
|
|
1100
1173
|
throw new EngineError("project_not_found", `Project not found: ${project}`);
|
|
1101
1174
|
}
|
|
1102
1175
|
const stats = { total: 0, resolved: 0 };
|
|
1103
|
-
const
|
|
1176
|
+
const { treeNode } = buildTree(root, 0, depth, stats);
|
|
1104
1177
|
return {
|
|
1105
1178
|
project,
|
|
1106
|
-
tree,
|
|
1179
|
+
tree: treeNode,
|
|
1107
1180
|
stats: {
|
|
1108
1181
|
total: stats.total,
|
|
1109
1182
|
resolved: stats.resolved,
|
|
@@ -1231,7 +1304,7 @@ function checkScope(_tier, scope) {
|
|
|
1231
1304
|
|
|
1232
1305
|
// src/server.ts
|
|
1233
1306
|
import { createHash } from "crypto";
|
|
1234
|
-
import { mkdirSync, readFileSync } from "fs";
|
|
1307
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
1235
1308
|
import { homedir } from "os";
|
|
1236
1309
|
import { join, resolve, dirname } from "path";
|
|
1237
1310
|
import { fileURLToPath } from "url";
|
|
@@ -1266,6 +1339,27 @@ async function checkForUpdate() {
|
|
|
1266
1339
|
} catch {
|
|
1267
1340
|
}
|
|
1268
1341
|
}
|
|
1342
|
+
function checkAndUpdateAgentFile() {
|
|
1343
|
+
try {
|
|
1344
|
+
const projectRoot = resolve(".");
|
|
1345
|
+
const agentPath = join(projectRoot, ".claude", "agents", "graph.md");
|
|
1346
|
+
const latest = handleAgentConfig(PKG_VERSION).agent_file;
|
|
1347
|
+
if (existsSync(agentPath)) {
|
|
1348
|
+
const current = readFileSync(agentPath, "utf-8");
|
|
1349
|
+
if (current === latest) return null;
|
|
1350
|
+
const match = current.match(/^---[\s\S]*?version:\s*(\S+)[\s\S]*?---/);
|
|
1351
|
+
const oldVersion = match?.[1] ?? "unknown";
|
|
1352
|
+
writeFileSync(agentPath, latest, "utf-8");
|
|
1353
|
+
return `[graph] Updated .claude/agents/graph.md (${oldVersion} \u2192 ${PKG_VERSION})`;
|
|
1354
|
+
} else {
|
|
1355
|
+
mkdirSync(dirname(agentPath), { recursive: true });
|
|
1356
|
+
writeFileSync(agentPath, latest, "utf-8");
|
|
1357
|
+
return `[graph] Created .claude/agents/graph.md`;
|
|
1358
|
+
}
|
|
1359
|
+
} catch {
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1269
1363
|
var TOOLS = [
|
|
1270
1364
|
{
|
|
1271
1365
|
name: "graph_open",
|
|
@@ -1280,6 +1374,10 @@ var TOOLS = [
|
|
|
1280
1374
|
goal: {
|
|
1281
1375
|
type: "string",
|
|
1282
1376
|
description: "Project goal/description. Used on creation only."
|
|
1377
|
+
},
|
|
1378
|
+
skip_discovery: {
|
|
1379
|
+
type: "boolean",
|
|
1380
|
+
description: "Skip discovery phase \u2014 create project ready for immediate planning. Default false."
|
|
1283
1381
|
}
|
|
1284
1382
|
}
|
|
1285
1383
|
}
|
|
@@ -1381,9 +1479,12 @@ var TOOLS = [
|
|
|
1381
1479
|
type: "object",
|
|
1382
1480
|
properties: {
|
|
1383
1481
|
node_id: { type: "string" },
|
|
1482
|
+
expected_rev: { type: "number", description: "Optimistic concurrency: reject if node's current rev doesn't match. Prevents silent overwrites by concurrent agents." },
|
|
1384
1483
|
resolved: { type: "boolean" },
|
|
1385
1484
|
resolved_reason: { type: "string", description: "Shorthand: auto-creates a note evidence entry. Use instead of add_evidence for simple cases." },
|
|
1386
1485
|
discovery: { type: "string", description: "Discovery phase status: 'pending' or 'done'. Set to 'done' after completing discovery interview." },
|
|
1486
|
+
blocked: { type: "boolean", description: "Manually block/unblock a node. Blocked nodes are skipped by graph_next. Use for external blockers (e.g., waiting on domain purchase, another team)." },
|
|
1487
|
+
blocked_reason: { type: "string", description: "Why the node is blocked. Cleared automatically when unblocking." },
|
|
1387
1488
|
state: { description: "Agent-defined state, any type" },
|
|
1388
1489
|
summary: { type: "string" },
|
|
1389
1490
|
properties: {
|
|
@@ -1487,7 +1588,7 @@ var TOOLS = [
|
|
|
1487
1588
|
},
|
|
1488
1589
|
{
|
|
1489
1590
|
name: "graph_restructure",
|
|
1490
|
-
description: "Modify graph structure: move (reparent), merge (combine two nodes), drop (resolve node + subtree with reason). Atomic. Reports newly_actionable nodes.",
|
|
1591
|
+
description: "Modify graph structure: move (reparent), merge (combine two nodes), drop (resolve node + subtree with reason), delete (permanently remove node + subtree). Atomic. Reports newly_actionable nodes.",
|
|
1491
1592
|
inputSchema: {
|
|
1492
1593
|
type: "object",
|
|
1493
1594
|
properties: {
|
|
@@ -1498,7 +1599,7 @@ var TOOLS = [
|
|
|
1498
1599
|
properties: {
|
|
1499
1600
|
op: {
|
|
1500
1601
|
type: "string",
|
|
1501
|
-
enum: ["move", "merge", "drop"]
|
|
1602
|
+
enum: ["move", "merge", "drop", "delete"]
|
|
1502
1603
|
},
|
|
1503
1604
|
node_id: { type: "string", description: "For move and drop" },
|
|
1504
1605
|
new_parent: { type: "string", description: "For move" },
|
|
@@ -1623,7 +1724,9 @@ async function startServer() {
|
|
|
1623
1724
|
{ name: "graph", version: PKG_VERSION },
|
|
1624
1725
|
{ capabilities: { tools: {}, resources: {} } }
|
|
1625
1726
|
);
|
|
1626
|
-
|
|
1727
|
+
if (process.env.GRAPH_UPDATE_CHECK === "1") {
|
|
1728
|
+
checkForUpdate();
|
|
1729
|
+
}
|
|
1627
1730
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
1628
1731
|
tools: TOOLS
|
|
1629
1732
|
}));
|
|
@@ -1635,7 +1738,7 @@ async function startServer() {
|
|
|
1635
1738
|
case "graph_open": {
|
|
1636
1739
|
const openArgs = args;
|
|
1637
1740
|
if (openArgs?.project) {
|
|
1638
|
-
const { getProjectRoot: getProjectRoot2 } = await import("./nodes-
|
|
1741
|
+
const { getProjectRoot: getProjectRoot2 } = await import("./nodes-YNM6KEK2.js");
|
|
1639
1742
|
if (!getProjectRoot2(openArgs.project)) {
|
|
1640
1743
|
checkProjectLimit(tier);
|
|
1641
1744
|
}
|
|
@@ -1646,7 +1749,7 @@ async function startServer() {
|
|
|
1646
1749
|
case "graph_plan": {
|
|
1647
1750
|
const planArgs = args;
|
|
1648
1751
|
if (planArgs?.nodes?.length > 0) {
|
|
1649
|
-
const { getNode: getNode2 } = await import("./nodes-
|
|
1752
|
+
const { getNode: getNode2 } = await import("./nodes-YNM6KEK2.js");
|
|
1650
1753
|
const firstParent = planArgs.nodes[0]?.parent_ref;
|
|
1651
1754
|
if (firstParent && typeof firstParent === "string" && !planArgs.nodes.some((n) => n.ref === firstParent)) {
|
|
1652
1755
|
const parentNode = getNode2(firstParent);
|
|
@@ -1694,7 +1797,7 @@ async function startServer() {
|
|
|
1694
1797
|
result = handleTree(args);
|
|
1695
1798
|
break;
|
|
1696
1799
|
case "graph_agent_config":
|
|
1697
|
-
result = handleAgentConfig();
|
|
1800
|
+
result = handleAgentConfig(PKG_VERSION);
|
|
1698
1801
|
break;
|
|
1699
1802
|
case "graph_knowledge_write":
|
|
1700
1803
|
checkKnowledgeTier(tier);
|
|
@@ -1724,7 +1827,11 @@ async function startServer() {
|
|
|
1724
1827
|
{ type: "text", text: JSON.stringify(result, null, 2) }
|
|
1725
1828
|
];
|
|
1726
1829
|
if (versionBanner) {
|
|
1727
|
-
|
|
1830
|
+
const agentNote = checkAndUpdateAgentFile();
|
|
1831
|
+
const bannerParts = [versionBanner];
|
|
1832
|
+
if (agentNote) bannerParts.push(agentNote);
|
|
1833
|
+
if (updateWarning) bannerParts.push(updateWarning);
|
|
1834
|
+
content.push({ type: "text", text: bannerParts.join("\n") });
|
|
1728
1835
|
versionBanner = null;
|
|
1729
1836
|
updateWarning = null;
|
|
1730
1837
|
}
|
|
@@ -1767,7 +1874,7 @@ async function startServer() {
|
|
|
1767
1874
|
}));
|
|
1768
1875
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1769
1876
|
try {
|
|
1770
|
-
const { listProjects: listProjects2 } = await import("./nodes-
|
|
1877
|
+
const { listProjects: listProjects2 } = await import("./nodes-YNM6KEK2.js");
|
|
1771
1878
|
const projects = listProjects2();
|
|
1772
1879
|
const resources = projects.flatMap((p) => [
|
|
1773
1880
|
{
|
|
@@ -1838,4 +1945,4 @@ async function startServer() {
|
|
|
1838
1945
|
export {
|
|
1839
1946
|
startServer
|
|
1840
1947
|
};
|
|
1841
|
-
//# sourceMappingURL=server-
|
|
1948
|
+
//# sourceMappingURL=server-X36DXLEG.js.map
|