dsh-code-review-graph 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +143 -10
- package/README.md +127 -9
- package/dist/backend.js +2 -2
- package/dist/backend.js.map +2 -2
- package/dist/client.js +45 -2
- package/dist/client.js.map +3 -3
- package/dist/index.js +147 -33
- package/dist/index.js.map +4 -4
- package/dist/setup.js +30 -14
- package/dist/setup.js.map +2 -2
- package/docs/release-0.1.2.md +29 -0
- package/docs/validation.md +20 -0
- package/package.json +2 -2
- package/docs/release-0.1.1.md +0 -30
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
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.1' });\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", "
|
|
3
|
+
"sources": ["../src/index.ts", "../src/backend.ts", "../src/safety.ts", "../src/refactor.ts", "../src/workflows.ts", "../src/setup.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';\nimport { prepare } from './setup.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 async function visualize(args: Record<string, unknown>, agent: NonNullable<ToolRunContext['agent']>, signal: AbortSignal) {\n const root = await repository(agent.session.header.cwd);\n signal = AbortSignal.any([signal, life.signal]);\n const graphUpdate = await pool.ensure(root, 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' } : {}), ...(graphUpdate ? { graph_update: graphUpdate } : {}), log };\n }\n\n // Native human commands reuse DSH's session/Agent lookup, cancellation and command history.\n // They never send a prompt or tool request to a model.\n let preparation: Promise<void> | undefined;\n const prepareDefault = (signal: AbortSignal) => {\n if (config.engineCommand !== join(engineDir, process.platform === 'win32' ? 'Scripts/code-review-graph.exe' : 'bin/code-review-graph') || config.engineArgs.length) {\n throw new Error('A custom engine is configured. Prepare that engine, or restore the default engine configuration. / \u5F53\u524D\u914D\u7F6E\u4E86\u81EA\u5B9A\u4E49\u5F15\u64CE\uFF0C\u8BF7\u51C6\u5907\u8BE5\u5F15\u64CE\u6216\u6062\u590D\u9ED8\u8BA4\u914D\u7F6E\u3002');\n }\n return preparation ??= prepare(undefined, undefined, { signal: AbortSignal.any([signal, life.signal]) }).finally(() => { preparation = undefined; });\n };\n type HumanInvocation = { agent: NonNullable<ToolRunContext['agent']>; signal: AbortSignal; rawInput: string };\n ctx.inject(['commands'], scope => {\n const commands = scope.get('commands') as { register(definition: { name: string; description: string; handler: (invocation: HumanInvocation) => Promise<{ kind: 'success'; text: string }> }): () => void };\n scope.effect(() => commands.register({ name: 'crg-setup', description: '\u51C6\u5907\u672C\u5730\u56FE\u8C31\u5F15\u64CE / Prepare the local graph engine', handler: async ({ signal, rawInput }) => {\n if (rawInput.trim()) throw new Error('/crg-setup does not need parameters / \u65E0\u9700\u586B\u5199\u53C2\u6570');\n await prepareDefault(signal);\n return { kind: 'success', text: '\u56FE\u8C31\u5F15\u64CE\u5DF2\u51C6\u5907\u597D\u3002\u6253\u5F00\u53F3\u4FA7\u4EE3\u7801\u56FE\u8C31\uFF0C\u70B9\u51FB\u751F\u6210\u56FE\u8C31\u3002 / Engine ready. Open Code graph and click Generate graph.' };\n } }));\n scope.effect(() => commands.register({ name: 'crg-graph', description: '\u751F\u6210\uFF0F\u66F4\u65B0\u4EA4\u4E92\u4EE3\u7801\u56FE\u8C31\uFF0C\u65E0\u9700\u6A21\u578B / Generate or update the interactive code graph without a model', handler: async ({ agent, signal, rawInput }) => {\n if (rawInput.trim()) throw new Error('/crg-graph does not need parameters / \u65E0\u9700\u586B\u5199\u53C2\u6570');\n await repository(agent.session.header.cwd);\n if (config.engineCommand === join(engineDir, process.platform === 'win32' ? 'Scripts/code-review-graph.exe' : 'bin/code-review-graph') && !config.engineArgs.length) await prepareDefault(signal);\n const result = await visualize({ mode: 'full', format: 'html' }, agent, signal);\n return { kind: 'success', text: `\u56FE\u8C31\u5DF2\u751F\u6210 / Graph generated: ${result.path}${result.graph_update ? '\\n\u89E3\u6790\u8B66\u544A / Parse warnings: ' + JSON.stringify(result.graph_update) : ''}` };\n } }));\n });\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 if (!exec.agent) throw new Error('Graph tools require a session-owned agent');\n return visualize(value as Record<string, unknown>, exec.agent, exec.signal);\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 generates a local graph for the Code graph sidebar; users can also generate it directly from that page without a model. 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.2' });\n try { await client.connect(transport); return client; }\n catch (error) { await transport.close(); throw new Error(`CRG engine unavailable. Open Code graph and click Set up engine, or run /crg-setup (CLI: dsh-crg prepare). ${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", "#!/usr/bin/env node\nimport { spawn } from 'node:child_process';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport const environment = join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'code-review-graph', 'engine');\nexport const pythonIn = (dir: string) => join(dir, process.platform === 'win32' ? 'Scripts/python.exe' : 'bin/python');\ninterface Preparation { signal?: AbortSignal; onProgress?: (text: string) => void }\nasync function command(exe: string, args: string[], quiet = false, options: Preparation = {}): Promise<void> {\n options.signal?.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n let log = '';\n const child = spawn(exe, args, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, signal: options.signal });\n const capture = (bytes: Buffer) => { const text = bytes.toString(); log = (log + text).slice(-16000); if (!quiet) options.onProgress?.(text); };\n child.stdout.on('data', capture); child.stderr.on('data', capture);\n child.on('error', reject); child.on('close', code => code === 0 ? resolve() : reject(new Error(`${exe} exited ${code}: ${log}`)));\n });\n}\nexport async function prepare(source?: string, python?: string, options: Preparation = {}): Promise<void> {\n options = { ...options, signal: AbortSignal.any([...(options.signal ? [options.signal] : []), AbortSignal.timeout(15 * 60 * 1000)]) };\n options.signal!.throwIfAborted();\n const execute = (exe: string, args: string[], quiet = false) => command(exe, args, quiet, options);\n const engine = JSON.parse(await readFile(new URL('../engine.json', import.meta.url), 'utf8'));\n const pinned = source ?? engine.source;\n const stamp = join(environment, 'dsh-crg-source.json');\n if (await readFile(stamp, 'utf8').then(value => JSON.parse(value).source === pinned, () => false)) {\n try { await execute(pythonIn(environment), ['-c', 'from code_review_graph.refactor import get_refactor_edit_plan'], true); options.onProgress?.('CRG engine is already prepared.'); return; } catch { options.signal!.throwIfAborted(); }\n }\n await mkdir(environment, { recursive: true });\n let uv = false;\n try { await execute('uv', ['--version'], true); uv = true; } catch { options.signal!.throwIfAborted(); }\n if (uv && !python) {\n await execute('uv', ['venv', '--allow-existing', '--python', '>=3.10', environment]);\n await execute('uv', ['pip', 'install', '--python', pythonIn(environment), pinned]);\n } else {\n let selected: { exe: string; args: string[] } | undefined;\n for (const candidate of python ? [{ exe: python, args: [] }] : [{ exe: 'python3', args: [] }, { exe: 'python', args: [] }, { exe: 'py', args: ['-3'] }]) {\n try { await execute(candidate.exe, [...candidate.args, '-c', 'import sys; assert sys.version_info >= (3,10)'], true); selected = candidate; break; } catch { options.signal!.throwIfAborted(); }\n }\n if (!selected) throw new Error('Install uv or real Python 3.10+; Windows Store aliases are not a Python runtime.');\n await execute(selected.exe, [...selected.args, '-m', 'venv', environment]);\n await execute(pythonIn(environment), ['-m', 'pip', 'install', pinned]);\n }\n await execute(pythonIn(environment), ['-c', 'from code_review_graph.refactor import get_refactor_edit_plan'], true);\n options.signal!.throwIfAborted();\n await writeFile(stamp, JSON.stringify({ source: pinned }), 'utf8');\n}\nif (process.argv[1] && resolve(fileURLToPath(import.meta.url)) === resolve(process.argv[1])) {\n if (process.argv[2] !== 'prepare') { console.error('Usage: dsh-crg prepare [engine-source] [--python executable]'); process.exitCode = 2; }\n else {\n const args = process.argv.slice(3);\n const flag = args.indexOf('--python');\n const python = flag >= 0 ? args.splice(flag, 2)[1] : undefined;\n try { await prepare(args[0], python, { onProgress: text => process.stdout.write(text.endsWith('\\n') ? text : text + '\\n') }); } catch (error) { console.error(String(error)); process.exitCode = 1; }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["readFile", "readdir", "stat", "join", "basename", "homedir", "resolve", "name", "name", "spawn", "join", "resolve", "environment", "join", "homedir", "readFile", "basename", "stat", "result", "command", "name", "readdir"]
|
|
7
7
|
}
|
package/dist/setup.js
CHANGED
|
@@ -8,50 +8,66 @@ import { join, resolve } from "node:path";
|
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
var environment = join(process.env.DSH_HOME ?? join(homedir(), ".dsh"), "code-review-graph", "engine");
|
|
10
10
|
var pythonIn = (dir) => join(dir, process.platform === "win32" ? "Scripts/python.exe" : "bin/python");
|
|
11
|
-
async function command(exe, args, quiet = false) {
|
|
11
|
+
async function command(exe, args, quiet = false, options = {}) {
|
|
12
|
+
options.signal?.throwIfAborted();
|
|
12
13
|
await new Promise((resolve2, reject) => {
|
|
13
|
-
|
|
14
|
+
let log = "";
|
|
15
|
+
const child = spawn(exe, args, { stdio: ["ignore", "pipe", "pipe"], windowsHide: true, signal: options.signal });
|
|
16
|
+
const capture = (bytes) => {
|
|
17
|
+
const text = bytes.toString();
|
|
18
|
+
log = (log + text).slice(-16e3);
|
|
19
|
+
if (!quiet) options.onProgress?.(text);
|
|
20
|
+
};
|
|
21
|
+
child.stdout.on("data", capture);
|
|
22
|
+
child.stderr.on("data", capture);
|
|
14
23
|
child.on("error", reject);
|
|
15
|
-
child.on("
|
|
24
|
+
child.on("close", (code) => code === 0 ? resolve2() : reject(new Error(`${exe} exited ${code}: ${log}`)));
|
|
16
25
|
});
|
|
17
26
|
}
|
|
18
|
-
async function prepare(source, python) {
|
|
27
|
+
async function prepare(source, python, options = {}) {
|
|
28
|
+
options = { ...options, signal: AbortSignal.any([...options.signal ? [options.signal] : [], AbortSignal.timeout(15 * 60 * 1e3)]) };
|
|
29
|
+
options.signal.throwIfAborted();
|
|
30
|
+
const execute = (exe, args, quiet = false) => command(exe, args, quiet, options);
|
|
19
31
|
const engine = JSON.parse(await readFile(new URL("../engine.json", import.meta.url), "utf8"));
|
|
20
32
|
const pinned = source ?? engine.source;
|
|
21
33
|
const stamp = join(environment, "dsh-crg-source.json");
|
|
22
34
|
if (await readFile(stamp, "utf8").then((value) => JSON.parse(value).source === pinned, () => false)) {
|
|
23
35
|
try {
|
|
24
|
-
await
|
|
25
|
-
|
|
36
|
+
await execute(pythonIn(environment), ["-c", "from code_review_graph.refactor import get_refactor_edit_plan"], true);
|
|
37
|
+
options.onProgress?.("CRG engine is already prepared.");
|
|
26
38
|
return;
|
|
27
39
|
} catch {
|
|
40
|
+
options.signal.throwIfAborted();
|
|
28
41
|
}
|
|
29
42
|
}
|
|
30
43
|
await mkdir(environment, { recursive: true });
|
|
31
44
|
let uv = false;
|
|
32
45
|
try {
|
|
33
|
-
await
|
|
46
|
+
await execute("uv", ["--version"], true);
|
|
34
47
|
uv = true;
|
|
35
48
|
} catch {
|
|
49
|
+
options.signal.throwIfAborted();
|
|
36
50
|
}
|
|
37
51
|
if (uv && !python) {
|
|
38
|
-
await
|
|
39
|
-
await
|
|
52
|
+
await execute("uv", ["venv", "--allow-existing", "--python", ">=3.10", environment]);
|
|
53
|
+
await execute("uv", ["pip", "install", "--python", pythonIn(environment), pinned]);
|
|
40
54
|
} else {
|
|
41
55
|
let selected;
|
|
42
56
|
for (const candidate of python ? [{ exe: python, args: [] }] : [{ exe: "python3", args: [] }, { exe: "python", args: [] }, { exe: "py", args: ["-3"] }]) {
|
|
43
57
|
try {
|
|
44
|
-
await
|
|
58
|
+
await execute(candidate.exe, [...candidate.args, "-c", "import sys; assert sys.version_info >= (3,10)"], true);
|
|
45
59
|
selected = candidate;
|
|
46
60
|
break;
|
|
47
61
|
} catch {
|
|
62
|
+
options.signal.throwIfAborted();
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
if (!selected) throw new Error("Install uv or real Python 3.10+; Windows Store aliases are not a Python runtime.");
|
|
51
|
-
await
|
|
52
|
-
await
|
|
66
|
+
await execute(selected.exe, [...selected.args, "-m", "venv", environment]);
|
|
67
|
+
await execute(pythonIn(environment), ["-m", "pip", "install", pinned]);
|
|
53
68
|
}
|
|
54
|
-
await
|
|
69
|
+
await execute(pythonIn(environment), ["-c", "from code_review_graph.refactor import get_refactor_edit_plan"], true);
|
|
70
|
+
options.signal.throwIfAborted();
|
|
55
71
|
await writeFile(stamp, JSON.stringify({ source: pinned }), "utf8");
|
|
56
72
|
}
|
|
57
73
|
if (process.argv[1] && resolve(fileURLToPath(import.meta.url)) === resolve(process.argv[1])) {
|
|
@@ -63,7 +79,7 @@ if (process.argv[1] && resolve(fileURLToPath(import.meta.url)) === resolve(proce
|
|
|
63
79
|
const flag = args.indexOf("--python");
|
|
64
80
|
const python = flag >= 0 ? args.splice(flag, 2)[1] : void 0;
|
|
65
81
|
try {
|
|
66
|
-
await prepare(args[0], python);
|
|
82
|
+
await prepare(args[0], python, { onProgress: (text) => process.stdout.write(text.endsWith("\n") ? text : text + "\n") });
|
|
67
83
|
} catch (error) {
|
|
68
84
|
console.error(String(error));
|
|
69
85
|
process.exitCode = 1;
|
package/dist/setup.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/setup.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\nimport { spawn } from 'node:child_process';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport const environment = join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'code-review-graph', 'engine');\nexport const pythonIn = (dir: string) => join(dir, process.platform === 'win32' ? 'Scripts/python.exe' : 'bin/python');\nasync function command(exe: string, args: string[], quiet = false): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(exe, args, { stdio:
|
|
5
|
-
"mappings": ";;;AACA,SAAS,aAAa;AACtB,SAAS,OAAO,UAAU,iBAAiB;AAC3C,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAC9B,SAAS,qBAAqB;AAEvB,IAAM,cAAc,KAAK,QAAQ,IAAI,YAAY,KAAK,QAAQ,GAAG,MAAM,GAAG,qBAAqB,QAAQ;AACvG,IAAM,WAAW,CAAC,QAAgB,KAAK,KAAK,QAAQ,aAAa,UAAU,uBAAuB,YAAY;
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\nimport { spawn } from 'node:child_process';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport const environment = join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'code-review-graph', 'engine');\nexport const pythonIn = (dir: string) => join(dir, process.platform === 'win32' ? 'Scripts/python.exe' : 'bin/python');\ninterface Preparation { signal?: AbortSignal; onProgress?: (text: string) => void }\nasync function command(exe: string, args: string[], quiet = false, options: Preparation = {}): Promise<void> {\n options.signal?.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n let log = '';\n const child = spawn(exe, args, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, signal: options.signal });\n const capture = (bytes: Buffer) => { const text = bytes.toString(); log = (log + text).slice(-16000); if (!quiet) options.onProgress?.(text); };\n child.stdout.on('data', capture); child.stderr.on('data', capture);\n child.on('error', reject); child.on('close', code => code === 0 ? resolve() : reject(new Error(`${exe} exited ${code}: ${log}`)));\n });\n}\nexport async function prepare(source?: string, python?: string, options: Preparation = {}): Promise<void> {\n options = { ...options, signal: AbortSignal.any([...(options.signal ? [options.signal] : []), AbortSignal.timeout(15 * 60 * 1000)]) };\n options.signal!.throwIfAborted();\n const execute = (exe: string, args: string[], quiet = false) => command(exe, args, quiet, options);\n const engine = JSON.parse(await readFile(new URL('../engine.json', import.meta.url), 'utf8'));\n const pinned = source ?? engine.source;\n const stamp = join(environment, 'dsh-crg-source.json');\n if (await readFile(stamp, 'utf8').then(value => JSON.parse(value).source === pinned, () => false)) {\n try { await execute(pythonIn(environment), ['-c', 'from code_review_graph.refactor import get_refactor_edit_plan'], true); options.onProgress?.('CRG engine is already prepared.'); return; } catch { options.signal!.throwIfAborted(); }\n }\n await mkdir(environment, { recursive: true });\n let uv = false;\n try { await execute('uv', ['--version'], true); uv = true; } catch { options.signal!.throwIfAborted(); }\n if (uv && !python) {\n await execute('uv', ['venv', '--allow-existing', '--python', '>=3.10', environment]);\n await execute('uv', ['pip', 'install', '--python', pythonIn(environment), pinned]);\n } else {\n let selected: { exe: string; args: string[] } | undefined;\n for (const candidate of python ? [{ exe: python, args: [] }] : [{ exe: 'python3', args: [] }, { exe: 'python', args: [] }, { exe: 'py', args: ['-3'] }]) {\n try { await execute(candidate.exe, [...candidate.args, '-c', 'import sys; assert sys.version_info >= (3,10)'], true); selected = candidate; break; } catch { options.signal!.throwIfAborted(); }\n }\n if (!selected) throw new Error('Install uv or real Python 3.10+; Windows Store aliases are not a Python runtime.');\n await execute(selected.exe, [...selected.args, '-m', 'venv', environment]);\n await execute(pythonIn(environment), ['-m', 'pip', 'install', pinned]);\n }\n await execute(pythonIn(environment), ['-c', 'from code_review_graph.refactor import get_refactor_edit_plan'], true);\n options.signal!.throwIfAborted();\n await writeFile(stamp, JSON.stringify({ source: pinned }), 'utf8');\n}\nif (process.argv[1] && resolve(fileURLToPath(import.meta.url)) === resolve(process.argv[1])) {\n if (process.argv[2] !== 'prepare') { console.error('Usage: dsh-crg prepare [engine-source] [--python executable]'); process.exitCode = 2; }\n else {\n const args = process.argv.slice(3);\n const flag = args.indexOf('--python');\n const python = flag >= 0 ? args.splice(flag, 2)[1] : undefined;\n try { await prepare(args[0], python, { onProgress: text => process.stdout.write(text.endsWith('\\n') ? text : text + '\\n') }); } catch (error) { console.error(String(error)); process.exitCode = 1; }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["resolve"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# 0.1.2
|
|
2
|
+
|
|
3
|
+
交互图谱可以直接操作,无需模型或工具参数:
|
|
4
|
+
|
|
5
|
+
- 右侧代码图谱页新增“准备引擎并生成图谱”和“更新图谱”按钮,首次主动操作自动准备隔离、固定版本的引擎。
|
|
6
|
+
- 新增真正的 DSH 用户命令 `/crg-setup`、`/crg-graph`,不接受参数、不运行模型。
|
|
7
|
+
- 支持取消、重试、解析警告和 HTML 导出;仍沿用当前会话的仓库绑定和已有后端生命周期。
|
|
8
|
+
- 中英文 README 改为界面优先,并解释高级工具选项。
|
|
9
|
+
|
|
10
|
+
桌面版通过原生插件管理器安装 `dsh-code-review-graph@0.1.2`,启用后在项目会话打开
|
|
11
|
+
右侧栏 → 新标签页 → 开始 → Code graph,点击“准备引擎并生成图谱”。首次需要联网及
|
|
12
|
+
uv 或真实 Python 3.10+;自定义引擎仍由用户自行准备。正常启动不下载依赖。
|
|
13
|
+
|
|
14
|
+
安装脚本受 pnpm 执行审批限制,因此准备入口在安装后的首次主动操作中;本版不添加
|
|
15
|
+
隐藏的 npm `postinstall`。验证范围及发行包证据见 [验证记录](validation.md)。
|
|
16
|
+
|
|
17
|
+
## English
|
|
18
|
+
|
|
19
|
+
- Generate/update the interactive graph directly from its native sidebar, without a model or JSON parameters.
|
|
20
|
+
- Add native `/crg-setup` and `/crg-graph` user commands. Both execute directly with no arguments.
|
|
21
|
+
- Prepare the isolated pinned engine on the first explicit UI action; retain cancellation, retry, parse warnings, HTML export and session-bound repository ownership.
|
|
22
|
+
- Update both READMEs with UI-first instructions and explanations of advanced options.
|
|
23
|
+
|
|
24
|
+
Install `dsh-code-review-graph@0.1.2` through the native Desktop manager, enable it,
|
|
25
|
+
then open the project session's right sidebar → New tab → Start → Code graph.
|
|
26
|
+
Click **Set up and generate graph**. First preparation needs network access and
|
|
27
|
+
uv or real Python 3.10+. Custom engines remain user-managed; ordinary startup
|
|
28
|
+
does not download dependencies. No hidden npm `postinstall` is added because
|
|
29
|
+
pnpm install scripts require execution approval. See [validation](validation.md).
|
package/docs/validation.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Validation / 验证记录
|
|
2
2
|
|
|
3
|
+
## 0.1.2 发行验证
|
|
4
|
+
|
|
5
|
+
0.1.2 的验证记录作为 [v0.1.2 发行页](https://github.com/sumingwang233/dsh-code-review-graph/releases/tag/v0.1.2)
|
|
6
|
+
附件保存,包含发行包 SHA-256、GitHub CI 结果和真实 Windows Desktop 证据。
|
|
7
|
+
|
|
8
|
+
- 两版真实 DSH 会话增加原生 `CommandRuntime.execute('/crg-graph')`,调用真实引擎,拒绝额外目录参数。
|
|
9
|
+
- 浏览器测试执行发行 Client,覆盖首次生成按钮、失败、取消、重试及原有图谱交互。
|
|
10
|
+
- 真实 Windows Desktop 0.2.0-rc.2 从空隔离引擎目录开始,通过图谱页按钮准备固定版本引擎,
|
|
11
|
+
生成图谱,再经真实工作区文件接口读取、搜索和导出。测试不再提前用 CLI 生成图谱。
|
|
12
|
+
- Windows/Linux/macOS × DSH 0.1.5-rc.2、0.2.0-rc.2 的六项 CI 覆盖会话、浏览器、CLI 生命周期及依赖准备。
|
|
13
|
+
- 无真实模型推理;其他 Desktop 平台及版本未整机实测。原安装器超时仍未复现。
|
|
14
|
+
|
|
15
|
+
Release 0.1.2 evidence is attached to its release page, including the exact tarball hash,
|
|
16
|
+
six-job compatibility CI and the actual Windows Desktop run. Native commands run
|
|
17
|
+
the real engine without a model. Desktop setup/generation is driven by the native
|
|
18
|
+
button from an empty isolated engine directory. Browser command services remain
|
|
19
|
+
fixtures; they test the published Client, including failure/cancellation/retry.
|
|
20
|
+
|
|
21
|
+
## 0.1.1 验证快照 / Previous release snapshot
|
|
22
|
+
|
|
3
23
|
Local checkpoint: **2026-10-08**, Windows, Node **24.14.1**, Python **3.11.16**.
|
|
4
24
|
CRG base **2.3.9**; exact contribution engine commit is in `engine.json`.
|
|
5
25
|
DSH packages are the real published releases **0.1.5-rc.2** and **0.2.0-rc.2**.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-code-review-graph",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Local code intelligence, review workflows and interactive graphs for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"engines": { "node": ">=22.19" },
|
|
9
9
|
"exports": { ".": "./dist/index.js", "./client": "./dist/client.js", "./package.json": "./package.json" },
|
|
10
10
|
"bin": { "dsh-crg": "./dist/setup.js" },
|
|
11
|
-
"files": ["dist", "cordis.patch.yml", "engine.json", "capabilities.json", "skills", "LICENSE", "NOTICE", "README.md", "README.en.md", "docs/capabilities.md", "docs/validation.md", "docs/release-0.1.
|
|
11
|
+
"files": ["dist", "cordis.patch.yml", "engine.json", "capabilities.json", "skills", "LICENSE", "NOTICE", "README.md", "README.en.md", "docs/capabilities.md", "docs/validation.md", "docs/release-0.1.2.md"],
|
|
12
12
|
"dsh": { "bundle": { "patch": "./cordis.patch.yml" }, "client": { "platform": "web", "inject": ["@deepseek-ai/dsh-api-workspace-files", "@deepseek-ai/dsh-client-ui-sidebar-right", "@deepseek-ai/dsh-api-remotes"] } },
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "node scripts/build.mjs",
|
package/docs/release-0.1.1.md
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# 0.1.1
|
|
2
|
-
|
|
3
|
-
修复 DSH Web/桌面客户端的原生加载和图谱侧栏显示:
|
|
4
|
-
|
|
5
|
-
- Client 发行文件改用 DSH 官方 closure-factory 格式,解决 `Cannot use import statement outside a module`。
|
|
6
|
-
- 侧栏正文按插件 provider ID 注册,解决打开图谱后显示“这类内容还没有可用的查看方式”。
|
|
7
|
-
- 浏览器回归直接执行发行文件;补充真实 Windows Desktop 0.2.0-rc.2 的隔离安装、启用、图谱读取、搜索、HTML 导出和卸载/重装验证。
|
|
8
|
-
|
|
9
|
-
桌面安装 `dsh-code-review-graph@0.1.1`,完成后点击“立即启用”。已有旧版先通过
|
|
10
|
-
原生插件管理器卸载;安装状态尚未确认时先核对状态。
|
|
11
|
-
|
|
12
|
-
用户报告的 pnpm 十分钟无输出超时未能复现。相同旧包及原有依赖组合均可正常安装;
|
|
13
|
-
本次修复不代表该安装器超时已解决。其他桌面平台/版本未整机实测,详细范围见
|
|
14
|
-
[验证记录](validation.md)。没有运行模型推理,也未修改用户的 DSH 配置。
|
|
15
|
-
|
|
16
|
-
## English
|
|
17
|
-
|
|
18
|
-
- Emit the Client in DSH's native closure-factory format, fixing `Cannot use import statement outside a module` in the actual loader.
|
|
19
|
-
- Register the sidebar body under the plugin provider ID, fixing the unavailable-view fallback when opening a graph.
|
|
20
|
-
- Execute the published Client in browser regressions; add isolated installation, enablement, native graph reading/search/HTML export, removal and reinstallation checks using the actual Windows Desktop 0.2.0-rc.2 application.
|
|
21
|
-
|
|
22
|
-
Install `dsh-code-review-graph@0.1.1` in the native Desktop plugin manager, then
|
|
23
|
-
choose **Enable now**. Remove an existing old version through that manager first;
|
|
24
|
-
reconcile an unconfirmed installation before proceeding.
|
|
25
|
-
|
|
26
|
-
The reported ten-minute pnpm no-output timeout did not reproduce with the same
|
|
27
|
-
old package and dependency combination. This release does not claim to resolve
|
|
28
|
-
that installer timeout. Other Desktop platforms/releases have not been tested as
|
|
29
|
-
complete applications. See [validation](validation.md) for scope. No model
|
|
30
|
-
inference or changes to the user's DSH configuration were involved.
|