@vpxa/kb 0.1.1
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/LICENSE +21 -0
- package/README.md +1140 -0
- package/bin/kb.mjs +10 -0
- package/package.json +67 -0
- package/packages/analyzers/dist/blast-radius-analyzer.d.ts +23 -0
- package/packages/analyzers/dist/blast-radius-analyzer.js +114 -0
- package/packages/analyzers/dist/dependency-analyzer.d.ts +29 -0
- package/packages/analyzers/dist/dependency-analyzer.js +425 -0
- package/packages/analyzers/dist/diagram-generator.d.ts +13 -0
- package/packages/analyzers/dist/diagram-generator.js +86 -0
- package/packages/analyzers/dist/entry-point-analyzer.d.ts +19 -0
- package/packages/analyzers/dist/entry-point-analyzer.js +239 -0
- package/packages/analyzers/dist/index.d.ts +14 -0
- package/packages/analyzers/dist/index.js +23 -0
- package/packages/analyzers/dist/knowledge-producer.d.ts +32 -0
- package/packages/analyzers/dist/knowledge-producer.js +113 -0
- package/packages/analyzers/dist/pattern-analyzer.d.ts +12 -0
- package/packages/analyzers/dist/pattern-analyzer.js +359 -0
- package/packages/analyzers/dist/regex-call-graph.d.ts +17 -0
- package/packages/analyzers/dist/regex-call-graph.js +428 -0
- package/packages/analyzers/dist/structure-analyzer.d.ts +11 -0
- package/packages/analyzers/dist/structure-analyzer.js +258 -0
- package/packages/analyzers/dist/symbol-analyzer.d.ts +10 -0
- package/packages/analyzers/dist/symbol-analyzer.js +442 -0
- package/packages/analyzers/dist/ts-call-graph.d.ts +27 -0
- package/packages/analyzers/dist/ts-call-graph.js +160 -0
- package/packages/analyzers/dist/types.d.ts +98 -0
- package/packages/analyzers/dist/types.js +1 -0
- package/packages/chunker/dist/call-graph-extractor.d.ts +22 -0
- package/packages/chunker/dist/call-graph-extractor.js +90 -0
- package/packages/chunker/dist/chunker-factory.d.ts +7 -0
- package/packages/chunker/dist/chunker-factory.js +36 -0
- package/packages/chunker/dist/chunker.interface.d.ts +10 -0
- package/packages/chunker/dist/chunker.interface.js +1 -0
- package/packages/chunker/dist/code-chunker.d.ts +14 -0
- package/packages/chunker/dist/code-chunker.js +134 -0
- package/packages/chunker/dist/generic-chunker.d.ts +12 -0
- package/packages/chunker/dist/generic-chunker.js +72 -0
- package/packages/chunker/dist/index.d.ts +8 -0
- package/packages/chunker/dist/index.js +21 -0
- package/packages/chunker/dist/markdown-chunker.d.ts +14 -0
- package/packages/chunker/dist/markdown-chunker.js +122 -0
- package/packages/chunker/dist/treesitter-chunker.d.ts +47 -0
- package/packages/chunker/dist/treesitter-chunker.js +234 -0
- package/packages/cli/dist/commands/analyze.d.ts +3 -0
- package/packages/cli/dist/commands/analyze.js +112 -0
- package/packages/cli/dist/commands/context-cmds.d.ts +3 -0
- package/packages/cli/dist/commands/context-cmds.js +155 -0
- package/packages/cli/dist/commands/environment.d.ts +3 -0
- package/packages/cli/dist/commands/environment.js +204 -0
- package/packages/cli/dist/commands/execution.d.ts +3 -0
- package/packages/cli/dist/commands/execution.js +137 -0
- package/packages/cli/dist/commands/graph.d.ts +3 -0
- package/packages/cli/dist/commands/graph.js +81 -0
- package/packages/cli/dist/commands/init.d.ts +8 -0
- package/packages/cli/dist/commands/init.js +87 -0
- package/packages/cli/dist/commands/knowledge.d.ts +3 -0
- package/packages/cli/dist/commands/knowledge.js +139 -0
- package/packages/cli/dist/commands/search.d.ts +3 -0
- package/packages/cli/dist/commands/search.js +267 -0
- package/packages/cli/dist/commands/system.d.ts +3 -0
- package/packages/cli/dist/commands/system.js +241 -0
- package/packages/cli/dist/commands/workspace.d.ts +3 -0
- package/packages/cli/dist/commands/workspace.js +388 -0
- package/packages/cli/dist/context.d.ts +5 -0
- package/packages/cli/dist/context.js +14 -0
- package/packages/cli/dist/helpers.d.ts +52 -0
- package/packages/cli/dist/helpers.js +458 -0
- package/packages/cli/dist/index.d.ts +8 -0
- package/packages/cli/dist/index.js +69 -0
- package/packages/cli/dist/kb-init.d.ts +57 -0
- package/packages/cli/dist/kb-init.js +82 -0
- package/packages/cli/dist/types.d.ts +7 -0
- package/packages/cli/dist/types.js +1 -0
- package/packages/core/dist/constants.d.ts +49 -0
- package/packages/core/dist/constants.js +43 -0
- package/packages/core/dist/content-detector.d.ts +9 -0
- package/packages/core/dist/content-detector.js +79 -0
- package/packages/core/dist/errors.d.ts +18 -0
- package/packages/core/dist/errors.js +40 -0
- package/packages/core/dist/index.d.ts +6 -0
- package/packages/core/dist/index.js +9 -0
- package/packages/core/dist/logger.d.ts +9 -0
- package/packages/core/dist/logger.js +34 -0
- package/packages/core/dist/types.d.ts +108 -0
- package/packages/core/dist/types.js +1 -0
- package/packages/embeddings/dist/embedder.interface.d.ts +24 -0
- package/packages/embeddings/dist/embedder.interface.js +1 -0
- package/packages/embeddings/dist/index.d.ts +3 -0
- package/packages/embeddings/dist/index.js +5 -0
- package/packages/embeddings/dist/onnx-embedder.d.ts +24 -0
- package/packages/embeddings/dist/onnx-embedder.js +82 -0
- package/packages/indexer/dist/file-hasher.d.ts +11 -0
- package/packages/indexer/dist/file-hasher.js +13 -0
- package/packages/indexer/dist/filesystem-crawler.d.ts +27 -0
- package/packages/indexer/dist/filesystem-crawler.js +125 -0
- package/packages/indexer/dist/graph-extractor.d.ts +22 -0
- package/packages/indexer/dist/graph-extractor.js +111 -0
- package/packages/indexer/dist/incremental-indexer.d.ts +47 -0
- package/packages/indexer/dist/incremental-indexer.js +278 -0
- package/packages/indexer/dist/index.d.ts +5 -0
- package/packages/indexer/dist/index.js +14 -0
- package/packages/server/dist/api.d.ts +8 -0
- package/packages/server/dist/api.js +9 -0
- package/packages/server/dist/config.d.ts +3 -0
- package/packages/server/dist/config.js +75 -0
- package/packages/server/dist/curated-manager.d.ts +86 -0
- package/packages/server/dist/curated-manager.js +357 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.js +134 -0
- package/packages/server/dist/replay-interceptor.d.ts +11 -0
- package/packages/server/dist/replay-interceptor.js +38 -0
- package/packages/server/dist/resources/resources.d.ts +4 -0
- package/packages/server/dist/resources/resources.js +40 -0
- package/packages/server/dist/server.d.ts +21 -0
- package/packages/server/dist/server.js +247 -0
- package/packages/server/dist/tools/analyze.tools.d.ts +11 -0
- package/packages/server/dist/tools/analyze.tools.js +288 -0
- package/packages/server/dist/tools/forge.tools.d.ts +12 -0
- package/packages/server/dist/tools/forge.tools.js +501 -0
- package/packages/server/dist/tools/forget.tool.d.ts +4 -0
- package/packages/server/dist/tools/forget.tool.js +43 -0
- package/packages/server/dist/tools/graph.tool.d.ts +4 -0
- package/packages/server/dist/tools/graph.tool.js +110 -0
- package/packages/server/dist/tools/list.tool.d.ts +4 -0
- package/packages/server/dist/tools/list.tool.js +56 -0
- package/packages/server/dist/tools/lookup.tool.d.ts +4 -0
- package/packages/server/dist/tools/lookup.tool.js +53 -0
- package/packages/server/dist/tools/onboard.tool.d.ts +5 -0
- package/packages/server/dist/tools/onboard.tool.js +112 -0
- package/packages/server/dist/tools/produce.tool.d.ts +3 -0
- package/packages/server/dist/tools/produce.tool.js +74 -0
- package/packages/server/dist/tools/read.tool.d.ts +4 -0
- package/packages/server/dist/tools/read.tool.js +49 -0
- package/packages/server/dist/tools/reindex.tool.d.ts +7 -0
- package/packages/server/dist/tools/reindex.tool.js +70 -0
- package/packages/server/dist/tools/remember.tool.d.ts +4 -0
- package/packages/server/dist/tools/remember.tool.js +45 -0
- package/packages/server/dist/tools/replay.tool.d.ts +3 -0
- package/packages/server/dist/tools/replay.tool.js +89 -0
- package/packages/server/dist/tools/search.tool.d.ts +5 -0
- package/packages/server/dist/tools/search.tool.js +331 -0
- package/packages/server/dist/tools/status.tool.d.ts +4 -0
- package/packages/server/dist/tools/status.tool.js +68 -0
- package/packages/server/dist/tools/toolkit.tools.d.ts +35 -0
- package/packages/server/dist/tools/toolkit.tools.js +1674 -0
- package/packages/server/dist/tools/update.tool.d.ts +4 -0
- package/packages/server/dist/tools/update.tool.js +42 -0
- package/packages/server/dist/tools/utility.tools.d.ts +15 -0
- package/packages/server/dist/tools/utility.tools.js +461 -0
- package/packages/store/dist/graph-store.interface.d.ts +104 -0
- package/packages/store/dist/graph-store.interface.js +1 -0
- package/packages/store/dist/index.d.ts +6 -0
- package/packages/store/dist/index.js +9 -0
- package/packages/store/dist/lance-store.d.ts +32 -0
- package/packages/store/dist/lance-store.js +258 -0
- package/packages/store/dist/sqlite-graph-store.d.ts +43 -0
- package/packages/store/dist/sqlite-graph-store.js +374 -0
- package/packages/store/dist/store-factory.d.ts +9 -0
- package/packages/store/dist/store-factory.js +14 -0
- package/packages/store/dist/store.interface.d.ts +48 -0
- package/packages/store/dist/store.interface.js +1 -0
- package/packages/tools/dist/batch.d.ts +21 -0
- package/packages/tools/dist/batch.js +45 -0
- package/packages/tools/dist/changelog.d.ts +34 -0
- package/packages/tools/dist/changelog.js +112 -0
- package/packages/tools/dist/check.d.ts +26 -0
- package/packages/tools/dist/check.js +59 -0
- package/packages/tools/dist/checkpoint.d.ts +17 -0
- package/packages/tools/dist/checkpoint.js +43 -0
- package/packages/tools/dist/codemod.d.ts +37 -0
- package/packages/tools/dist/codemod.js +69 -0
- package/packages/tools/dist/compact.d.ts +41 -0
- package/packages/tools/dist/compact.js +60 -0
- package/packages/tools/dist/data-transform.d.ts +10 -0
- package/packages/tools/dist/data-transform.js +124 -0
- package/packages/tools/dist/dead-symbols.d.ts +21 -0
- package/packages/tools/dist/dead-symbols.js +71 -0
- package/packages/tools/dist/delegate.d.ts +34 -0
- package/packages/tools/dist/delegate.js +130 -0
- package/packages/tools/dist/diff-parse.d.ts +26 -0
- package/packages/tools/dist/diff-parse.js +153 -0
- package/packages/tools/dist/digest.d.ts +53 -0
- package/packages/tools/dist/digest.js +242 -0
- package/packages/tools/dist/encode.d.ts +14 -0
- package/packages/tools/dist/encode.js +46 -0
- package/packages/tools/dist/env-info.d.ts +28 -0
- package/packages/tools/dist/env-info.js +58 -0
- package/packages/tools/dist/eval.d.ts +13 -0
- package/packages/tools/dist/eval.js +79 -0
- package/packages/tools/dist/evidence-map.d.ts +79 -0
- package/packages/tools/dist/evidence-map.js +203 -0
- package/packages/tools/dist/file-summary.d.ts +32 -0
- package/packages/tools/dist/file-summary.js +106 -0
- package/packages/tools/dist/file-walk.d.ts +4 -0
- package/packages/tools/dist/file-walk.js +75 -0
- package/packages/tools/dist/find-examples.d.ts +25 -0
- package/packages/tools/dist/find-examples.js +48 -0
- package/packages/tools/dist/find.d.ts +47 -0
- package/packages/tools/dist/find.js +120 -0
- package/packages/tools/dist/forge-classify.d.ts +44 -0
- package/packages/tools/dist/forge-classify.js +319 -0
- package/packages/tools/dist/forge-ground.d.ts +64 -0
- package/packages/tools/dist/forge-ground.js +184 -0
- package/packages/tools/dist/git-context.d.ts +22 -0
- package/packages/tools/dist/git-context.js +46 -0
- package/packages/tools/dist/graph-query.d.ts +89 -0
- package/packages/tools/dist/graph-query.js +194 -0
- package/packages/tools/dist/health.d.ts +14 -0
- package/packages/tools/dist/health.js +118 -0
- package/packages/tools/dist/http-request.d.ts +23 -0
- package/packages/tools/dist/http-request.js +58 -0
- package/packages/tools/dist/index.d.ts +49 -0
- package/packages/tools/dist/index.js +273 -0
- package/packages/tools/dist/lane.d.ts +39 -0
- package/packages/tools/dist/lane.js +227 -0
- package/packages/tools/dist/measure.d.ts +38 -0
- package/packages/tools/dist/measure.js +119 -0
- package/packages/tools/dist/onboard.d.ts +41 -0
- package/packages/tools/dist/onboard.js +1139 -0
- package/packages/tools/dist/parse-output.d.ts +80 -0
- package/packages/tools/dist/parse-output.js +158 -0
- package/packages/tools/dist/process-manager.d.ts +18 -0
- package/packages/tools/dist/process-manager.js +69 -0
- package/packages/tools/dist/queue.d.ts +38 -0
- package/packages/tools/dist/queue.js +126 -0
- package/packages/tools/dist/regex-test.d.ts +31 -0
- package/packages/tools/dist/regex-test.js +39 -0
- package/packages/tools/dist/rename.d.ts +29 -0
- package/packages/tools/dist/rename.js +70 -0
- package/packages/tools/dist/replay.d.ts +56 -0
- package/packages/tools/dist/replay.js +108 -0
- package/packages/tools/dist/schema-validate.d.ts +23 -0
- package/packages/tools/dist/schema-validate.js +141 -0
- package/packages/tools/dist/scope-map.d.ts +52 -0
- package/packages/tools/dist/scope-map.js +72 -0
- package/packages/tools/dist/snippet.d.ts +34 -0
- package/packages/tools/dist/snippet.js +80 -0
- package/packages/tools/dist/stash.d.ts +12 -0
- package/packages/tools/dist/stash.js +60 -0
- package/packages/tools/dist/stratum-card.d.ts +31 -0
- package/packages/tools/dist/stratum-card.js +239 -0
- package/packages/tools/dist/symbol.d.ts +28 -0
- package/packages/tools/dist/symbol.js +87 -0
- package/packages/tools/dist/test-run.d.ts +23 -0
- package/packages/tools/dist/test-run.js +55 -0
- package/packages/tools/dist/text-utils.d.ts +16 -0
- package/packages/tools/dist/text-utils.js +31 -0
- package/packages/tools/dist/time-utils.d.ts +18 -0
- package/packages/tools/dist/time-utils.js +135 -0
- package/packages/tools/dist/trace.d.ts +24 -0
- package/packages/tools/dist/trace.js +114 -0
- package/packages/tools/dist/truncation.d.ts +22 -0
- package/packages/tools/dist/truncation.js +45 -0
- package/packages/tools/dist/watch.d.ts +30 -0
- package/packages/tools/dist/watch.js +61 -0
- package/packages/tools/dist/web-fetch.d.ts +45 -0
- package/packages/tools/dist/web-fetch.js +249 -0
- package/packages/tools/dist/web-search.d.ts +23 -0
- package/packages/tools/dist/web-search.js +46 -0
- package/packages/tools/dist/workset.d.ts +45 -0
- package/packages/tools/dist/workset.js +77 -0
- package/packages/tui/dist/App.d.ts +8 -0
- package/packages/tui/dist/App.js +52659 -0
- package/packages/tui/dist/index.d.ts +19 -0
- package/packages/tui/dist/index.js +54742 -0
- package/packages/tui/dist/panels/CuratedPanel.d.ts +8 -0
- package/packages/tui/dist/panels/CuratedPanel.js +34452 -0
- package/packages/tui/dist/panels/LogPanel.d.ts +3 -0
- package/packages/tui/dist/panels/LogPanel.js +51894 -0
- package/packages/tui/dist/panels/SearchPanel.d.ts +10 -0
- package/packages/tui/dist/panels/SearchPanel.js +34985 -0
- package/packages/tui/dist/panels/StatusPanel.d.ts +8 -0
- package/packages/tui/dist/panels/StatusPanel.js +34465 -0
- package/skills/knowledge-base/SKILL.md +316 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
import { digest, evidenceMap, forgeClassify, forgeGround, stratumCard } from "@kb/tools";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
function registerEvidenceMapTool(server) {
|
|
4
|
+
server.registerTool(
|
|
5
|
+
"evidence_map",
|
|
6
|
+
{
|
|
7
|
+
description: "FORGE Evidence Map \u2014 track critical-path claims as Verified/Assumed/Unresolved with receipts. Supports CRUD operations and deterministic Gate evaluation (YIELD/HOLD/HARD_BLOCK/FORCED_DELIVERY). Persists across tool calls.",
|
|
8
|
+
inputSchema: {
|
|
9
|
+
action: z.enum(["create", "add", "update", "get", "gate", "list", "delete"]).describe("Operation to perform"),
|
|
10
|
+
task_id: z.string().optional().describe("Task identifier (required for all except list)"),
|
|
11
|
+
tier: z.enum(["floor", "standard", "critical"]).optional().describe("FORGE tier (required for create)"),
|
|
12
|
+
claim: z.string().optional().describe("Critical-path claim text (for add)"),
|
|
13
|
+
status: z.enum(["V", "A", "U"]).optional().describe("Evidence status: V=Verified, A=Assumed, U=Unresolved"),
|
|
14
|
+
receipt: z.string().optional().describe("Evidence receipt: tool\u2192ref for V, reasoning for A, attempts for U"),
|
|
15
|
+
id: z.number().optional().describe("Entry ID (for update)"),
|
|
16
|
+
critical_path: z.boolean().default(true).describe("Whether this claim is on the critical path"),
|
|
17
|
+
unknown_type: z.enum(["contract", "convention", "freshness", "runtime", "data-flow", "impact"]).optional().describe("Typed unknown classification"),
|
|
18
|
+
retry_count: z.number().default(0).describe("Retry count for gate evaluation (0 = first attempt)"),
|
|
19
|
+
cwd: z.string().optional().describe(
|
|
20
|
+
"Working directory for evidence map storage (default: server cwd). Use root_path from forge_ground to match."
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
async ({
|
|
25
|
+
action,
|
|
26
|
+
task_id,
|
|
27
|
+
tier,
|
|
28
|
+
claim,
|
|
29
|
+
status,
|
|
30
|
+
receipt,
|
|
31
|
+
id,
|
|
32
|
+
critical_path,
|
|
33
|
+
unknown_type,
|
|
34
|
+
retry_count,
|
|
35
|
+
cwd
|
|
36
|
+
}) => {
|
|
37
|
+
try {
|
|
38
|
+
switch (action) {
|
|
39
|
+
case "create": {
|
|
40
|
+
if (!task_id) throw new Error("task_id required for create");
|
|
41
|
+
if (!tier) throw new Error("tier required for create");
|
|
42
|
+
evidenceMap({ action: "create", taskId: task_id, tier }, cwd);
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "text",
|
|
47
|
+
text: `Created evidence map "${task_id}" (tier: ${tier}).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
_Next: Use \`evidence_map\` with action "add" to record critical-path claims._`
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
case "add": {
|
|
56
|
+
if (!task_id) throw new Error("task_id required for add");
|
|
57
|
+
if (!claim) throw new Error("claim required for add");
|
|
58
|
+
if (!status) throw new Error("status required for add");
|
|
59
|
+
const result = evidenceMap(
|
|
60
|
+
{
|
|
61
|
+
action: "add",
|
|
62
|
+
taskId: task_id,
|
|
63
|
+
claim,
|
|
64
|
+
status,
|
|
65
|
+
receipt: receipt ?? "",
|
|
66
|
+
criticalPath: critical_path,
|
|
67
|
+
unknownType: unknown_type
|
|
68
|
+
},
|
|
69
|
+
cwd
|
|
70
|
+
);
|
|
71
|
+
const lines = [
|
|
72
|
+
`Added entry #${result.entry?.id} to "${task_id}": [${status}] ${claim}`
|
|
73
|
+
];
|
|
74
|
+
if (result.formattedMap) {
|
|
75
|
+
lines.push("", result.formattedMap);
|
|
76
|
+
}
|
|
77
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
78
|
+
}
|
|
79
|
+
case "update": {
|
|
80
|
+
if (!task_id) throw new Error("task_id required for update");
|
|
81
|
+
if (id === void 0) throw new Error("id required for update");
|
|
82
|
+
if (!status) throw new Error("status required for update");
|
|
83
|
+
const result = evidenceMap(
|
|
84
|
+
{
|
|
85
|
+
action: "update",
|
|
86
|
+
taskId: task_id,
|
|
87
|
+
id,
|
|
88
|
+
status,
|
|
89
|
+
receipt: receipt ?? ""
|
|
90
|
+
},
|
|
91
|
+
cwd
|
|
92
|
+
);
|
|
93
|
+
const lines = [`Updated entry #${id} in "${task_id}" \u2192 ${status}`];
|
|
94
|
+
if (result.formattedMap) {
|
|
95
|
+
lines.push("", result.formattedMap);
|
|
96
|
+
}
|
|
97
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
98
|
+
}
|
|
99
|
+
case "get": {
|
|
100
|
+
if (!task_id) throw new Error("task_id required for get");
|
|
101
|
+
const result = evidenceMap({ action: "get", taskId: task_id }, cwd);
|
|
102
|
+
if (!result.state) {
|
|
103
|
+
return {
|
|
104
|
+
content: [
|
|
105
|
+
{
|
|
106
|
+
type: "text",
|
|
107
|
+
text: `Evidence map "${task_id}" not found.`
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const lines = [
|
|
113
|
+
`## Evidence Map: ${task_id} (${result.state.tier})`,
|
|
114
|
+
"",
|
|
115
|
+
result.formattedMap ?? "No entries.",
|
|
116
|
+
"",
|
|
117
|
+
`_${result.state.entries.length} entries \u2014 created ${result.state.createdAt}_`
|
|
118
|
+
];
|
|
119
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
120
|
+
}
|
|
121
|
+
case "gate": {
|
|
122
|
+
if (!task_id) throw new Error("task_id required for gate");
|
|
123
|
+
const result = evidenceMap(
|
|
124
|
+
{
|
|
125
|
+
action: "gate",
|
|
126
|
+
taskId: task_id,
|
|
127
|
+
retryCount: retry_count
|
|
128
|
+
},
|
|
129
|
+
cwd
|
|
130
|
+
);
|
|
131
|
+
if (!result.gate) {
|
|
132
|
+
return {
|
|
133
|
+
content: [
|
|
134
|
+
{
|
|
135
|
+
type: "text",
|
|
136
|
+
text: `Evidence map "${task_id}" not found.`
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const g = result.gate;
|
|
142
|
+
const lines = [
|
|
143
|
+
`## FORGE Gate: **${g.decision}**`,
|
|
144
|
+
"",
|
|
145
|
+
`**Reason:** ${g.reason}`,
|
|
146
|
+
"",
|
|
147
|
+
`**Stats:** ${g.stats.verified}V / ${g.stats.assumed}A / ${g.stats.unresolved}U (${g.stats.total} total)`
|
|
148
|
+
];
|
|
149
|
+
if (g.warnings.length > 0) {
|
|
150
|
+
lines.push("", "**Warnings:**", ...g.warnings.map((w) => `- \u26A0\uFE0F ${w}`));
|
|
151
|
+
}
|
|
152
|
+
if (g.unresolvedCritical.length > 0) {
|
|
153
|
+
lines.push(
|
|
154
|
+
"",
|
|
155
|
+
"**Blocking entries:**",
|
|
156
|
+
...g.unresolvedCritical.map(
|
|
157
|
+
(e) => `- #${e.id}: ${e.claim} [${e.unknownType ?? "untyped"}]`
|
|
158
|
+
)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (g.annotation) {
|
|
162
|
+
lines.push("", "**Annotation:**", g.annotation);
|
|
163
|
+
}
|
|
164
|
+
if (result.formattedMap) {
|
|
165
|
+
lines.push("", "---", "", result.formattedMap);
|
|
166
|
+
}
|
|
167
|
+
lines.push(
|
|
168
|
+
"",
|
|
169
|
+
"---",
|
|
170
|
+
`_Next: ${g.decision === "YIELD" ? "Proceed to implementation." : g.decision === "HOLD" ? "Resolve blocking entries, then re-run gate." : g.decision === "HARD_BLOCK" ? "Contract unknowns MUST be resolved. Use search or schema_validate." : "Proceed with annotation \u2014 document unresolved items in delivery."}_`
|
|
171
|
+
);
|
|
172
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
173
|
+
}
|
|
174
|
+
case "list": {
|
|
175
|
+
const result = evidenceMap({ action: "list" }, cwd);
|
|
176
|
+
if (!result.states || result.states.length === 0) {
|
|
177
|
+
return {
|
|
178
|
+
content: [{ type: "text", text: "No evidence maps found." }]
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const lines = result.states.map(
|
|
182
|
+
(s) => `- **${s.taskId}** (${s.tier}) \u2014 ${s.entries.length} entries \u2014 ${s.updatedAt}`
|
|
183
|
+
);
|
|
184
|
+
return {
|
|
185
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
case "delete": {
|
|
189
|
+
if (!task_id) throw new Error("task_id required for delete");
|
|
190
|
+
const result = evidenceMap({ action: "delete", taskId: task_id }, cwd);
|
|
191
|
+
return {
|
|
192
|
+
content: [
|
|
193
|
+
{
|
|
194
|
+
type: "text",
|
|
195
|
+
text: result.deleted ? `Deleted evidence map "${task_id}".` : `Evidence map "${task_id}" not found.`
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
} catch (err) {
|
|
202
|
+
return {
|
|
203
|
+
content: [
|
|
204
|
+
{
|
|
205
|
+
type: "text",
|
|
206
|
+
text: `Evidence map error: ${err.message}`
|
|
207
|
+
}
|
|
208
|
+
],
|
|
209
|
+
isError: true
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
function registerDigestTool(server, embedder) {
|
|
216
|
+
server.registerTool(
|
|
217
|
+
"digest",
|
|
218
|
+
{
|
|
219
|
+
description: "Compress multiple text sources (handoffs, debates, phase summaries) into a token-budgeted digest. Jointly ranks across all sources, pins structured fields (status, files, decisions, blockers), and allocates budget by priority weight.",
|
|
220
|
+
inputSchema: {
|
|
221
|
+
sources: z.array(
|
|
222
|
+
z.object({
|
|
223
|
+
id: z.string().describe('Source identifier (e.g., "phase-2-handoff")'),
|
|
224
|
+
text: z.string().describe("Source text to compress"),
|
|
225
|
+
weight: z.number().min(0).default(1).describe("Priority weight (higher = more budget)")
|
|
226
|
+
})
|
|
227
|
+
).min(1).describe("Text sources to compress"),
|
|
228
|
+
query: z.string().describe("Focus query \u2014 what matters for the next step?"),
|
|
229
|
+
max_chars: z.number().min(100).max(5e4).default(4e3).describe("Target budget in characters"),
|
|
230
|
+
pin_fields: z.array(z.string()).optional().describe(
|
|
231
|
+
"Key fields to always extract (default: status, files, decisions, blockers, next)"
|
|
232
|
+
),
|
|
233
|
+
segmentation: z.enum(["paragraph", "sentence", "line"]).default("paragraph").describe("How to split text for scoring")
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
async ({ sources, query, max_chars, pin_fields, segmentation }) => {
|
|
237
|
+
try {
|
|
238
|
+
const result = await digest(embedder, {
|
|
239
|
+
sources,
|
|
240
|
+
query,
|
|
241
|
+
maxChars: max_chars,
|
|
242
|
+
pinFields: pin_fields,
|
|
243
|
+
segmentation
|
|
244
|
+
});
|
|
245
|
+
const lines = [
|
|
246
|
+
`## Digest (${result.totalOriginalChars} \u2192 ${result.totalCompressedChars} chars, ${(result.ratio * 100).toFixed(0)}%)`,
|
|
247
|
+
""
|
|
248
|
+
];
|
|
249
|
+
const fieldKeys = Object.keys(result.fields);
|
|
250
|
+
if (fieldKeys.length > 0) {
|
|
251
|
+
lines.push("### Extracted Fields");
|
|
252
|
+
for (const key of fieldKeys) {
|
|
253
|
+
const entries = result.fields[key];
|
|
254
|
+
lines.push(`**${key}:**`);
|
|
255
|
+
for (const e of entries) {
|
|
256
|
+
lines.push(` - [${e.sourceId}] ${e.value}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
lines.push("");
|
|
260
|
+
}
|
|
261
|
+
lines.push("### Compressed Content", "", result.text);
|
|
262
|
+
lines.push("", "### Source Stats");
|
|
263
|
+
for (const s of result.sourceStats) {
|
|
264
|
+
lines.push(
|
|
265
|
+
`- **${s.id}**: ${s.originalChars} \u2192 ${s.keptChars} chars (${s.segmentsKept}/${s.segmentsTotal} segments)`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
lines.push(
|
|
269
|
+
"",
|
|
270
|
+
"---",
|
|
271
|
+
"_Next: Use the digest as compressed context for the next phase. Use `stash` to persist it if needed._"
|
|
272
|
+
);
|
|
273
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
274
|
+
} catch (err) {
|
|
275
|
+
return {
|
|
276
|
+
content: [{ type: "text", text: `Digest failed: ${err.message}` }],
|
|
277
|
+
isError: true
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
function registerForgeClassifyTool(server) {
|
|
284
|
+
server.registerTool(
|
|
285
|
+
"forge_classify",
|
|
286
|
+
{
|
|
287
|
+
description: "Classify FORGE tier (Floor/Standard/Critical) from target files and task description. Checks blast radius, cross-package boundaries, schema/contract patterns, and security signals. Returns tier, triggers, typed unknown seeds, and ceremony guidance.",
|
|
288
|
+
inputSchema: {
|
|
289
|
+
files: z.array(z.string()).min(1).describe("Files being modified (paths)"),
|
|
290
|
+
task: z.string().describe("Task description"),
|
|
291
|
+
root_path: z.string().describe("Root path of the codebase")
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
async ({ files, task, root_path }) => {
|
|
295
|
+
try {
|
|
296
|
+
const result = await forgeClassify({ files, task, rootPath: root_path });
|
|
297
|
+
const lines = [`## FORGE Classification: **${result.tier.toUpperCase()}**`, ""];
|
|
298
|
+
if (result.triggers.length > 0) {
|
|
299
|
+
lines.push("### Triggers");
|
|
300
|
+
for (const t of result.triggers) {
|
|
301
|
+
lines.push(`- **${t.rule}** (${t.source}): ${t.detail}`);
|
|
302
|
+
}
|
|
303
|
+
lines.push("");
|
|
304
|
+
}
|
|
305
|
+
if (result.packagesCrossed.length > 0) {
|
|
306
|
+
lines.push(`**Packages crossed:** ${result.packagesCrossed.join(", ")}`);
|
|
307
|
+
}
|
|
308
|
+
if (result.typedUnknownSeeds.length > 0) {
|
|
309
|
+
lines.push("", "### Typed Unknown Seeds");
|
|
310
|
+
for (const u of result.typedUnknownSeeds) {
|
|
311
|
+
lines.push(`- [${u.type}] ${u.description} \u2192 use \`${u.suggestedTool}\``);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
lines.push("", "### Ceremony");
|
|
315
|
+
const c = result.ceremony;
|
|
316
|
+
lines.push(
|
|
317
|
+
`- **Ground:** ${c.ground}`,
|
|
318
|
+
`- **Build:** ${c.build}`,
|
|
319
|
+
`- **Break:** ${c.break}`,
|
|
320
|
+
`- **Evidence Map:** ${c.evidenceMap}`,
|
|
321
|
+
`- **Gate:** ${c.gate}`
|
|
322
|
+
);
|
|
323
|
+
lines.push(
|
|
324
|
+
"",
|
|
325
|
+
"---",
|
|
326
|
+
`_Next: ${result.tier === "floor" ? "Proceed directly to implementation." : "Run `forge_ground` to execute the full Ground phase."}_`
|
|
327
|
+
);
|
|
328
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
329
|
+
} catch (err) {
|
|
330
|
+
return {
|
|
331
|
+
content: [
|
|
332
|
+
{
|
|
333
|
+
type: "text",
|
|
334
|
+
text: `FORGE classify failed: ${err.message}`
|
|
335
|
+
}
|
|
336
|
+
],
|
|
337
|
+
isError: true
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
function registerStratumCardTool(server, embedder) {
|
|
344
|
+
server.registerTool(
|
|
345
|
+
"stratum_card",
|
|
346
|
+
{
|
|
347
|
+
description: "Generate STRATUM context cards from files. T1 = structural metadata (~100 tokens/file). T2 = T1 + compressed content (~300 tokens/file). Replaces reading full files \u2014 10-100x token reduction.",
|
|
348
|
+
inputSchema: {
|
|
349
|
+
files: z.array(z.string()).min(1).describe("Absolute file paths to generate cards for"),
|
|
350
|
+
query: z.string().describe("Current task query \u2014 guides relevance scoring"),
|
|
351
|
+
tier: z.enum(["T1", "T2"]).default("T1").describe("Card tier: T1 = structural only, T2 = T1 + compressed content"),
|
|
352
|
+
max_content_chars: z.number().min(100).max(5e3).default(800).describe("For T2: max chars for compressed content section")
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
async ({ files, query, tier, max_content_chars }) => {
|
|
356
|
+
try {
|
|
357
|
+
const result = await stratumCard(embedder, {
|
|
358
|
+
files,
|
|
359
|
+
query,
|
|
360
|
+
tier,
|
|
361
|
+
maxContentChars: max_content_chars
|
|
362
|
+
});
|
|
363
|
+
const lines = [
|
|
364
|
+
`## STRATUM Cards (${tier}) \u2014 ${result.cards.length} files`,
|
|
365
|
+
`Total: ~${result.totalTokenEstimate} tokens (was ~${result.totalOriginalTokenEstimate}, ${(result.compressionRatio * 100).toFixed(0)}% of original)`,
|
|
366
|
+
""
|
|
367
|
+
];
|
|
368
|
+
for (const card of result.cards) {
|
|
369
|
+
lines.push(card.card, "");
|
|
370
|
+
}
|
|
371
|
+
lines.push(
|
|
372
|
+
"---",
|
|
373
|
+
`_Next: Use these cards as context instead of reading full files. Use \`compact\` for deeper content extraction on specific files._`
|
|
374
|
+
);
|
|
375
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
376
|
+
} catch (err) {
|
|
377
|
+
return {
|
|
378
|
+
content: [
|
|
379
|
+
{
|
|
380
|
+
type: "text",
|
|
381
|
+
text: `STRATUM cards failed: ${err.message}`
|
|
382
|
+
}
|
|
383
|
+
],
|
|
384
|
+
isError: true
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
function registerForgeGroundTool(server, embedder, store) {
|
|
391
|
+
server.registerTool(
|
|
392
|
+
"forge_ground",
|
|
393
|
+
{
|
|
394
|
+
description: "Execute the complete FORGE Ground phase in a single call. Chains: tier classification \u2192 scope map \u2192 typed unknown seeds \u2192 constraint loading \u2192 file summaries \u2192 evidence map creation. Replaces 5-15 manual tool calls.",
|
|
395
|
+
inputSchema: {
|
|
396
|
+
task: z.string().describe("Task description"),
|
|
397
|
+
files: z.array(z.string()).min(1).describe("Target files being modified (absolute paths)"),
|
|
398
|
+
root_path: z.string().describe("Root path of the codebase"),
|
|
399
|
+
max_constraints: z.number().min(0).max(10).default(3).describe("Max constraint entries to load from KB"),
|
|
400
|
+
force_tier: z.enum(["floor", "standard", "critical"]).optional().describe("Force a specific tier (skips auto-classification)"),
|
|
401
|
+
task_id: z.string().optional().describe("Custom task ID for evidence map (auto-generated if omitted)")
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
async ({ task, files, root_path, max_constraints, force_tier, task_id }) => {
|
|
405
|
+
try {
|
|
406
|
+
const result = await forgeGround(embedder, store, {
|
|
407
|
+
task,
|
|
408
|
+
files,
|
|
409
|
+
rootPath: root_path,
|
|
410
|
+
maxConstraints: max_constraints,
|
|
411
|
+
forceTier: force_tier,
|
|
412
|
+
taskId: task_id
|
|
413
|
+
});
|
|
414
|
+
const lines = [
|
|
415
|
+
`## FORGE Ground: **${result.tier.toUpperCase()}**`,
|
|
416
|
+
`Estimated output: ~${result.estimatedTokens} tokens`,
|
|
417
|
+
""
|
|
418
|
+
];
|
|
419
|
+
if (result.classifyTriggers.length > 0) {
|
|
420
|
+
lines.push("### Classification Triggers");
|
|
421
|
+
for (const t of result.classifyTriggers) {
|
|
422
|
+
lines.push(`- **${t.rule}** (${t.source}): ${t.detail}`);
|
|
423
|
+
}
|
|
424
|
+
lines.push("");
|
|
425
|
+
}
|
|
426
|
+
if (result.fileSummaries.length > 0) {
|
|
427
|
+
lines.push("### Target Files");
|
|
428
|
+
for (const f of result.fileSummaries) {
|
|
429
|
+
lines.push(
|
|
430
|
+
`- **${f.path}** (${f.lines} lines) \u2014 exports: ${f.exports.join(", ") || "none"} \u2014 functions: ${f.functions.join(", ") || "none"}`
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
lines.push("");
|
|
434
|
+
}
|
|
435
|
+
if (result.typedUnknownSeeds.length > 0) {
|
|
436
|
+
lines.push("### Typed Unknown Seeds");
|
|
437
|
+
for (const u of result.typedUnknownSeeds) {
|
|
438
|
+
lines.push(`- [${u.type}] ${u.description} \u2192 \`${u.suggestedTool}\``);
|
|
439
|
+
}
|
|
440
|
+
lines.push("");
|
|
441
|
+
}
|
|
442
|
+
if (result.constraints.length > 0) {
|
|
443
|
+
lines.push("### Constraint Seed");
|
|
444
|
+
for (const c2 of result.constraints) {
|
|
445
|
+
lines.push(`- **${c2.source}** (${(c2.relevance * 100).toFixed(0)}%): ${c2.snippet}`);
|
|
446
|
+
}
|
|
447
|
+
lines.push("");
|
|
448
|
+
}
|
|
449
|
+
if (result.scopeMap) {
|
|
450
|
+
lines.push(
|
|
451
|
+
`### Scope Map: ${result.scopeMap.files.length} files (~${result.scopeMap.totalEstimatedTokens} tokens)`
|
|
452
|
+
);
|
|
453
|
+
for (const f of result.scopeMap.files.slice(0, 5)) {
|
|
454
|
+
lines.push(`- ${f.path} (${(f.relevance * 100).toFixed(0)}%) \u2014 ${f.reason}`);
|
|
455
|
+
}
|
|
456
|
+
if (result.scopeMap.files.length > 5) {
|
|
457
|
+
lines.push(`- _...and ${result.scopeMap.files.length - 5} more_`);
|
|
458
|
+
}
|
|
459
|
+
lines.push("");
|
|
460
|
+
}
|
|
461
|
+
if (result.evidenceMapTaskId) {
|
|
462
|
+
lines.push(`**Evidence Map:** \`${result.evidenceMapTaskId}\` (initialized)`);
|
|
463
|
+
lines.push("");
|
|
464
|
+
}
|
|
465
|
+
lines.push("### Ceremony Guidance");
|
|
466
|
+
const c = result.ceremony;
|
|
467
|
+
lines.push(
|
|
468
|
+
`- **Ground:** ${c.ground}`,
|
|
469
|
+
`- **Build:** ${c.build}`,
|
|
470
|
+
`- **Break:** ${c.break}`,
|
|
471
|
+
`- **Evidence Map:** ${c.evidenceMap}`,
|
|
472
|
+
`- **Gate:** ${c.gate}`
|
|
473
|
+
);
|
|
474
|
+
lines.push(
|
|
475
|
+
"",
|
|
476
|
+
"---",
|
|
477
|
+
`_Next: ${result.tier === "floor" ? "Proceed to Build phase." : "Use `evidence_map` to track claims during Build, then `evidence_map` gate after Break."}_`
|
|
478
|
+
);
|
|
479
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
480
|
+
} catch (err) {
|
|
481
|
+
return {
|
|
482
|
+
content: [
|
|
483
|
+
{
|
|
484
|
+
type: "text",
|
|
485
|
+
text: `FORGE Ground failed: ${err.message}`
|
|
486
|
+
}
|
|
487
|
+
],
|
|
488
|
+
isError: true
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
export {
|
|
495
|
+
registerDigestTool,
|
|
496
|
+
registerEvidenceMapTool,
|
|
497
|
+
registerForgeClassifyTool,
|
|
498
|
+
registerForgeGroundTool,
|
|
499
|
+
registerStratumCardTool
|
|
500
|
+
};
|
|
501
|
+
//# sourceMappingURL=forge.tools.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { CuratedKnowledgeManager } from '../curated-manager.js';
|
|
3
|
+
export declare function registerForgetTool(server: McpServer, curated: CuratedKnowledgeManager): void;
|
|
4
|
+
//# sourceMappingURL=forget.tool.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
function registerForgetTool(server, curated) {
|
|
3
|
+
server.registerTool(
|
|
4
|
+
"forget",
|
|
5
|
+
{
|
|
6
|
+
description: "Remove a curated knowledge entry. Deletes the file and removes it from the vector store.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
path: z.string().describe('Relative path within curated/ (e.g., "decisions/deprecated-approach.md")'),
|
|
9
|
+
reason: z.string().min(3).describe("Why this entry is being removed")
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
async ({ path, reason }) => {
|
|
13
|
+
try {
|
|
14
|
+
const result = await curated.forget(path, reason);
|
|
15
|
+
console.error(`[KB] Forgot: ${result.path} \u2014 reason: ${reason}`);
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: `Forgotten: \`curated/${result.path}\`
|
|
21
|
+
|
|
22
|
+
Removed from disk and vector store.
|
|
23
|
+
Reason: ${reason}
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
_Next: Use \`list\` to verify removal, or \`search\` to confirm the entry is no longer returned._`
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
};
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error("[KB] Forget failed:", err);
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: `Forget failed: ${err.message}` }],
|
|
34
|
+
isError: true
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
registerForgetTool
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=forget.tool.js.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { graphQuery } from "@kb/tools";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const nodeSchema = z.object({
|
|
4
|
+
id: z.string().optional().describe("Node ID (auto-generated if omitted)"),
|
|
5
|
+
type: z.string().describe("Node type (entity, service, api, concept, decision)"),
|
|
6
|
+
name: z.string().describe("Display name"),
|
|
7
|
+
properties: z.record(z.string(), z.unknown()).optional().describe("Arbitrary properties"),
|
|
8
|
+
sourceRecordId: z.string().optional().describe("Back-link to knowledge record ID"),
|
|
9
|
+
sourcePath: z.string().optional().describe("Source file path")
|
|
10
|
+
});
|
|
11
|
+
const edgeSchema = z.object({
|
|
12
|
+
id: z.string().optional().describe("Edge ID (auto-generated if omitted)"),
|
|
13
|
+
fromId: z.string().describe("Source node ID"),
|
|
14
|
+
toId: z.string().describe("Target node ID"),
|
|
15
|
+
type: z.string().describe("Relationship type (depends-on, implements, calls, affects)"),
|
|
16
|
+
weight: z.number().min(0).max(1).optional().describe("Relationship weight"),
|
|
17
|
+
properties: z.record(z.string(), z.unknown()).optional().describe("Arbitrary properties")
|
|
18
|
+
});
|
|
19
|
+
function registerGraphTool(server, graphStore) {
|
|
20
|
+
server.registerTool(
|
|
21
|
+
"graph",
|
|
22
|
+
{
|
|
23
|
+
description: "Query and manage the knowledge graph. Find nodes/edges, traverse connections, add entities and relationships. The graph captures structural relationships between concepts discovered in the codebase.",
|
|
24
|
+
inputSchema: {
|
|
25
|
+
action: z.enum([
|
|
26
|
+
"find_nodes",
|
|
27
|
+
"find_edges",
|
|
28
|
+
"neighbors",
|
|
29
|
+
"traverse",
|
|
30
|
+
"stats",
|
|
31
|
+
"add",
|
|
32
|
+
"delete",
|
|
33
|
+
"clear"
|
|
34
|
+
]).describe(
|
|
35
|
+
"Action: find_nodes (search nodes), find_edges (search edges), neighbors (direct connections), traverse (multi-hop), stats (graph overview), add (insert nodes/edges), delete (remove nodes), clear (remove all)"
|
|
36
|
+
),
|
|
37
|
+
node_type: z.string().optional().describe("Node type filter (for find_nodes)"),
|
|
38
|
+
name_pattern: z.string().optional().describe("Name substring match (for find_nodes)"),
|
|
39
|
+
source_path: z.string().optional().describe("Source path filter"),
|
|
40
|
+
node_id: z.string().optional().describe("Node ID (for neighbors, traverse, delete)"),
|
|
41
|
+
edge_type: z.string().optional().describe("Edge type filter"),
|
|
42
|
+
from_id: z.string().optional().describe("Source node ID (for find_edges)"),
|
|
43
|
+
to_id: z.string().optional().describe("Target node ID (for find_edges)"),
|
|
44
|
+
direction: z.enum(["outgoing", "incoming", "both"]).default("both").describe("Traversal direction"),
|
|
45
|
+
max_depth: z.number().min(1).max(5).default(2).describe("Max traversal depth"),
|
|
46
|
+
limit: z.number().min(1).max(100).default(50).describe("Max results"),
|
|
47
|
+
nodes: z.array(nodeSchema).optional().describe("Nodes to add (for action=add)"),
|
|
48
|
+
edges: z.array(edgeSchema).optional().describe("Edges to add (for action=add)")
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
async (args) => {
|
|
52
|
+
try {
|
|
53
|
+
const result = await graphQuery(graphStore, {
|
|
54
|
+
action: args.action,
|
|
55
|
+
nodeType: args.node_type,
|
|
56
|
+
namePattern: args.name_pattern,
|
|
57
|
+
sourcePath: args.source_path,
|
|
58
|
+
nodeId: args.node_id,
|
|
59
|
+
edgeType: args.edge_type,
|
|
60
|
+
fromId: args.from_id,
|
|
61
|
+
toId: args.to_id,
|
|
62
|
+
direction: args.direction,
|
|
63
|
+
maxDepth: args.max_depth,
|
|
64
|
+
limit: args.limit,
|
|
65
|
+
nodes: args.nodes,
|
|
66
|
+
edges: args.edges
|
|
67
|
+
});
|
|
68
|
+
const parts = [result.summary];
|
|
69
|
+
if (result.nodes && result.nodes.length > 0) {
|
|
70
|
+
parts.push("\n### Nodes");
|
|
71
|
+
for (const n of result.nodes) {
|
|
72
|
+
const props = Object.keys(n.properties).length > 0 ? ` \u2014 ${JSON.stringify(n.properties)}` : "";
|
|
73
|
+
parts.push(`- **${n.name}** (${n.type}, id: \`${n.id}\`)${props}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (result.edges && result.edges.length > 0) {
|
|
77
|
+
parts.push("\n### Edges");
|
|
78
|
+
for (const e of result.edges) {
|
|
79
|
+
parts.push(
|
|
80
|
+
`- \`${e.fromId}\` \u2014[${e.type}]\u2192 \`${e.toId}\`${e.weight !== 1 ? ` (weight: ${e.weight})` : ""}`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (result.stats) {
|
|
85
|
+
parts.push(`
|
|
86
|
+
Node types: ${JSON.stringify(result.stats.nodeTypes)}`);
|
|
87
|
+
parts.push(`Edge types: ${JSON.stringify(result.stats.edgeTypes)}`);
|
|
88
|
+
}
|
|
89
|
+
parts.push(
|
|
90
|
+
"\n---\n_Next: Use `graph(traverse)` to explore connections, `graph(add)` to insert entities, or `search` with graph-augmented results._"
|
|
91
|
+
);
|
|
92
|
+
return {
|
|
93
|
+
content: [{ type: "text", text: parts.join("\n") }]
|
|
94
|
+
};
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error("[KB] Graph query failed:", err);
|
|
97
|
+
return {
|
|
98
|
+
content: [
|
|
99
|
+
{ type: "text", text: `Graph query failed: ${err.message}` }
|
|
100
|
+
],
|
|
101
|
+
isError: true
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
registerGraphTool
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=graph.tool.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { CuratedKnowledgeManager } from '../curated-manager.js';
|
|
3
|
+
export declare function registerListTool(server: McpServer, curated: CuratedKnowledgeManager): void;
|
|
4
|
+
//# sourceMappingURL=list.tool.d.ts.map
|