dsh-code-review-graph 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/NOTICE +12 -0
- package/README.en.md +117 -0
- package/README.md +110 -2
- package/capabilities.json +1790 -0
- package/cordis.patch.yml +3 -0
- package/dist/backend.js +215 -0
- package/dist/backend.js.map +7 -0
- package/dist/client.js +70 -0
- package/dist/client.js.map +7 -0
- package/dist/html.js +17 -0
- package/dist/html.js.map +7 -0
- package/dist/index.js +511 -0
- package/dist/index.js.map +7 -0
- package/dist/refactor.js +68 -0
- package/dist/refactor.js.map +7 -0
- package/dist/safety.js +52 -0
- package/dist/safety.js.map +7 -0
- package/dist/setup.js +78 -0
- package/dist/setup.js.map +7 -0
- package/dist/workflows.js +30 -0
- package/dist/workflows.js.map +7 -0
- package/docs/capabilities.md +103 -0
- package/docs/validation.md +113 -0
- package/engine.json +8 -0
- package/package.json +37 -4
- package/skills/build-graph/SKILL.md +26 -0
- package/skills/debug-issue/SKILL.md +23 -0
- package/skills/explore-codebase/SKILL.md +24 -0
- package/skills/refactor-safely/SKILL.md +24 -0
- package/skills/review-changes/SKILL.md +27 -0
- package/skills/review-delta/SKILL.md +25 -0
- package/skills/review-pr/SKILL.md +48 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
|
+
import { Ajv } from "ajv";
|
|
4
|
+
import { readFile, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
5
|
+
import { join as join2, basename as basename2 } from "node:path";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
|
|
8
|
+
// src/backend.ts
|
|
9
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
10
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
|
|
13
|
+
// src/safety.ts
|
|
14
|
+
import { realpath, stat, lstat, readdir } from "node:fs/promises";
|
|
15
|
+
import { isAbsolute, relative, resolve, sep, dirname, basename, join } from "node:path";
|
|
16
|
+
import { createHash } from "node:crypto";
|
|
17
|
+
var sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
18
|
+
function contained(root, path) {
|
|
19
|
+
const part = relative(root, path);
|
|
20
|
+
return part === "" || !isAbsolute(part) && part !== ".." && !part.startsWith(`..${sep}`);
|
|
21
|
+
}
|
|
22
|
+
async function checkedPath(root, value, allowMissing = false) {
|
|
23
|
+
const candidate = resolve(root, value);
|
|
24
|
+
if (!contained(root, candidate)) throw new Error("Path is outside the authorized repository");
|
|
25
|
+
let current = candidate;
|
|
26
|
+
const suffix = [];
|
|
27
|
+
while (allowMissing && !await lstat(current).then(() => true, () => false)) {
|
|
28
|
+
suffix.unshift(basename(current));
|
|
29
|
+
current = dirname(current);
|
|
30
|
+
}
|
|
31
|
+
const canonical = join(await realpath(current), ...suffix);
|
|
32
|
+
if (!contained(root, canonical)) throw new Error("Symlink escapes the authorized repository");
|
|
33
|
+
return canonical;
|
|
34
|
+
}
|
|
35
|
+
async function repository(cwd) {
|
|
36
|
+
if (!cwd || !isAbsolute(cwd)) throw new Error("This session has no local absolute workspace");
|
|
37
|
+
const root = await realpath(cwd);
|
|
38
|
+
if (!(await stat(root)).isDirectory()) throw new Error("Workspace is not a directory");
|
|
39
|
+
for (const marker of [".git", ".svn"]) {
|
|
40
|
+
if (await stat(resolve(root, marker)).then(() => true, () => false)) return root;
|
|
41
|
+
}
|
|
42
|
+
throw new Error("Select a Git or SVN repository before using the graph");
|
|
43
|
+
}
|
|
44
|
+
function scrubEnv(env) {
|
|
45
|
+
return { ...Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== void 0 && !/KEY|PASSWORD|SECRET|TOKEN|^(DSH|CRG|OPENAI|GOOGLE|GEMINI|MINIMAX|VOYAGE|HF)_/i.test(key))), HF_HUB_OFFLINE: "1", TRANSFORMERS_OFFLINE: "1", HF_HUB_DISABLE_TELEMETRY: "1" };
|
|
46
|
+
}
|
|
47
|
+
async function checkedData(root) {
|
|
48
|
+
const dir = resolve(root, ".code-review-graph");
|
|
49
|
+
if (!await lstat(dir).then(() => true, () => false)) return;
|
|
50
|
+
await checkedPath(root, dir);
|
|
51
|
+
const entries = await readdir(dir, { withFileTypes: true, recursive: true });
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (entry.isSymbolicLink()) await checkedPath(root, join(entry.parentPath, entry.name));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/backend.ts
|
|
58
|
+
var environment = (engine) => ({ ...scrubEnv(process.env), ...engine.env });
|
|
59
|
+
function valueOf(result) {
|
|
60
|
+
const r = result;
|
|
61
|
+
const text = r.content?.filter((x) => x.type === "text").map((x) => x.text).join("\n") ?? "";
|
|
62
|
+
if (r.isError) throw new Error(text || "Engine tool failed");
|
|
63
|
+
const value = r.structuredContent ?? (() => {
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(text);
|
|
66
|
+
} catch {
|
|
67
|
+
return { text };
|
|
68
|
+
}
|
|
69
|
+
})();
|
|
70
|
+
if (value.status === "error") throw new Error(String(value.error));
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
async function connect(engine, cwd) {
|
|
74
|
+
await checkedData(cwd);
|
|
75
|
+
const transport = new StdioClientTransport({ command: engine.command, args: [...engine.args, "serve", "--repo", cwd], cwd, env: environment(engine), stderr: "pipe" });
|
|
76
|
+
transport.stderr?.on("data", () => {
|
|
77
|
+
});
|
|
78
|
+
const client = new Client({ name: "dsh-code-review-graph", version: "0.1.0" });
|
|
79
|
+
try {
|
|
80
|
+
await client.connect(transport);
|
|
81
|
+
return client;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
await transport.close();
|
|
84
|
+
throw new Error(`CRG engine unavailable. Run dsh-crg prepare explicitly. ${String(error)}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function stop(child) {
|
|
88
|
+
if (!child || child.exitCode !== null || child.signalCode !== null) return;
|
|
89
|
+
await new Promise((resolve2) => {
|
|
90
|
+
const timer = setTimeout(() => {
|
|
91
|
+
child.kill("SIGKILL");
|
|
92
|
+
resolve2();
|
|
93
|
+
}, 3e3);
|
|
94
|
+
child.once("exit", () => {
|
|
95
|
+
clearTimeout(timer);
|
|
96
|
+
resolve2();
|
|
97
|
+
});
|
|
98
|
+
child.kill();
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
var BackendPool = class {
|
|
102
|
+
constructor(engine) {
|
|
103
|
+
this.engine = engine;
|
|
104
|
+
}
|
|
105
|
+
entries = /* @__PURE__ */ new Map();
|
|
106
|
+
retired = /* @__PURE__ */ new Set();
|
|
107
|
+
closed = false;
|
|
108
|
+
activate(owner) {
|
|
109
|
+
this.retired.delete(owner);
|
|
110
|
+
}
|
|
111
|
+
async acquire(root, owner) {
|
|
112
|
+
if (this.closed || this.retired.has(owner)) throw new Error("Session has been released");
|
|
113
|
+
let promise = this.entries.get(root);
|
|
114
|
+
if (!promise) {
|
|
115
|
+
promise = connect(this.engine, root).then((client) => ({ client, owners: /* @__PURE__ */ new Set(), queue: Promise.resolve() }));
|
|
116
|
+
this.entries.set(root, promise);
|
|
117
|
+
promise.catch(() => {
|
|
118
|
+
if (this.entries.get(root) === promise) this.entries.delete(root);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const entry = await promise;
|
|
122
|
+
if (this.closed || this.retired.has(owner)) throw new Error("Session has been released");
|
|
123
|
+
entry.owners.add(owner);
|
|
124
|
+
return entry;
|
|
125
|
+
}
|
|
126
|
+
async call(root, owner, name2, args, signal) {
|
|
127
|
+
const entry = await this.acquire(root, owner);
|
|
128
|
+
const work = entry.queue.catch(() => {
|
|
129
|
+
}).then(async () => {
|
|
130
|
+
signal.throwIfAborted();
|
|
131
|
+
const cancel = () => {
|
|
132
|
+
this.entries.delete(root);
|
|
133
|
+
void stop(entry.watcher);
|
|
134
|
+
void entry.client.close();
|
|
135
|
+
};
|
|
136
|
+
signal.addEventListener("abort", cancel, { once: true });
|
|
137
|
+
let result;
|
|
138
|
+
try {
|
|
139
|
+
await checkedData(root);
|
|
140
|
+
if (entry.watchError) throw new Error(`Incremental watcher stopped: ${entry.watchError}`);
|
|
141
|
+
result = await entry.client.callTool({ name: name2, arguments: args }, void 0, { signal, timeout: this.engine.timeoutMs });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
this.entries.delete(root);
|
|
144
|
+
await stop(entry.watcher);
|
|
145
|
+
await entry.client.close();
|
|
146
|
+
throw error;
|
|
147
|
+
} finally {
|
|
148
|
+
signal.removeEventListener("abort", cancel);
|
|
149
|
+
}
|
|
150
|
+
valueOf(result);
|
|
151
|
+
return result;
|
|
152
|
+
});
|
|
153
|
+
entry.queue = work;
|
|
154
|
+
return work;
|
|
155
|
+
}
|
|
156
|
+
async ensure(root, owner, signal) {
|
|
157
|
+
const entry = await this.acquire(root, owner);
|
|
158
|
+
entry.ready ??= (async () => {
|
|
159
|
+
const update = valueOf(await this.call(root, owner, "build_or_update_graph_tool", { repo_root: root }, signal));
|
|
160
|
+
if (update.status === "partial" || Array.isArray(update.warnings) && update.warnings.length) entry.update = update;
|
|
161
|
+
signal.throwIfAborted();
|
|
162
|
+
const watcher = spawn(this.engine.command, [...this.engine.args, "watch", "--repo", root], { cwd: root, env: environment(this.engine), stdio: "ignore", windowsHide: true });
|
|
163
|
+
entry.watcher = watcher;
|
|
164
|
+
await new Promise((resolve2, reject) => {
|
|
165
|
+
watcher.once("spawn", resolve2);
|
|
166
|
+
watcher.once("error", reject);
|
|
167
|
+
});
|
|
168
|
+
watcher.on("error", (error) => {
|
|
169
|
+
entry.watchError = String(error);
|
|
170
|
+
});
|
|
171
|
+
watcher.on("exit", (code, reason) => {
|
|
172
|
+
if (entry.watcher === watcher) entry.watchError = `exit ${code ?? reason}`;
|
|
173
|
+
});
|
|
174
|
+
})().catch((error) => {
|
|
175
|
+
entry.ready = void 0;
|
|
176
|
+
throw error;
|
|
177
|
+
});
|
|
178
|
+
await entry.ready;
|
|
179
|
+
if (entry.watchError) throw new Error(`Incremental watcher stopped: ${entry.watchError}`);
|
|
180
|
+
return entry.update;
|
|
181
|
+
}
|
|
182
|
+
async release(owner) {
|
|
183
|
+
this.retired.add(owner);
|
|
184
|
+
for (const [root, promise] of this.entries) {
|
|
185
|
+
const entry = await promise.catch(() => void 0);
|
|
186
|
+
if (!entry) continue;
|
|
187
|
+
entry.owners.delete(owner);
|
|
188
|
+
if (!entry.owners.size) {
|
|
189
|
+
this.entries.delete(root);
|
|
190
|
+
const watcher = entry.watcher;
|
|
191
|
+
entry.watcher = void 0;
|
|
192
|
+
await stop(watcher);
|
|
193
|
+
await entry.client.close();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async dispose() {
|
|
198
|
+
this.closed = true;
|
|
199
|
+
const entries = [...this.entries.values()];
|
|
200
|
+
this.entries.clear();
|
|
201
|
+
for (const promise of entries) {
|
|
202
|
+
const entry = await promise.catch(() => void 0);
|
|
203
|
+
if (entry) {
|
|
204
|
+
const watcher = entry.watcher;
|
|
205
|
+
entry.watcher = void 0;
|
|
206
|
+
await stop(watcher);
|
|
207
|
+
await entry.client.close();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
async function run(engine, args, cwd, signal) {
|
|
213
|
+
await checkedData(cwd);
|
|
214
|
+
signal = AbortSignal.any([signal, AbortSignal.timeout(engine.timeoutMs)]);
|
|
215
|
+
return new Promise((resolve2, reject) => {
|
|
216
|
+
let log = "";
|
|
217
|
+
const child = spawn(engine.command, [...engine.args, ...args], { cwd, env: environment(engine), stdio: ["ignore", "pipe", "pipe"], windowsHide: true, signal });
|
|
218
|
+
const capture = (bytes) => {
|
|
219
|
+
log = (log + bytes.toString()).slice(-16e3);
|
|
220
|
+
};
|
|
221
|
+
child.stdout?.on("data", capture);
|
|
222
|
+
child.stderr?.on("data", capture);
|
|
223
|
+
child.on("error", reject);
|
|
224
|
+
child.on("exit", (code) => code === 0 ? resolve2({ log }) : reject(new Error(`Engine command exited ${code}: ${log}`)));
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/refactor.ts
|
|
229
|
+
async function commitPlan(ctx, exec, root, plan) {
|
|
230
|
+
if (!exec.agent) throw new Error("Refactor requires a session-owned agent");
|
|
231
|
+
const policy = ctx.sandboxPolicy.resolve({ session: exec.agent.session });
|
|
232
|
+
if (policy.mode === "read-only") throw new Error("Refactor is denied by read-only policy");
|
|
233
|
+
if (!Array.isArray(plan.files)) throw new Error("Invalid edit plan");
|
|
234
|
+
const prepared = [];
|
|
235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
236
|
+
for (const file of plan.files) {
|
|
237
|
+
if (typeof file.path !== "string" || !/^[a-f0-9]{64}$/.test(file.before_sha256) || typeof file.after_content !== "string" || !Number.isInteger(file.edit_count) || file.edit_count < 0) throw new Error("Invalid edit plan file");
|
|
238
|
+
exec.signal.throwIfAborted();
|
|
239
|
+
const path = await checkedPath(root, file.path);
|
|
240
|
+
if (seen.has(path)) throw new Error("Duplicate edit target");
|
|
241
|
+
seen.add(path);
|
|
242
|
+
const target = await ctx.fs.resolve(path, { cwd: root, signal: exec.signal });
|
|
243
|
+
const before = await ctx.fs.stat(target, exec.signal);
|
|
244
|
+
if (!before || before.type !== "file") throw new Error("Edit target is not a regular file");
|
|
245
|
+
const bytes = await ctx.fs.readBytes(target, exec.signal, 32 * 1024 * 1024);
|
|
246
|
+
if (sha256(bytes) !== file.before_sha256) throw new Error(`Stale edit plan: ${path}`);
|
|
247
|
+
const after = await ctx.fs.stat(target, exec.signal);
|
|
248
|
+
if (after?.version !== before.version) throw new Error(`File changed during preflight: ${path}`);
|
|
249
|
+
const intent = await ctx.waterfall("fs/write-intent", target, exec, () => void 0);
|
|
250
|
+
if (intent && (intent.kind !== "replaceIfVersion" || intent.version !== before.version)) throw new Error(`File intent disagrees with edit plan: ${path}`);
|
|
251
|
+
prepared.push({ file, path, target, original: Buffer.from(bytes).toString("utf8"), intent: intent ?? { kind: "replaceIfVersion", version: before.version } });
|
|
252
|
+
}
|
|
253
|
+
const applied = [];
|
|
254
|
+
const recovery = [];
|
|
255
|
+
try {
|
|
256
|
+
for (const item of prepared) {
|
|
257
|
+
exec.signal.throwIfAborted();
|
|
258
|
+
await checkedPath(root, item.path);
|
|
259
|
+
const outcome = await ctx.fs.writeText(item.target, item.file.after_content, item.intent, exec.signal, policy);
|
|
260
|
+
ctx.emit("fs/observed", item.target, { kind: "present", version: outcome.version }, exec);
|
|
261
|
+
applied.push(item.path);
|
|
262
|
+
recovery.push({ path: item.path, before_sha256: sha256(item.file.after_content), after_content: item.original, edit_count: item.file.edit_count });
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
return { status: "partial_failure", error: String(error), files_modified: applied, recovery_patch: { files: recovery } };
|
|
266
|
+
}
|
|
267
|
+
return { status: "ok", files_modified: applied, edits_applied: plan.files.reduce((n, f) => n + f.edit_count, 0) };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/workflows.ts
|
|
271
|
+
var groups = ["context", "review", "refactor", "export", "advanced", "all"];
|
|
272
|
+
var context = ["build_or_update_graph_tool", "get_minimal_context_tool", "query_graph_tool", "semantic_search_nodes_tool", "list_graph_stats_tool", "get_docs_section_tool"];
|
|
273
|
+
var members = {
|
|
274
|
+
context,
|
|
275
|
+
review: [...context, "detect_changes_tool", "get_review_context_tool", "get_impact_radius_tool", "get_affected_flows_tool", "list_flows_tool", "get_flow_tool", "list_communities_tool"],
|
|
276
|
+
refactor: [...context, "refactor_tool", "apply_refactor_tool", "find_large_functions_tool", "get_impact_radius_tool", "get_affected_flows_tool", "detect_changes_tool"],
|
|
277
|
+
export: [...context, "generate_wiki_tool", "get_wiki_page_tool"],
|
|
278
|
+
advanced: [...context, "embed_graph_tool", "run_postprocess_tool", "list_repos_tool", "cross_repo_search_tool", "list_communities_tool", "get_community_tool", "get_architecture_overview_tool", "get_hub_nodes_tool", "get_bridge_nodes_tool", "get_knowledge_gaps_tool", "get_surprising_connections_tool", "get_suggested_questions_tool", "traverse_graph_tool", "detect_changes_tool", "list_flows_tool", "get_flow_tool", "find_large_functions_tool"]
|
|
279
|
+
};
|
|
280
|
+
var skillWorkflow = {
|
|
281
|
+
"build-graph": "advanced",
|
|
282
|
+
"debug-issue": "review",
|
|
283
|
+
"explore-codebase": "advanced",
|
|
284
|
+
"refactor-safely": "refactor",
|
|
285
|
+
"review-changes": "review",
|
|
286
|
+
"review-delta": "review",
|
|
287
|
+
"review-pr": "review"
|
|
288
|
+
};
|
|
289
|
+
var publicName = (raw) => `mcp__code_review_graph__${raw}`;
|
|
290
|
+
function exposed(workflow, names) {
|
|
291
|
+
return workflow === "all" ? names : names.filter((name2) => members[workflow].includes(name2));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// src/index.ts
|
|
295
|
+
var name = "code-review-graph";
|
|
296
|
+
var inject = ["tools", "agents", "fs", "sandboxPolicy", "skills", "systemPrompt"];
|
|
297
|
+
var engineDir = join2(process.env.DSH_HOME ?? join2(homedir(), ".dsh"), "code-review-graph", "engine");
|
|
298
|
+
var Config = z.object({
|
|
299
|
+
engineCommand: z.string().default(join2(engineDir, process.platform === "win32" ? "Scripts/code-review-graph.exe" : "bin/code-review-graph")),
|
|
300
|
+
engineArgs: z.array(z.string()).default([]),
|
|
301
|
+
timeoutMs: z.number().min(1e3).default(12e4),
|
|
302
|
+
authorizedRepos: z.array(z.string()).default([]),
|
|
303
|
+
embeddingProviders: z.array(z.string()).default(["local"]),
|
|
304
|
+
embeddingEnv: z.array(z.string()).default([])
|
|
305
|
+
});
|
|
306
|
+
var output = {
|
|
307
|
+
schema: { type: "object", additionalProperties: true },
|
|
308
|
+
render: (_args, value) => [{ type: "text", text: JSON.stringify(value) }]
|
|
309
|
+
};
|
|
310
|
+
async function apply(ctx, config) {
|
|
311
|
+
const engine = { command: config.engineCommand, args: config.engineArgs, timeoutMs: config.timeoutMs, env: Object.fromEntries(config.embeddingEnv.filter((key) => /^(OPENAI|GOOGLE|GEMINI|MINIMAX|VOYAGE|CRG)_/.test(key) && process.env[key] !== void 0).map((key) => [key, process.env[key]])) };
|
|
312
|
+
const pool = new BackendPool(engine);
|
|
313
|
+
const snapshot = JSON.parse(await readFile(new URL("../capabilities.json", import.meta.url), "utf8"));
|
|
314
|
+
const tools = snapshot.tools.filter((t) => t.name !== "get_refactor_edit_plan_tool");
|
|
315
|
+
const names = tools.map((t) => t.name);
|
|
316
|
+
const masks = /* @__PURE__ */ new Map();
|
|
317
|
+
const ajv = new Ajv({ strict: false, allErrors: true });
|
|
318
|
+
const life = new AbortController();
|
|
319
|
+
ctx.effect(() => () => {
|
|
320
|
+
life.abort();
|
|
321
|
+
for (const dispose of masks.values()) dispose();
|
|
322
|
+
return pool.dispose();
|
|
323
|
+
});
|
|
324
|
+
const switchWorkflow = (agent, workflow) => {
|
|
325
|
+
pool.activate(agent.id);
|
|
326
|
+
const available = workflow ? exposed(workflow, names) : [];
|
|
327
|
+
masks.get(agent.id)?.();
|
|
328
|
+
masks.set(agent.id, agent.ctx.tools.restrict({ deny: names.filter((n) => !available.includes(n)).map(publicName) }));
|
|
329
|
+
return available.map(publicName);
|
|
330
|
+
};
|
|
331
|
+
async function rootFor(exec) {
|
|
332
|
+
if (!exec.agent) throw new Error("Graph tools require a session-owned agent");
|
|
333
|
+
return repository(exec.agent.session.header.cwd);
|
|
334
|
+
}
|
|
335
|
+
async function invoke(raw, args, exec) {
|
|
336
|
+
const root = await rootFor(exec);
|
|
337
|
+
const owner = exec.agent.id;
|
|
338
|
+
const signal = AbortSignal.any([exec.signal, life.signal]);
|
|
339
|
+
const providerKey = ["build_or_update_graph_tool", "run_postprocess_tool"].includes(raw) ? "embedding_provider" : "provider";
|
|
340
|
+
const provider = args[providerKey];
|
|
341
|
+
if (raw === "get_docs_section_tool") await checkedPath(root, "docs/LLM-OPTIMIZED-REFERENCE.md", true);
|
|
342
|
+
if (provider && (typeof provider !== "string" || !config.embeddingProviders.includes(provider))) throw new Error("Embedding provider has not been authorized in plugin configuration");
|
|
343
|
+
if (["semantic_search_nodes_tool", "embed_graph_tool"].includes(raw) && !provider) args = { ...args, provider: "local" };
|
|
344
|
+
for (const key of ["file_path", "file", "path"]) {
|
|
345
|
+
if (typeof args[key] === "string") await checkedPath(root, args[key]);
|
|
346
|
+
}
|
|
347
|
+
for (const key of ["changed_files", "files"]) {
|
|
348
|
+
if (Array.isArray(args[key])) for (const path of args[key]) await checkedPath(root, path, true);
|
|
349
|
+
}
|
|
350
|
+
if (raw === "list_repos_tool") {
|
|
351
|
+
const roots = [.../* @__PURE__ */ new Set([root, ...await Promise.all(config.authorizedRepos.map(repository))])];
|
|
352
|
+
return { status: "ok", repos: roots.map((path) => ({ alias: roots.filter((r) => basename2(r) === basename2(path)).length > 1 ? `${basename2(path)}@${sha256(path).slice(0, 8)}` : basename2(path), path })) };
|
|
353
|
+
}
|
|
354
|
+
if (raw === "cross_repo_search_tool") {
|
|
355
|
+
const roots = [.../* @__PURE__ */ new Set([root, ...await Promise.all(config.authorizedRepos.map(repository))])];
|
|
356
|
+
const aliases = roots.map((path) => ({ path, alias: roots.filter((r) => basename2(r) === basename2(path)).length > 1 ? `${basename2(path)}@${sha256(path).slice(0, 8)}` : basename2(path) }));
|
|
357
|
+
const selected = Array.isArray(args.repos) ? args.repos : [];
|
|
358
|
+
if (selected.some((n) => !aliases.some((r) => r.alias === n))) throw new Error("Repository is not authorized");
|
|
359
|
+
const results = [];
|
|
360
|
+
for (const { path: repo, alias } of aliases.filter((r) => !selected.length || selected.includes(r.alias))) {
|
|
361
|
+
if (repo !== root && !await stat2(join2(repo, ".code-review-graph/graph.db")).then(() => true, () => false)) throw new Error(`Build ${repo} in its own session first`);
|
|
362
|
+
await pool.ensure(repo, owner, signal);
|
|
363
|
+
const data = valueOf(await pool.call(repo, owner, "semantic_search_nodes_tool", { query: args.query, kind: args.kind, limit: args.limit ?? 20, provider: "local", repo_root: repo }, signal));
|
|
364
|
+
for (const result2 of data.results) results.push({ ...result2, repo: alias });
|
|
365
|
+
}
|
|
366
|
+
results.sort((a, b) => Number(b.score ?? 0) - Number(a.score ?? 0));
|
|
367
|
+
const limit = Math.min(Number(args.max_results ?? 50), 100);
|
|
368
|
+
return { status: "ok", results: results.slice(0, limit), total: results.length, results_omitted: Math.max(0, results.length - limit), truncated: results.length > limit };
|
|
369
|
+
}
|
|
370
|
+
const graphUpdate = raw !== "build_or_update_graph_tool" ? await pool.ensure(root, owner, signal) : void 0;
|
|
371
|
+
if (raw === "apply_refactor_tool" && !args.dry_run) {
|
|
372
|
+
const plan = valueOf(await pool.call(root, owner, "get_refactor_edit_plan_tool", { refactor_id: args.refactor_id, repo_root: root }, signal));
|
|
373
|
+
const result2 = await commitPlan(ctx, exec, root, plan);
|
|
374
|
+
if (result2.status === "ok") {
|
|
375
|
+
try {
|
|
376
|
+
return { ...result2, graph_update: valueOf(await pool.call(root, owner, "build_or_update_graph_tool", { repo_root: root }, signal)) };
|
|
377
|
+
} catch (error) {
|
|
378
|
+
return { ...result2, graph_update_error: String(error) };
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return result2;
|
|
382
|
+
}
|
|
383
|
+
if (raw === "apply_refactor_tool") args = { ...args, dry_run: true };
|
|
384
|
+
const result = valueOf(await pool.call(root, owner, raw, { ...args, repo_root: root }, signal));
|
|
385
|
+
if (raw === "build_or_update_graph_tool") await pool.ensure(root, owner, signal);
|
|
386
|
+
return graphUpdate ? { ...result, graph_update: graphUpdate } : result;
|
|
387
|
+
}
|
|
388
|
+
for (const tool of tools) {
|
|
389
|
+
const parameters = structuredClone(tool.inputSchema);
|
|
390
|
+
delete parameters.properties?.repo_root;
|
|
391
|
+
parameters.required = parameters.required?.filter((n) => n !== "repo_root");
|
|
392
|
+
parameters.additionalProperties = false;
|
|
393
|
+
const validate = ajv.compile(parameters);
|
|
394
|
+
const definition = {
|
|
395
|
+
name: publicName(tool.name),
|
|
396
|
+
description: tool.description ?? tool.name,
|
|
397
|
+
parameters,
|
|
398
|
+
output,
|
|
399
|
+
timeoutMs: config.timeoutMs,
|
|
400
|
+
execute: async (args, exec) => {
|
|
401
|
+
if (!validate(args)) throw new Error(ajv.errorsText(validate.errors));
|
|
402
|
+
return invoke(tool.name, args, exec);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
ctx.effect(() => ctx.tools.register(definition));
|
|
406
|
+
}
|
|
407
|
+
ctx.effect(() => ctx.tools.register({
|
|
408
|
+
name: "crg_workflow",
|
|
409
|
+
description: "Select code graph tools: context, review, refactor, export, advanced or all. Begin with get_minimal_context.",
|
|
410
|
+
parameters: { type: "object", properties: { workflow: { type: "string", enum: [...groups] } }, required: ["workflow"], additionalProperties: false },
|
|
411
|
+
output,
|
|
412
|
+
execute: async (args, exec) => {
|
|
413
|
+
const workflow = args.workflow;
|
|
414
|
+
if (!groups.includes(workflow) || !exec.agent) throw new Error("Invalid workflow or missing agent");
|
|
415
|
+
return { tools: switchWorkflow(exec.agent, workflow) };
|
|
416
|
+
}
|
|
417
|
+
}));
|
|
418
|
+
const visualizationSchema = { type: "object", properties: {
|
|
419
|
+
mode: { type: "string", enum: ["auto", "file", "community", "full"] },
|
|
420
|
+
format: { type: "string", enum: ["html", "json", "graphml", "cypher", "obsidian", "svg"] },
|
|
421
|
+
seed_file: { type: "array", items: { type: "string" } },
|
|
422
|
+
seed_symbol: { type: "string" },
|
|
423
|
+
seed_changed: { type: "boolean" },
|
|
424
|
+
seed_changed_base: { type: "string" },
|
|
425
|
+
seed_flow: { type: "string" },
|
|
426
|
+
path_from: { type: "string" },
|
|
427
|
+
path_to: { type: "string" },
|
|
428
|
+
depth: { type: "integer", minimum: 0 },
|
|
429
|
+
render_depth: { type: "integer", minimum: 0 },
|
|
430
|
+
max_nodes: { type: "integer", minimum: 1 }
|
|
431
|
+
}, additionalProperties: false };
|
|
432
|
+
const validateVisualization = ajv.compile(visualizationSchema);
|
|
433
|
+
ctx.effect(() => ctx.tools.register({
|
|
434
|
+
name: "crg_visualize",
|
|
435
|
+
description: "Generate the local interactive graph for the DSH Code graph sidebar, or export HTML, JSON, GraphML, Cypher, Obsidian or SVG. Supports file, community, symbol, changed-code, flow and shortest-path views.",
|
|
436
|
+
parameters: visualizationSchema,
|
|
437
|
+
output,
|
|
438
|
+
timeoutMs: config.timeoutMs,
|
|
439
|
+
execute: async (value, exec) => {
|
|
440
|
+
if (!validateVisualization(value)) throw new Error(ajv.errorsText(validateVisualization.errors));
|
|
441
|
+
const args = value;
|
|
442
|
+
const root = await rootFor(exec);
|
|
443
|
+
const signal = AbortSignal.any([exec.signal, life.signal]);
|
|
444
|
+
await pool.ensure(root, exec.agent.id, signal);
|
|
445
|
+
for (const path of args.seed_file ?? []) await checkedPath(root, path, true);
|
|
446
|
+
const command = ["visualize", "--repo", root];
|
|
447
|
+
for (const [key, value2] of Object.entries(args)) {
|
|
448
|
+
const flag = `--${key.replaceAll("_", "-")}`;
|
|
449
|
+
if (Array.isArray(value2)) for (const item of value2) command.push(flag, String(item));
|
|
450
|
+
else if (value2 === true) command.push(flag);
|
|
451
|
+
else if (value2 !== void 0 && value2 !== false) command.push(flag, String(value2));
|
|
452
|
+
}
|
|
453
|
+
const { log } = await run(engine, command, root, signal);
|
|
454
|
+
const format = String(args.format ?? "html");
|
|
455
|
+
return { status: "ok", path: join2(root, ".code-review-graph", format === "obsidian" ? "obsidian" : `graph.${format}`), ...format === "html" ? { sidebar: "code-review-graph" } : {}, log };
|
|
456
|
+
}
|
|
457
|
+
}));
|
|
458
|
+
const promptNames = ["review_changes", "architecture_map", "debug_issue", "onboard_developer", "pre_merge_check"];
|
|
459
|
+
const promptSchema = { type: "object", properties: { name: { type: "string", enum: promptNames }, base: { type: "string" }, description: { type: "string" } }, required: ["name"], additionalProperties: false };
|
|
460
|
+
const validatePrompt = ajv.compile(promptSchema);
|
|
461
|
+
ctx.effect(() => ctx.tools.register({
|
|
462
|
+
name: "crg_prompt",
|
|
463
|
+
description: "Load one of the five original CRG workflows and reveal its graph tools.",
|
|
464
|
+
parameters: promptSchema,
|
|
465
|
+
output,
|
|
466
|
+
execute: async (args, exec) => {
|
|
467
|
+
if (!validatePrompt(args) || !exec.agent) throw new Error("Invalid workflow prompt or missing agent");
|
|
468
|
+
const { name: name2, ...parameters } = args;
|
|
469
|
+
const workflow = name2 === "pre_merge_check" ? "all" : name2 === "review_changes" ? "review" : name2 === "debug_issue" ? "review" : "advanced";
|
|
470
|
+
switchWorkflow(exec.agent, workflow);
|
|
471
|
+
const root = await rootFor(exec);
|
|
472
|
+
const { client } = await pool.acquire(root, exec.agent.id);
|
|
473
|
+
const result = await client.getPrompt({ name: name2, arguments: parameters }, { signal: AbortSignal.any([exec.signal, life.signal]), timeout: config.timeoutMs });
|
|
474
|
+
return { ...result, messages: result.messages.map((message) => ({ ...message, content: message.content.type === "text" ? { ...message.content, text: message.content.text.replace(/\b([a-z_]+_tool)\b/g, (raw) => names.includes(raw) ? publicName(raw) : raw) } : message.content })) };
|
|
475
|
+
}
|
|
476
|
+
}));
|
|
477
|
+
ctx.on("agent/created", ({ agent }) => {
|
|
478
|
+
switchWorkflow(agent);
|
|
479
|
+
return void 0;
|
|
480
|
+
});
|
|
481
|
+
ctx.on("agent/disposed", ({ agent }) => {
|
|
482
|
+
masks.get(agent.id)?.();
|
|
483
|
+
masks.delete(agent.id);
|
|
484
|
+
return pool.release(agent.id);
|
|
485
|
+
});
|
|
486
|
+
for (const agent of ctx.agents.list()) switchWorkflow(agent);
|
|
487
|
+
ctx.effect(() => ctx.systemPrompt.section({
|
|
488
|
+
name: "code-review-graph",
|
|
489
|
+
order: 80,
|
|
490
|
+
interpolate: false,
|
|
491
|
+
text: "Use crg_workflow to reveal task-specific local code graph tools, then get_minimal_context_tool before broader queries. Prefer minimal detail. crg_visualize opens the local graph in the Code graph sidebar. Refactors use session filesystem permissions."
|
|
492
|
+
}));
|
|
493
|
+
const skillsDir = new URL("../skills/", import.meta.url);
|
|
494
|
+
for (const slug of await readdir2(skillsDir)) {
|
|
495
|
+
const path = new URL(`${slug}/SKILL.md`, skillsDir);
|
|
496
|
+
const body = await readFile(path, "utf8");
|
|
497
|
+
const content = body.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, "").replace(/\b([a-z_]+_tool)\b/g, (raw) => names.includes(raw) ? publicName(raw) : raw);
|
|
498
|
+
if (!skillWorkflow[slug]) throw new Error(`Unmapped CRG skill: ${slug}`);
|
|
499
|
+
ctx.effect(() => ctx.skills.register({ name: `crg-${slug}`, description: `Code review graph: ${slug}`, source: "bundled", content: `First call crg_workflow with workflow "${skillWorkflow[slug]}". Tool names use mcp__code_review_graph__ prefixes.
|
|
500
|
+
|
|
501
|
+
${content}` }));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
export {
|
|
505
|
+
Config,
|
|
506
|
+
apply,
|
|
507
|
+
inject,
|
|
508
|
+
name,
|
|
509
|
+
output
|
|
510
|
+
};
|
|
511
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts", "../src/backend.ts", "../src/safety.ts", "../src/refactor.ts", "../src/workflows.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@deepseek-ai/cordis';\nimport type { ToolDefinition, ToolRunContext } from '@deepseek-ai/dsh-tools';\nimport type {} from '@deepseek-ai/dsh-agent';\nimport type {} from '@deepseek-ai/dsh-skill';\nimport type {} from '@deepseek-ai/dsh-system-prompt';\nimport z from '@deepseek-ai/schemastery';\nimport { Ajv } from 'ajv';\nimport { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { homedir } from 'node:os';\nimport { BackendPool, run, valueOf, type Engine } from './backend.ts';\nimport { repository, checkedPath, sha256 } from './safety.ts';\nimport { commitPlan, type EditPlan } from './refactor.ts';\nimport { exposed, groups, publicName, skillWorkflow, type Workflow } from './workflows.ts';\n\nexport const name = 'code-review-graph';\nexport const inject = ['tools', 'agents', 'fs', 'sandboxPolicy', 'skills', 'systemPrompt'];\nconst engineDir = join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'code-review-graph', 'engine');\nexport const Config = z.object({\n engineCommand: z.string().default(join(engineDir, process.platform === 'win32' ? 'Scripts/code-review-graph.exe' : 'bin/code-review-graph')),\n engineArgs: z.array(z.string()).default([]),\n timeoutMs: z.number().min(1000).default(120000),\n authorizedRepos: z.array(z.string()).default([]),\n embeddingProviders: z.array(z.string()).default(['local']),\n embeddingEnv: z.array(z.string()).default([]),\n});\nexport interface Configuration { engineCommand: string; engineArgs: string[]; timeoutMs: number; authorizedRepos: string[]; embeddingProviders: string[]; embeddingEnv: string[] }\ninterface Capability { name: string; description?: string; inputSchema: Record<string, unknown> & { properties?: Record<string, unknown>; required?: string[] } }\nexport const output: ToolDefinition['output'] = {\n schema: { type: 'object', additionalProperties: true },\n render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }],\n};\n\nexport async function apply(ctx: Context, config: Configuration): Promise<void> {\n const engine: Engine = { command: config.engineCommand, args: config.engineArgs, timeoutMs: config.timeoutMs, env: Object.fromEntries(config.embeddingEnv.filter(key => /^(OPENAI|GOOGLE|GEMINI|MINIMAX|VOYAGE|CRG)_/.test(key) && process.env[key] !== undefined).map(key => [key, process.env[key]!])) };\n const pool = new BackendPool(engine);\n const snapshot = JSON.parse(await readFile(new URL('../capabilities.json', import.meta.url), 'utf8')) as { tools: Capability[] };\n const tools = snapshot.tools.filter(t => t.name !== 'get_refactor_edit_plan_tool');\n const names = tools.map(t => t.name);\n const masks = new Map<string, () => void>();\n const ajv = new Ajv({ strict: false, allErrors: true });\n const life = new AbortController();\n ctx.effect(() => () => { life.abort(); for (const dispose of masks.values()) dispose(); return pool.dispose(); });\n const switchWorkflow = (agent: NonNullable<ToolRunContext['agent']>, workflow?: Workflow) => {\n pool.activate(agent.id);\n const available = workflow ? exposed(workflow, names) : [];\n masks.get(agent.id)?.();\n masks.set(agent.id, agent.ctx.tools.restrict({ deny: names.filter(n => !available.includes(n)).map(publicName) }));\n return available.map(publicName);\n };\n\n async function rootFor(exec: ToolRunContext) {\n if (!exec.agent) throw new Error('Graph tools require a session-owned agent');\n return repository(exec.agent.session.header.cwd);\n }\n\n async function invoke(raw: string, args: Record<string, unknown>, exec: ToolRunContext) {\n const root = await rootFor(exec);\n const owner = exec.agent!.id;\n const signal = AbortSignal.any([exec.signal, life.signal]);\n const providerKey = ['build_or_update_graph_tool', 'run_postprocess_tool'].includes(raw) ? 'embedding_provider' : 'provider';\n const provider = args[providerKey];\n if (raw === 'get_docs_section_tool') await checkedPath(root, 'docs/LLM-OPTIMIZED-REFERENCE.md', true);\n if (provider && (typeof provider !== 'string' || !config.embeddingProviders.includes(provider))) throw new Error('Embedding provider has not been authorized in plugin configuration');\n if (['semantic_search_nodes_tool', 'embed_graph_tool'].includes(raw) && !provider) args = { ...args, provider: 'local' };\n for (const key of ['file_path', 'file', 'path']) {\n if (typeof args[key] === 'string') await checkedPath(root, args[key] as string);\n }\n for (const key of ['changed_files', 'files']) {\n if (Array.isArray(args[key])) for (const path of args[key] as string[]) await checkedPath(root, path, true);\n }\n if (raw === 'list_repos_tool') {\n const roots = [...new Set([root, ...await Promise.all(config.authorizedRepos.map(repository))])];\n return { status: 'ok', repos: roots.map(path => ({ alias: roots.filter(r => basename(r) === basename(path)).length > 1 ? `${basename(path)}@${sha256(path).slice(0, 8)}` : basename(path), path })) };\n }\n if (raw === 'cross_repo_search_tool') {\n const roots = [...new Set([root, ...await Promise.all(config.authorizedRepos.map(repository))])];\n const aliases = roots.map(path => ({ path, alias: roots.filter(r => basename(r) === basename(path)).length > 1 ? `${basename(path)}@${sha256(path).slice(0, 8)}` : basename(path) }));\n const selected = Array.isArray(args.repos) ? args.repos as string[] : [];\n if (selected.some(n => !aliases.some(r => r.alias === n))) throw new Error('Repository is not authorized');\n const results: Record<string, unknown>[] = [];\n for (const { path: repo, alias } of aliases.filter(r => !selected.length || selected.includes(r.alias))) {\n if (repo !== root && !await stat(join(repo, '.code-review-graph/graph.db')).then(() => true, () => false)) throw new Error(`Build ${repo} in its own session first`);\n await pool.ensure(repo, owner, signal);\n const data = valueOf(await pool.call(repo, owner, 'semantic_search_nodes_tool', { query: args.query, kind: args.kind, limit: args.limit ?? 20, provider: 'local', repo_root: repo }, signal));\n for (const result of data.results as Record<string, unknown>[]) results.push({ ...result, repo: alias });\n }\n results.sort((a, b) => Number(b.score ?? 0) - Number(a.score ?? 0));\n const limit = Math.min(Number(args.max_results ?? 50), 100);\n return { status: 'ok', results: results.slice(0, limit), total: results.length, results_omitted: Math.max(0, results.length - limit), truncated: results.length > limit };\n }\n const graphUpdate = raw !== 'build_or_update_graph_tool' ? await pool.ensure(root, owner, signal) : undefined;\n if (raw === 'apply_refactor_tool' && !args.dry_run) {\n const plan = valueOf(await pool.call(root, owner, 'get_refactor_edit_plan_tool', { refactor_id: args.refactor_id, repo_root: root }, signal)) as unknown as EditPlan;\n const result = await commitPlan(ctx, exec, root, plan);\n if (result.status === 'ok') {\n try { return { ...result, graph_update: valueOf(await pool.call(root, owner, 'build_or_update_graph_tool', { repo_root: root }, signal)) }; }\n catch (error) { return { ...result, graph_update_error: String(error) }; }\n }\n return result;\n }\n if (raw === 'apply_refactor_tool') args = { ...args, dry_run: true };\n const result = valueOf(await pool.call(root, owner, raw, { ...args, repo_root: root }, signal));\n if (raw === 'build_or_update_graph_tool') await pool.ensure(root, owner, signal);\n return graphUpdate ? { ...result, graph_update: graphUpdate } : result;\n }\n\n for (const tool of tools) {\n const parameters = structuredClone(tool.inputSchema);\n delete parameters.properties?.repo_root;\n parameters.required = parameters.required?.filter(n => n !== 'repo_root');\n parameters.additionalProperties = false;\n const validate = ajv.compile(parameters);\n const definition = {\n name: publicName(tool.name), description: tool.description ?? tool.name, parameters, output,\n timeoutMs: config.timeoutMs,\n execute: async (args: unknown, exec: ToolRunContext) => {\n if (!validate(args)) throw new Error(ajv.errorsText(validate.errors));\n return invoke(tool.name, args as Record<string, unknown>, exec);\n },\n } as ToolDefinition;\n ctx.effect(() => ctx.tools.register(definition));\n }\n\n ctx.effect(() => ctx.tools.register({ name: 'crg_workflow', description: 'Select code graph tools: context, review, refactor, export, advanced or all. Begin with get_minimal_context.',\n parameters: { type: 'object', properties: { workflow: { type: 'string', enum: [...groups] } }, required: ['workflow'], additionalProperties: false }, output,\n execute: async (args, exec) => {\n const workflow = (args as { workflow: Workflow }).workflow;\n if (!groups.includes(workflow) || !exec.agent) throw new Error('Invalid workflow or missing agent');\n return { tools: switchWorkflow(exec.agent, workflow) };\n },\n }));\n\n const visualizationSchema = { type: 'object', properties: {\n mode: { type: 'string', enum: ['auto', 'file', 'community', 'full'] },\n format: { type: 'string', enum: ['html', 'json', 'graphml', 'cypher', 'obsidian', 'svg'] },\n seed_file: { type: 'array', items: { type: 'string' } }, seed_symbol: { type: 'string' }, seed_changed: { type: 'boolean' }, seed_changed_base: { type: 'string' }, seed_flow: { type: 'string' },\n path_from: { type: 'string' }, path_to: { type: 'string' }, depth: { type: 'integer', minimum: 0 }, render_depth: { type: 'integer', minimum: 0 }, max_nodes: { type: 'integer', minimum: 1 },\n }, additionalProperties: false };\n const validateVisualization = ajv.compile(visualizationSchema);\n ctx.effect(() => ctx.tools.register({ name: 'crg_visualize', description: 'Generate the local interactive graph for the DSH Code graph sidebar, or export HTML, JSON, GraphML, Cypher, Obsidian or SVG. Supports file, community, symbol, changed-code, flow and shortest-path views.',\n parameters: visualizationSchema, output,\n timeoutMs: config.timeoutMs,\n execute: async (value, exec) => {\n if (!validateVisualization(value)) throw new Error(ajv.errorsText(validateVisualization.errors));\n const args = value as Record<string, unknown>;\n const root = await rootFor(exec);\n const signal = AbortSignal.any([exec.signal, life.signal]);\n await pool.ensure(root, exec.agent!.id, signal);\n for (const path of (args.seed_file ?? []) as string[]) await checkedPath(root, path, true);\n const command = ['visualize', '--repo', root];\n for (const [key, value] of Object.entries(args)) {\n const flag = `--${key.replaceAll('_', '-')}`;\n if (Array.isArray(value)) for (const item of value) command.push(flag, String(item));\n else if (value === true) command.push(flag);\n else if (value !== undefined && value !== false) command.push(flag, String(value));\n }\n const { log } = await run(engine, command, root, signal);\n const format = String(args.format ?? 'html');\n return { status: 'ok', path: join(root, '.code-review-graph', format === 'obsidian' ? 'obsidian' : `graph.${format}`), ...(format === 'html' ? { sidebar: 'code-review-graph' } : {}), log };\n },\n }));\n const promptNames = ['review_changes', 'architecture_map', 'debug_issue', 'onboard_developer', 'pre_merge_check'];\n const promptSchema = { type: 'object', properties: { name: { type: 'string', enum: promptNames }, base: { type: 'string' }, description: { type: 'string' } }, required: ['name'], additionalProperties: false };\n const validatePrompt = ajv.compile(promptSchema);\n ctx.effect(() => ctx.tools.register({ name: 'crg_prompt', description: 'Load one of the five original CRG workflows and reveal its graph tools.', parameters: promptSchema, output,\n execute: async (args, exec) => {\n if (!validatePrompt(args) || !exec.agent) throw new Error('Invalid workflow prompt or missing agent');\n const { name, ...parameters } = args as { name: string; base?: string; description?: string };\n const workflow: Workflow = name === 'pre_merge_check' ? 'all' : name === 'review_changes' ? 'review' : name === 'debug_issue' ? 'review' : 'advanced';\n switchWorkflow(exec.agent, workflow);\n const root = await rootFor(exec);\n const { client } = await pool.acquire(root, exec.agent.id);\n const result = await client.getPrompt({ name, arguments: parameters }, { signal: AbortSignal.any([exec.signal, life.signal]), timeout: config.timeoutMs });\n return { ...result, messages: result.messages.map(message => ({ ...message, content: message.content.type === 'text' ? { ...message.content, text: message.content.text.replace(/\\b([a-z_]+_tool)\\b/g, raw => names.includes(raw) ? publicName(raw) : raw) } : message.content })) };\n },\n }));\n ctx.on('agent/created', ({ agent }) => { switchWorkflow(agent); return undefined; });\n ctx.on('agent/disposed', ({ agent }) => { masks.get(agent.id)?.(); masks.delete(agent.id); return pool.release(agent.id); });\n for (const agent of ctx.agents.list()) switchWorkflow(agent);\n ctx.effect(() => ctx.systemPrompt.section({ name: 'code-review-graph', order: 80, interpolate: false,\n text: 'Use crg_workflow to reveal task-specific local code graph tools, then get_minimal_context_tool before broader queries. Prefer minimal detail. crg_visualize opens the local graph in the Code graph sidebar. Refactors use session filesystem permissions.' }));\n\n const skillsDir = new URL('../skills/', import.meta.url);\n for (const slug of await readdir(skillsDir)) {\n const path = new URL(`${slug}/SKILL.md`, skillsDir);\n const body = await readFile(path, 'utf8');\n const content = body.replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/, '').replace(/\\b([a-z_]+_tool)\\b/g, raw => names.includes(raw) ? publicName(raw) : raw);\n if (!skillWorkflow[slug]) throw new Error(`Unmapped CRG skill: ${slug}`);\n ctx.effect(() => ctx.skills.register({ name: `crg-${slug}`, description: `Code review graph: ${slug}`, source: 'bundled', content: `First call crg_workflow with workflow \"${skillWorkflow[slug]}\". Tool names use mcp__code_review_graph__ prefixes.\\n\\n${content}` }));\n }\n}\n", "import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport { spawn, type ChildProcess } from 'node:child_process';\nimport { checkedData, scrubEnv } from './safety.ts';\n\nexport interface Engine { command: string; args: string[]; timeoutMs: number; env?: Record<string, string> }\nconst environment = (engine: Engine) => ({ ...scrubEnv(process.env), ...engine.env });\nexport function valueOf(result: unknown): Record<string, unknown> {\n const r = result as { isError?: boolean; structuredContent?: Record<string, unknown>; content?: { type: string; text?: string }[] };\n const text = r.content?.filter(x => x.type === 'text').map(x => x.text).join('\\n') ?? '';\n if (r.isError) throw new Error(text || 'Engine tool failed');\n const value = r.structuredContent ?? (() => { try { return JSON.parse(text); } catch { return { text }; } })();\n if (value.status === 'error') throw new Error(String(value.error));\n return value;\n}\n\nexport async function connect(engine: Engine, cwd: string): Promise<Client> {\n await checkedData(cwd);\n const transport = new StdioClientTransport({ command: engine.command, args: [...engine.args, 'serve', '--repo', cwd], cwd, env: environment(engine), stderr: 'pipe' });\n transport.stderr?.on('data', () => {});\n const client = new Client({ name: 'dsh-code-review-graph', version: '0.1.0' });\n try { await client.connect(transport); return client; }\n catch (error) { await transport.close(); throw new Error(`CRG engine unavailable. Run dsh-crg prepare explicitly. ${String(error)}`); }\n}\n\nasync function stop(child?: ChildProcess): Promise<void> {\n if (!child || child.exitCode !== null || child.signalCode !== null) return;\n await new Promise<void>(resolve => {\n const timer = setTimeout(() => { child.kill('SIGKILL'); resolve(); }, 3000);\n child.once('exit', () => { clearTimeout(timer); resolve(); });\n child.kill();\n });\n}\ninterface Entry { client: Client; owners: Set<string>; ready?: Promise<void>; watcher?: ChildProcess; watchError?: string; queue: Promise<unknown>; update?: Record<string, unknown> }\nexport class BackendPool {\n private entries = new Map<string, Promise<Entry>>();\n private retired = new Set<string>();\n private closed = false;\n constructor(readonly engine: Engine) {}\n activate(owner: string): void { this.retired.delete(owner); }\n\n async acquire(root: string, owner: string): Promise<Entry> {\n if (this.closed || this.retired.has(owner)) throw new Error('Session has been released');\n let promise = this.entries.get(root);\n if (!promise) {\n promise = connect(this.engine, root).then(client => ({ client, owners: new Set<string>(), queue: Promise.resolve() }));\n this.entries.set(root, promise);\n promise.catch(() => { if (this.entries.get(root) === promise) this.entries.delete(root); });\n }\n const entry = await promise;\n if (this.closed || this.retired.has(owner)) throw new Error('Session has been released');\n entry.owners.add(owner);\n return entry;\n }\n\n async call(root: string, owner: string, name: string, args: Record<string, unknown>, signal: AbortSignal) {\n const entry = await this.acquire(root, owner);\n // One mutation at a time per SQLite graph; cancellation restarts this repository's shared worker.\n const work = entry.queue.catch(() => {}).then(async () => {\n signal.throwIfAborted();\n const cancel = () => { this.entries.delete(root); void stop(entry.watcher); void entry.client.close(); };\n signal.addEventListener('abort', cancel, { once: true });\n let result: unknown;\n try {\n await checkedData(root);\n if (entry.watchError) throw new Error(`Incremental watcher stopped: ${entry.watchError}`);\n result = await entry.client.callTool({ name, arguments: args }, undefined, { signal, timeout: this.engine.timeoutMs });\n } catch (error) {\n // A timed-out Python thread cannot safely be left mutating the graph.\n this.entries.delete(root); await stop(entry.watcher); await entry.client.close();\n throw error;\n } finally { signal.removeEventListener('abort', cancel); }\n // A normal tool error must not discard another call's pending refactor preview.\n valueOf(result);\n return result;\n });\n entry.queue = work;\n return work;\n }\n\n async ensure(root: string, owner: string, signal: AbortSignal): Promise<Record<string, unknown> | undefined> {\n const entry = await this.acquire(root, owner);\n entry.ready ??= (async () => {\n // An existing database can be stale after all sessions were closed.\n const update = valueOf(await this.call(root, owner, 'build_or_update_graph_tool', { repo_root: root }, signal));\n if (update.status === 'partial' || Array.isArray(update.warnings) && update.warnings.length) entry.update = update;\n signal.throwIfAborted();\n const watcher = spawn(this.engine.command, [...this.engine.args, 'watch', '--repo', root], { cwd: root, env: environment(this.engine), stdio: 'ignore', windowsHide: true });\n entry.watcher = watcher;\n await new Promise<void>((resolve, reject) => { watcher.once('spawn', resolve); watcher.once('error', reject); });\n watcher.on('error', error => { entry.watchError = String(error); });\n watcher.on('exit', (code, reason) => { if (entry.watcher === watcher) entry.watchError = `exit ${code ?? reason}`; });\n })().catch(error => { entry.ready = undefined; throw error; });\n await entry.ready;\n if (entry.watchError) throw new Error(`Incremental watcher stopped: ${entry.watchError}`);\n return entry.update;\n }\n\n async release(owner: string): Promise<void> {\n this.retired.add(owner);\n for (const [root, promise] of this.entries) {\n const entry = await promise.catch(() => undefined);\n if (!entry) continue;\n entry.owners.delete(owner);\n if (!entry.owners.size) { this.entries.delete(root); const watcher = entry.watcher; entry.watcher = undefined; await stop(watcher); await entry.client.close(); }\n }\n }\n\n async dispose(): Promise<void> {\n this.closed = true;\n const entries = [...this.entries.values()]; this.entries.clear();\n for (const promise of entries) {\n const entry = await promise.catch(() => undefined);\n if (entry) { const watcher = entry.watcher; entry.watcher = undefined; await stop(watcher); await entry.client.close(); }\n }\n }\n}\n\nexport async function run(engine: Engine, args: string[], cwd: string, signal: AbortSignal): Promise<{ log: string }> {\n await checkedData(cwd);\n signal = AbortSignal.any([signal, AbortSignal.timeout(engine.timeoutMs)]);\n return new Promise((resolve, reject) => {\n let log = '';\n const child = spawn(engine.command, [...engine.args, ...args], { cwd, env: environment(engine), stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, signal });\n const capture = (bytes: Buffer) => { log = (log + bytes.toString()).slice(-16000); };\n child.stdout?.on('data', capture); child.stderr?.on('data', capture);\n child.on('error', reject);\n child.on('exit', code => code === 0 ? resolve({ log }) : reject(new Error(`Engine command exited ${code}: ${log}`)));\n });\n}\n", "import { realpath, stat, lstat, readdir } from 'node:fs/promises';\nimport { isAbsolute, relative, resolve, sep, dirname, basename, join } from 'node:path';\nimport { createHash } from 'node:crypto';\n\nexport const sha256 = (bytes: Uint8Array | string): string => createHash('sha256').update(bytes).digest('hex');\n\nexport function contained(root: string, path: string): boolean {\n const part = relative(root, path);\n return part === '' || (!isAbsolute(part) && part !== '..' && !part.startsWith(`..${sep}`));\n}\n\nexport async function checkedPath(root: string, value: string, allowMissing = false): Promise<string> {\n const candidate = resolve(root, value);\n if (!contained(root, candidate)) throw new Error('Path is outside the authorized repository');\n let current = candidate;\n const suffix: string[] = [];\n while (allowMissing && !await lstat(current).then(() => true, () => false)) {\n suffix.unshift(basename(current)); current = dirname(current);\n }\n const canonical = join(await realpath(current), ...suffix);\n if (!contained(root, canonical)) throw new Error('Symlink escapes the authorized repository');\n return canonical;\n}\n\nexport async function repository(cwd: string | undefined): Promise<string> {\n if (!cwd || !isAbsolute(cwd)) throw new Error('This session has no local absolute workspace');\n const root = await realpath(cwd);\n if (!(await stat(root)).isDirectory()) throw new Error('Workspace is not a directory');\n for (const marker of ['.git', '.svn']) {\n if (await stat(resolve(root, marker)).then(() => true, () => false)) return root;\n }\n throw new Error('Select a Git or SVN repository before using the graph');\n}\n\nexport function scrubEnv(env: NodeJS.ProcessEnv): Record<string, string> {\n return { ...Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== undefined && !/KEY|PASSWORD|SECRET|TOKEN|^(DSH|CRG|OPENAI|GOOGLE|GEMINI|MINIMAX|VOYAGE|HF)_/i.test(key))), HF_HUB_OFFLINE: '1', TRANSFORMERS_OFFLINE: '1', HF_HUB_DISABLE_TELEMETRY: '1' } as Record<string, string>;\n}\n\nexport async function checkedData(root: string): Promise<void> {\n const dir = resolve(root, '.code-review-graph');\n if (!await lstat(dir).then(() => true, () => false)) return;\n await checkedPath(root, dir);\n const entries = await readdir(dir, { withFileTypes: true, recursive: true });\n for (const entry of entries) {\n if (entry.isSymbolicLink()) await checkedPath(root, join(entry.parentPath, entry.name));\n }\n}\n", "import type { Context } from '@deepseek-ai/cordis';\nimport type { ToolRunContext } from '@deepseek-ai/dsh-tools';\nimport type {} from '@deepseek-ai/dsh-fs';\nimport type {} from '@deepseek-ai/dsh-sandbox-policy';\nimport { checkedPath, sha256 } from './safety.ts';\n\nexport interface EditPlan { files: { path: string; before_sha256: string; after_content: string; edit_count: number }[] }\nexport async function commitPlan(ctx: Context, exec: ToolRunContext, root: string, plan: EditPlan) {\n if (!exec.agent) throw new Error('Refactor requires a session-owned agent');\n const policy = ctx.sandboxPolicy.resolve({ session: exec.agent.session });\n if (policy.mode === 'read-only') throw new Error('Refactor is denied by read-only policy');\n if (!Array.isArray(plan.files)) throw new Error('Invalid edit plan');\n const prepared = [];\n const seen = new Set<string>();\n for (const file of plan.files) {\n if (typeof file.path !== 'string' || !/^[a-f0-9]{64}$/.test(file.before_sha256) || typeof file.after_content !== 'string' || !Number.isInteger(file.edit_count) || file.edit_count < 0) throw new Error('Invalid edit plan file');\n exec.signal.throwIfAborted();\n const path = await checkedPath(root, file.path);\n if (seen.has(path)) throw new Error('Duplicate edit target');\n seen.add(path);\n const target = await ctx.fs.resolve(path, { cwd: root, signal: exec.signal });\n const before = await ctx.fs.stat(target, exec.signal);\n if (!before || before.type !== 'file') throw new Error('Edit target is not a regular file');\n const bytes = await ctx.fs.readBytes(target, exec.signal, 32 * 1024 * 1024);\n if (sha256(bytes) !== file.before_sha256) throw new Error(`Stale edit plan: ${path}`);\n const after = await ctx.fs.stat(target, exec.signal);\n if (after?.version !== before.version) throw new Error(`File changed during preflight: ${path}`);\n const intent = await ctx.waterfall('fs/write-intent', target, exec, () => undefined);\n if (intent && (intent.kind !== 'replaceIfVersion' || intent.version !== before.version)) throw new Error(`File intent disagrees with edit plan: ${path}`);\n prepared.push({ file, path, target, original: Buffer.from(bytes).toString('utf8'), intent: intent ?? { kind: 'replaceIfVersion' as const, version: before.version } });\n }\n const applied: string[] = [];\n const recovery: EditPlan['files'] = [];\n try {\n for (const item of prepared) {\n exec.signal.throwIfAborted();\n await checkedPath(root, item.path);\n const outcome = await ctx.fs.writeText(item.target, item.file.after_content, item.intent, exec.signal, policy);\n ctx.emit('fs/observed', item.target, { kind: 'present', version: outcome.version }, exec);\n applied.push(item.path);\n recovery.push({ path: item.path, before_sha256: sha256(item.file.after_content), after_content: item.original, edit_count: item.file.edit_count });\n }\n } catch (error) {\n // Return the complete recovery patch through the tool output; never silently roll back a later edit.\n return { status: 'partial_failure', error: String(error), files_modified: applied, recovery_patch: { files: recovery } };\n }\n return { status: 'ok', files_modified: applied, edits_applied: plan.files.reduce((n, f) => n + f.edit_count, 0) };\n}\n", "export const groups = ['context', 'review', 'refactor', 'export', 'advanced', 'all'] as const;\nexport type Workflow = typeof groups[number];\nconst context = ['build_or_update_graph_tool', 'get_minimal_context_tool', 'query_graph_tool', 'semantic_search_nodes_tool', 'list_graph_stats_tool', 'get_docs_section_tool'];\nconst members: Record<Exclude<Workflow, 'all'>, string[]> = {\n context,\n review: [...context, 'detect_changes_tool', 'get_review_context_tool', 'get_impact_radius_tool', 'get_affected_flows_tool', 'list_flows_tool', 'get_flow_tool', 'list_communities_tool'],\n refactor: [...context, 'refactor_tool', 'apply_refactor_tool', 'find_large_functions_tool', 'get_impact_radius_tool', 'get_affected_flows_tool', 'detect_changes_tool'],\n export: [...context, 'generate_wiki_tool', 'get_wiki_page_tool'],\n advanced: [...context, 'embed_graph_tool', 'run_postprocess_tool', 'list_repos_tool', 'cross_repo_search_tool', 'list_communities_tool', 'get_community_tool', 'get_architecture_overview_tool', 'get_hub_nodes_tool', 'get_bridge_nodes_tool', 'get_knowledge_gaps_tool', 'get_surprising_connections_tool', 'get_suggested_questions_tool', 'traverse_graph_tool', 'detect_changes_tool', 'list_flows_tool', 'get_flow_tool', 'find_large_functions_tool'],\n};\nexport const skillWorkflow: Record<string, Workflow> = {\n 'build-graph': 'advanced', 'debug-issue': 'review', 'explore-codebase': 'advanced',\n 'refactor-safely': 'refactor', 'review-changes': 'review', 'review-delta': 'review', 'review-pr': 'review',\n};\nexport const publicName = (raw: string): string => `mcp__code_review_graph__${raw}`;\nexport function exposed(workflow: Workflow, names: string[]): string[] {\n return workflow === 'all' ? names : names.filter(name => members[workflow].includes(name));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["readdir", "stat", "join", "basename", "resolve", "name", "name", "join", "basename", "stat", "result", "value", "name", "readdir"]
|
|
7
|
+
}
|