codebase-onboarder 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/cli/chat/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport { AGENT_MODES, type AgentMode, type AgentRequest, type AgentEvent, type AgentResult } from '../agent/contracts.js';\nimport { runAgent, savedRun, type RunnerOptions } from '../agent/runner.js';\nimport { agentHome } from '../agent/config.js';\nimport { redact, terminalText } from '../agent/process.js';\nimport { ChatStore, newChat, historySummary, type ChatRecord, type ChatSettings } from './store.js';\nimport { slashInput, chatHelp, BROWSE_COMMANDS } from './commands.js';\nimport { ChatSources, isRemoteSource } from './source.js';\n\nexport type ChatOutput =\n | { type: 'message'; text: string }\n | { type: 'start'; prompt: string; mode: AgentMode }\n | { type: 'event'; event: AgentEvent }\n | { type: 'end'; result: AgentResult; elapsed: number }\n | { type: 'clear' | 'exit' };\nexport interface ChatPorts {\n output: (event: ChatOutput) => void;\n run?: typeof runAgent;\n browse?: (name: string, args: string[], root: string, signal: AbortSignal) => Promise<string>;\n utility?: (name: ChatUtility, signal: AbortSignal) => Promise<string>;\n chooseModel?: (configure: boolean, signal: AbortSignal) => Promise<boolean>;\n store?: ChatStore; runner?: Omit<RunnerOptions, 'onEvent' | 'signal'>;\n sources?: ChatSources;\n}\nexport type ChatUtility = 'doctor' | 'setup' | 'model' | 'tools' | 'runs';\nexport class ChatController {\n record: ChatRecord;\n lastResult: AgentResult | null = null;\n busy = false;\n closed = false;\n private abort: AbortController | null = null;\n private paste: string[] | null = null;\n private store: ChatStore;\n private sources: ChatSources;\n constructor(settings: ChatSettings, private ports: ChatPorts) {\n this.record = newChat(settings);\n this.store = ports.store || new ChatStore(ports.runner?.home || agentHome(ports.runner?.env), ports.runner?.env);\n this.sources = ports.sources || new ChatSources(this.store.home, { env: ports.runner?.env });\n }\n get settings() { return this.record.settings; }\n get pasting() { return this.paste !== null; }\n get workspace() { return this.lastResult?.workspace || this.settings.root; }\n private say(text: string) { this.ports.output({ type: 'message', text: terminalText(redact(text, this.ports.runner?.env)) }); }\n cancel() { this.abort?.abort(); }\n close() { this.closed = true; this.cancel(); this.paste = null; this.ports.output({ type: 'exit' }); }\n private async persist() {\n this.record.updatedAt = new Date().toISOString();\n try { await this.store.save(this.record); return true; }\n catch (e) { this.say(`Could not save this conversation: ${e instanceof Error ? e.message : e}. The agent run remains in agent runs.`); return false; }\n }\n async save() { return this.persist(); }\n private resetContext() { this.record.lastRun = null; this.lastResult = null; }\n status(): string {\n const s = this.settings;\n return [...(s.sourceUrl ? [`GitHub: ${s.sourceUrl}`] : []), `Repository: ${s.root}`, `Workflow: ${s.mode}${s.pr ? ' · PR #' + s.pr : ''}${s.issue ? ' · issue #' + s.issue : ''}`,\n `Model: ${s.model || 'Hermes profile default'}${s.provider ? ' (' + s.provider + ')' : ''}`,\n `Permissions: files ${['implement', 'pr'].includes(s.mode) ? 'isolated workspace' : 'read only'} · checks ${s.checks ? 'on' : 'off'} · GitHub writes ${s.github ? 'on' : 'off'}`,\n `Limits: ${s.timeout}s · ${s.maxTurns} agent turns`, `Conversation: ${this.record.id}`, `Session run: ${this.record.lastRun || 'new'}`,\n `Workspace: ${this.workspace}`, ...(this.lastResult?.branch ? [`Branch: ${this.lastResult.branch}`] : [])].join('\\n');\n }\n async accept(input: string): Promise<void> {\n if (this.closed) return;\n const trimmed = input.trim(), command = slashInput(trimmed);\n if (command?.name === 'exit' || command?.name === 'quit') { this.close(); return; }\n if (command?.name === 'cancel') { if (this.busy) { this.cancel(); this.say('Cancelling…'); } else this.say('No active task.'); return; }\n if (this.busy) { this.say('A task is running. Use /cancel or Ctrl-C before starting another.'); return; }\n if (this.paste !== null) {\n if (trimmed === '/discard') { this.paste = null; this.say('Multiline message discarded.'); return; }\n if (trimmed === '/send') { const body = this.paste.join('\\n'); this.paste = null; if (body.trim()) await this.submit(body); return; }\n if (this.paste.join('\\n').length + input.length + 1 > 16000) { this.say('Message limit is 16000 characters. /send or /discard this message.'); return; }\n this.paste.push(input); return;\n }\n if (!trimmed) return;\n this.busy = true; this.abort = new AbortController();\n try {\n if (!command) {\n if (trimmed.startsWith('/')) throw new Error('Invalid slash command. Use /help.');\n const first = trimmed.split(/\\s+/)[0]!;\n if (isRemoteSource(first)) {\n await this.openSource(first);\n const question = trimmed.slice(first.length).trim(); if (question) await this.run(question);\n return;\n }\n await this.run(trimmed); return;\n }\n const { name, args, body } = command;\n if (!name || name === 'help') { this.say(chatHelp(args[0])); return; }\n if (name === 'status') { this.say(this.status()); return; }\n if (name === 'skills') { this.say('Built-in workflow skills\\n' + ['ask — repository Q&A', 'review — local and PR review', 'triage — investigate issues', 'implement — isolated code changes', 'pr — prepare or publish a draft PR', 'github — issues, discussions, labels, and CI'].map(s => ' /' + s).join('\\n')); return; }\n if (name === 'tools' || name === 'runs') { this.say(await this.utility(name)); return; }\n if (name === 'run') {\n const saved = await savedRun(args[0] || '', this.store.home);\n if (saved.manifest.sourceRoot !== this.settings.root) throw new Error('This run belongs to another repository. Switch with /repo first.');\n this.say(`Run: ${saved.manifest.id} · ${saved.result?.status || 'unfinished'}\\nWorkspace: ${saved.manifest.root}\\n\\n${saved.result?.answer || 'No saved final answer.'}`); return;\n }\n if (name === 'export') { this.say('Conversation exported: ' + await this.store.export(this.record)); return; }\n if (name === 'send' || name === 'discard') { this.say('Use /paste first to compose a multiline message.'); return; }\n if (name === 'clear') { this.ports.output({ type: 'clear' }); return; }\n if (name === 'paste') { this.paste = []; this.say('Multiline input. /send submits; /discard cancels.'); return; }\n if (name === 'new') { this.record = newChat({ ...this.settings, pr: undefined, issue: undefined }); this.lastResult = null; this.say('New conversation. ' + this.record.id); await this.persist(); return; }\n if (name === 'history') { this.say(historySummary(await this.store.list(this.settings.root))); return; }\n if (name === 'resume') { await this.resume(args[0] || ''); return; }\n if (name === 'repo' || name === 'clone') {\n if (!body) { this.say(name === 'clone' ? 'Usage: /clone <GitHub URL>' : (this.settings.sourceUrl || this.settings.root)); return; }\n if (name === 'clone' && (args.length !== 1 || !isRemoteSource(args[0]!))) throw new Error('Usage: /clone <GitHub URL>');\n await this.openSource(args.join(' ')); return;\n }\n if (name === 'pull') {\n if (body) throw new Error('Usage: /pull');\n if (this.lastResult?.branch) throw new Error('Use /new before pulling the source checkout. Your implementation workspace remains saved in agent runs.');\n this.say(await this.sources.pull(this.settings.root, this.abort.signal, text => this.say(text)));\n this.resetContext(); await this.persist(); this.say('Source refreshed. The next question starts a new agent session.'); return;\n }\n if (name === 'mode') {\n if (!body) { this.say(`Workflow: ${this.settings.mode}. Choose ${AGENT_MODES.join(', ')}.`); return; }\n if (!AGENT_MODES.includes(body as AgentMode)) throw new Error('Usage: /mode ' + AGENT_MODES.join('|'));\n if (body !== this.settings.mode) { this.settings.mode = body as AgentMode; this.settings.pr = undefined; this.settings.issue = undefined; this.resetContext(); }\n this.say('Workflow: ' + body + '. Following messages use this workflow.'); await this.persist(); return;\n }\n if (name === 'permissions') {\n if (!body) { this.say(`Checks: ${this.settings.checks ? 'on' : 'off'} · GitHub writes: ${this.settings.github ? 'on' : 'off'}\\n/permissions checks on|off · /permissions github on|off`); return; }\n if (args.length !== 2 || !['checks', 'github'].includes(args[0]!) || !['on', 'off'].includes(args[1]!)) throw new Error('Usage: /permissions checks|github on|off');\n const key = args[0] as 'checks' | 'github', value = args[1] === 'on';\n if (this.settings[key] !== value) { this.settings[key] = value; this.resetContext(); }\n this.say(`${key === 'checks' ? 'Repository test execution' : 'GitHub writes'} ${value ? 'enabled' : 'disabled'}.`); await this.persist(); return;\n }\n if (name === 'model') {\n if (args.length > 2 || args.some(arg => arg.length > 512)) throw new Error('Usage: /model <name> [provider] (maximum 512 characters each)');\n if (!body || body === 'configure') {\n const changed = this.ports.chooseModel ? await this.ports.chooseModel(body === 'configure', this.abort.signal) : (this.say(await this.utility('model')), true);\n if (!changed) { this.say('Model selection closed. Current settings kept.'); return; }\n this.settings.model = undefined; this.settings.provider = undefined;\n }\n else { this.settings.model = args[0] === 'default' ? undefined : args[0]; this.settings.provider = args[0] === 'default' ? undefined : args[1]; }\n this.resetContext(); this.say('Model: ' + (this.settings.model || 'Hermes profile default')); await this.persist(); return;\n }\n if (name === 'limits') {\n if (!body) { this.say(`${this.settings.timeout}s · ${this.settings.maxTurns} agent turns`); return; }\n const seconds = Number(args[0]), turns = args[1] === undefined ? this.settings.maxTurns : Number(args[1]);\n if (args.length > 2 || !Number.isInteger(seconds) || seconds < 15 || seconds > 3600 || !Number.isInteger(turns) || turns < 1 || turns > 100) throw new Error('Usage: /limits <15–3600 seconds> [1–100 turns]');\n this.settings.timeout = seconds; this.settings.maxTurns = turns; await this.persist(); this.say(`${seconds}s · ${turns} agent turns`); return;\n }\n if (name === 'setup' || name === 'doctor') { this.say(await this.utility(name)); return; }\n if (BROWSE_COMMANDS.includes(name as typeof BROWSE_COMMANDS[number])) {\n if (name === 'deep' && !this.settings.checks) throw new Error('Enable /permissions checks on before running an external analyzer.');\n if (!this.ports.browse) throw new Error('Repository browsing is unavailable.');\n this.say(await this.ports.browse(name, args, this.workspace, this.abort.signal)); return;\n }\n if (AGENT_MODES.includes(name as AgentMode)) {\n const mode = name as AgentMode;\n let task = body, pr: number | undefined, issue: number | undefined;\n if (['review', 'triage'].includes(mode) && /^\\d+(?:\\s|$)/.test(body)) {\n const match = /^(\\d+)(?:\\s+([\\s\\S]*))?$/.exec(body)!;\n const id = Number(match[1]); if (!Number.isSafeInteger(id) || id < 1) throw new Error('Use a positive PR or issue number.');\n if (mode === 'review') pr = id; else issue = id;\n task = match[2] || '';\n }\n task ||= mode === 'review' ? `Review ${pr ? 'PR #' + pr : 'local changes'} for actionable correctness and security issues.` : mode === 'triage' ? `Investigate ${issue ? 'issue #' + issue : 'open issues'} and propose a prioritized plan.` : '';\n if (!task) throw new Error(`Usage: /${mode} <task>`);\n if (mode !== this.settings.mode || pr !== this.settings.pr || issue !== this.settings.issue) this.resetContext();\n Object.assign(this.settings, { mode, pr, issue }); await this.run(task); return;\n }\n throw new Error(`Unknown command /${name}. Use /help; Tab completes commands.`);\n } catch (e) { this.say(e instanceof Error ? e.message : String(e)); }\n finally { this.busy = false; this.abort = null; }\n }\n private async submit(task: string) {\n this.busy = true; this.abort = new AbortController();\n try { await this.run(task); } catch (e) { this.say(e instanceof Error ? e.message : String(e)); }\n finally { this.busy = false; this.abort = null; }\n }\n private async utility(name: ChatUtility) {\n if (!this.ports.utility) throw new Error(`Use onboarder agent ${name} in a terminal.`);\n return this.ports.utility(name, this.abort!.signal);\n }\n private async openSource(target: string) {\n const source = await this.sources.open(target, this.settings.root, this.abort!.signal, text => this.say(text));\n this.abort!.signal.throwIfAborted();\n await this.persist();\n this.abort!.signal.throwIfAborted();\n this.record = newChat({ ...this.settings, root: source.root, sourceUrl: source.sourceUrl, pr: undefined, issue: undefined });\n this.lastResult = null;\n this.say(`Repository: ${source.sourceUrl || source.root}\\nNew conversation. Type your question.`);\n await this.persist();\n }\n async resume(id: string) {\n const record = await this.store.load(id);\n if (record.settings.root !== this.settings.root) throw new Error('This conversation belongs to another repository. Switch with /repo first.');\n let result: AgentResult | null = null;\n if (record.lastRun) {\n const saved = await savedRun(record.lastRun, this.store.home);\n if (saved.manifest.sourceRoot !== this.settings.root || saved.manifest.mode !== record.settings.mode || !saved.result?.sessionId) throw new Error('This conversation has no resumable Hermes session. Use /new.');\n await fs.access(saved.manifest.root);\n if (this.settings.checks && !saved.manifest.permissions.checks || this.settings.github && !saved.manifest.permissions.github) throw new Error('Resume cannot expand permissions. Turn them off first or use /new.');\n result = saved.result;\n }\n // Restore the model and task target, while retaining the permissions chosen in this application.\n const changed = record.settings.checks !== this.settings.checks || record.settings.github !== this.settings.github;\n record.settings.checks = this.settings.checks; record.settings.github = this.settings.github;\n if (changed) record.lastRun = null;\n this.record = record; this.lastResult = changed ? null : result;\n this.say(`Resumed conversation ${id}.\\n${this.status()}${changed ? '\\nPermissions changed; the next task starts a new Hermes session.' : ''}`);\n const last = record.turns.at(-1); if (last) this.say('Last answer\\n' + last.answer);\n }\n private async run(task: string) {\n if (!task.trim() || task.length > 16000) throw new Error('Messages must contain 1–16000 characters.');\n const s = this.settings, start = Date.now();\n const request: AgentRequest = { root: s.root, mode: s.mode, task, model: s.model, provider: s.provider, pr: s.pr, issue: s.issue,\n base: s.base, allowChecks: s.checks, allowGithubWrites: s.github, timeoutSeconds: s.timeout, maxTurns: s.maxTurns,\n ...(this.record.lastRun ? { resume: this.record.lastRun } : {}) };\n this.ports.output({ type: 'start', prompt: terminalText(redact(task, this.ports.runner?.env)), mode: s.mode });\n let result: Awaited<ReturnType<typeof runAgent>>, sessionStarted = false;\n try {\n result = await (this.ports.run || runAgent)(request, { ...this.ports.runner, signal: this.abort!.signal,\n onEvent: event => {\n if (['text', 'tool_use', 'tool_result'].includes(event.type)) sessionStarted = true;\n this.ports.output({ type: 'event', event });\n } });\n } catch (e) {\n // Validation can reject before a run exists. Finish the UI without inventing a saved run.\n this.say('Task could not start: ' + (e instanceof Error ? e.message : String(e))); return;\n }\n if ('dryRun' in result) throw new Error('Chat requires a live agent result.');\n this.lastResult = result;\n // Failed startup can emit an ID without creating a usable Hermes session.\n // Keep the previous working session on failure; new failures start fresh.\n if (result.sessionId && (result.status === 'completed' || result.status === 'cancelled' && sessionStarted)) this.record.lastRun = result.id;\n this.record.turns.push({ at: new Date().toISOString(), prompt: task, answer: result.answer, run: result.id, status: result.status });\n this.record.turns = this.record.turns.slice(-100);\n this.ports.output({ type: 'end', result, elapsed: Date.now() - start });\n await this.persist();\n }\n}\n"]}
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/cli/chat/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport { AGENT_MODES, type AgentMode, type AgentRequest, type AgentEvent, type AgentResult } from '../agent/contracts.js';\nimport { runAgent, savedRun, type RunnerOptions } from '../agent/runner.js';\nimport { agentHome } from '../agent/config.js';\nimport { redact, terminalText } from '../agent/process.js';\nimport { ChatStore, newChat, historySummary, type ChatRecord, type ChatSettings } from './store.js';\nimport { slashInput, chatHelp, BROWSE_COMMANDS } from './commands.js';\nimport { ChatSources, isRemoteSource } from './source.js';\n\nexport type ChatOutput =\n | { type: 'message'; text: string }\n | { type: 'start'; prompt: string; mode: AgentMode }\n | { type: 'event'; event: AgentEvent }\n | { type: 'end'; result: AgentResult; elapsed: number }\n | { type: 'clear' | 'exit' };\nexport interface ChatPorts {\n output: (event: ChatOutput) => void;\n run?: typeof runAgent;\n browse?: (name: string, args: string[], root: string, signal: AbortSignal) => Promise<string>;\n utility?: (name: ChatUtility, signal: AbortSignal) => Promise<string>;\n chooseModel?: (configure: boolean, signal: AbortSignal) => Promise<boolean>;\n analysis?: (name: string, args: string[], root: string, signal: AbortSignal, checks: boolean) => Promise<{ text: string; explain?: string }>;\n store?: ChatStore; runner?: Omit<RunnerOptions, 'onEvent' | 'signal'>;\n sources?: ChatSources;\n}\nexport type ChatUtility = 'doctor' | 'setup' | 'model' | 'tools' | 'runs';\nexport class ChatController {\n record: ChatRecord;\n lastResult: AgentResult | null = null;\n busy = false;\n closed = false;\n private abort: AbortController | null = null;\n private paste: string[] | null = null;\n private store: ChatStore;\n private sources: ChatSources;\n constructor(settings: ChatSettings, private ports: ChatPorts) {\n this.record = newChat(settings);\n this.store = ports.store || new ChatStore(ports.runner?.home || agentHome(ports.runner?.env), ports.runner?.env);\n this.sources = ports.sources || new ChatSources(this.store.home, { env: ports.runner?.env });\n }\n get settings() { return this.record.settings; }\n get pasting() { return this.paste !== null; }\n get workspace() { return this.lastResult?.workspace || this.settings.root; }\n private say(text: string) { this.ports.output({ type: 'message', text: terminalText(redact(text, this.ports.runner?.env)) }); }\n cancel() { this.abort?.abort(); }\n close() { this.closed = true; this.cancel(); this.paste = null; this.ports.output({ type: 'exit' }); }\n private async persist() {\n this.record.updatedAt = new Date().toISOString();\n try { await this.store.save(this.record); return true; }\n catch (e) { this.say(`Could not save this conversation: ${e instanceof Error ? e.message : e}. The agent run remains in agent runs.`); return false; }\n }\n async save() { return this.persist(); }\n private resetContext() { this.record.lastRun = null; this.lastResult = null; }\n status(): string {\n const s = this.settings;\n return [...(s.sourceUrl ? [`GitHub: ${s.sourceUrl}`] : []), `Repository: ${s.root}`, `Workflow: ${s.mode}${s.pr ? ' · PR #' + s.pr : ''}${s.issue ? ' · issue #' + s.issue : ''}`,\n `Model: ${s.model || 'Hermes profile default'}${s.provider ? ' (' + s.provider + ')' : ''}`,\n `Permissions: files ${['implement', 'pr'].includes(s.mode) ? 'isolated workspace' : 'read only'} · checks ${s.checks ? 'on' : 'off'} · GitHub writes ${s.github ? 'on' : 'off'}`,\n `Limits: ${s.timeout}s · ${s.maxTurns} agent turns`, `Conversation: ${this.record.id}`, `Session run: ${this.record.lastRun || 'new'}`,\n `Workspace: ${this.workspace}`, ...(this.lastResult?.branch ? [`Branch: ${this.lastResult.branch}`] : [])].join('\\n');\n }\n async accept(input: string): Promise<void> {\n if (this.closed) return;\n const trimmed = input.trim(), command = slashInput(trimmed);\n if (command?.name === 'exit' || command?.name === 'quit') { this.close(); return; }\n if (command?.name === 'cancel') { if (this.busy) { this.cancel(); this.say('Cancelling…'); } else this.say('No active task.'); return; }\n if (this.busy) { this.say('A task is running. Use /cancel or Ctrl-C before starting another.'); return; }\n if (this.paste !== null) {\n if (trimmed === '/discard') { this.paste = null; this.say('Multiline message discarded.'); return; }\n if (trimmed === '/send') { const body = this.paste.join('\\n'); this.paste = null; if (body.trim()) await this.submit(body); return; }\n if (this.paste.join('\\n').length + input.length + 1 > 16000) { this.say('Message limit is 16000 characters. /send or /discard this message.'); return; }\n this.paste.push(input); return;\n }\n if (!trimmed) return;\n this.busy = true; this.abort = new AbortController();\n try {\n if (!command) {\n if (trimmed.startsWith('/')) throw new Error('Invalid slash command. Use /help.');\n const first = trimmed.split(/\\s+/)[0]!;\n if (isRemoteSource(first)) {\n await this.openSource(first);\n const question = trimmed.slice(first.length).trim(); if (question) await this.run(question);\n return;\n }\n await this.run(trimmed); return;\n }\n const { name, args, body } = command;\n if (!name || name === 'help') { this.say(chatHelp(args[0])); return; }\n if (name === 'status') { this.say(this.status()); return; }\n if (name === 'skills') { this.say('Built-in workflow skills\\n' + ['ask — repository Q&A', 'review — local and PR review', 'triage — investigate issues', 'implement — isolated code changes', 'pr — prepare or publish a draft PR', 'github — issues, discussions, labels, and CI'].map(s => ' /' + s).join('\\n')); return; }\n if (name === 'tools' || name === 'runs') { this.say(await this.utility(name)); return; }\n if (name === 'run') {\n const saved = await savedRun(args[0] || '', this.store.home);\n if (saved.manifest.sourceRoot !== this.settings.root) throw new Error('This run belongs to another repository. Switch with /repo first.');\n this.say(`Run: ${saved.manifest.id} · ${saved.result?.status || 'unfinished'}\\nWorkspace: ${saved.manifest.root}\\n\\n${saved.result?.answer || 'No saved final answer.'}`); return;\n }\n if (name === 'export') { this.say('Conversation exported: ' + await this.store.export(this.record)); return; }\n if (name === 'send' || name === 'discard') { this.say('Use /paste first to compose a multiline message.'); return; }\n if (name === 'clear') { this.ports.output({ type: 'clear' }); return; }\n if (name === 'paste') { this.paste = []; this.say('Multiline input. /send submits; /discard cancels.'); return; }\n if (name === 'new') { this.record = newChat({ ...this.settings, pr: undefined, issue: undefined }); this.lastResult = null; this.say('New conversation. ' + this.record.id); await this.persist(); return; }\n if (name === 'history') { this.say(historySummary(await this.store.list(this.settings.root))); return; }\n if (name === 'resume') { await this.resume(args[0] || ''); return; }\n if (name === 'repo' || name === 'clone') {\n if (!body) { this.say(name === 'clone' ? 'Usage: /clone <GitHub URL>' : (this.settings.sourceUrl || this.settings.root)); return; }\n if (name === 'clone' && (args.length !== 1 || !isRemoteSource(args[0]!))) throw new Error('Usage: /clone <GitHub URL>');\n await this.openSource(args.join(' ')); return;\n }\n if (name === 'pull') {\n if (body) throw new Error('Usage: /pull');\n if (this.lastResult?.branch) throw new Error('Use /new before pulling the source checkout. Your implementation workspace remains saved in agent runs.');\n this.say(await this.sources.pull(this.settings.root, this.abort.signal, text => this.say(text)));\n this.resetContext(); await this.persist(); this.say('Source refreshed. The next question starts a new agent session.'); return;\n }\n if (name === 'mode') {\n if (!body) { this.say(`Workflow: ${this.settings.mode}. Choose ${AGENT_MODES.join(', ')}.`); return; }\n if (!AGENT_MODES.includes(body as AgentMode)) throw new Error('Usage: /mode ' + AGENT_MODES.join('|'));\n if (body !== this.settings.mode) { this.settings.mode = body as AgentMode; this.settings.pr = undefined; this.settings.issue = undefined; this.resetContext(); }\n this.say('Workflow: ' + body + '. Following messages use this workflow.'); await this.persist(); return;\n }\n if (name === 'permissions') {\n if (!body) { this.say(`Checks: ${this.settings.checks ? 'on' : 'off'} · GitHub writes: ${this.settings.github ? 'on' : 'off'}\\n/permissions checks on|off · /permissions github on|off`); return; }\n if (args.length !== 2 || !['checks', 'github'].includes(args[0]!) || !['on', 'off'].includes(args[1]!)) throw new Error('Usage: /permissions checks|github on|off');\n const key = args[0] as 'checks' | 'github', value = args[1] === 'on';\n if (this.settings[key] !== value) { this.settings[key] = value; this.resetContext(); }\n this.say(`${key === 'checks' ? 'Repository test execution' : 'GitHub writes'} ${value ? 'enabled' : 'disabled'}.`); await this.persist(); return;\n }\n if (name === 'model') {\n if (args.length > 2 || args.some(arg => arg.length > 512)) throw new Error('Usage: /model <name> [provider] (maximum 512 characters each)');\n if (!body || body === 'configure') {\n const changed = this.ports.chooseModel ? await this.ports.chooseModel(body === 'configure', this.abort.signal) : (this.say(await this.utility('model')), true);\n if (!changed) { this.say('Model selection closed. Current settings kept.'); return; }\n this.settings.model = undefined; this.settings.provider = undefined;\n }\n else { this.settings.model = args[0] === 'default' ? undefined : args[0]; this.settings.provider = args[0] === 'default' ? undefined : args[1]; }\n this.resetContext(); this.say('Model: ' + (this.settings.model || 'Hermes profile default')); await this.persist(); return;\n }\n if (name === 'limits') {\n if (!body) { this.say(`${this.settings.timeout}s · ${this.settings.maxTurns} agent turns`); return; }\n const seconds = Number(args[0]), turns = args[1] === undefined ? this.settings.maxTurns : Number(args[1]);\n if (args.length > 2 || !Number.isInteger(seconds) || seconds < 15 || seconds > 3600 || !Number.isInteger(turns) || turns < 1 || turns > 100) throw new Error('Usage: /limits <15–3600 seconds> [1–100 turns]');\n this.settings.timeout = seconds; this.settings.maxTurns = turns; await this.persist(); this.say(`${seconds}s · ${turns} agent turns`); return;\n }\n if (name === 'setup' || name === 'doctor') { this.say(await this.utility(name)); return; }\n if ((name === 'deep' || name === 'engines') && this.ports.analysis) {\n const result = await this.ports.analysis(name, args, this.workspace, this.abort.signal, this.settings.checks);\n this.abort.signal.throwIfAborted();\n if (result.explain) await this.run(result.explain, result.text); else this.say(result.text);\n return;\n }\n if (BROWSE_COMMANDS.includes(name as typeof BROWSE_COMMANDS[number])) {\n if (name === 'deep' && !this.settings.checks) throw new Error('Enable /permissions checks on before running an external analyzer.');\n if (!this.ports.browse) throw new Error('Repository browsing is unavailable.');\n this.say(await this.ports.browse(name, args, this.workspace, this.abort.signal)); return;\n }\n if (AGENT_MODES.includes(name as AgentMode)) {\n const mode = name as AgentMode;\n let task = body, pr: number | undefined, issue: number | undefined;\n if (['review', 'triage'].includes(mode) && /^\\d+(?:\\s|$)/.test(body)) {\n const match = /^(\\d+)(?:\\s+([\\s\\S]*))?$/.exec(body)!;\n const id = Number(match[1]); if (!Number.isSafeInteger(id) || id < 1) throw new Error('Use a positive PR or issue number.');\n if (mode === 'review') pr = id; else issue = id;\n task = match[2] || '';\n }\n task ||= mode === 'review' ? `Review ${pr ? 'PR #' + pr : 'local changes'} for actionable correctness and security issues.` : mode === 'triage' ? `Investigate ${issue ? 'issue #' + issue : 'open issues'} and propose a prioritized plan.` : '';\n if (!task) throw new Error(`Usage: /${mode} <task>`);\n if (mode !== this.settings.mode || pr !== this.settings.pr || issue !== this.settings.issue) this.resetContext();\n Object.assign(this.settings, { mode, pr, issue }); await this.run(task); return;\n }\n throw new Error(`Unknown command /${name}. Use /help; Tab completes commands.`);\n } catch (e) { this.say(this.abort?.signal.aborted ? 'Task cancelled.' : e instanceof Error ? e.message : String(e)); }\n finally { this.busy = false; this.abort = null; }\n }\n private async submit(task: string) {\n this.busy = true; this.abort = new AbortController();\n try { await this.run(task); } catch (e) { this.say(e instanceof Error ? e.message : String(e)); }\n finally { this.busy = false; this.abort = null; }\n }\n private async utility(name: ChatUtility) {\n if (!this.ports.utility) throw new Error(`Use onboarder agent ${name} in a terminal.`);\n return this.ports.utility(name, this.abort!.signal);\n }\n private async openSource(target: string) {\n const source = await this.sources.open(target, this.settings.root, this.abort!.signal, text => this.say(text));\n this.abort!.signal.throwIfAborted();\n await this.persist();\n this.abort!.signal.throwIfAborted();\n this.record = newChat({ ...this.settings, root: source.root, sourceUrl: source.sourceUrl, pr: undefined, issue: undefined });\n this.lastResult = null;\n this.say(`Repository: ${source.sourceUrl || source.root}\\nNew conversation. Type your question.`);\n await this.persist();\n }\n async resume(id: string) {\n const record = await this.store.load(id);\n if (record.settings.root !== this.settings.root) throw new Error('This conversation belongs to another repository. Switch with /repo first.');\n let result: AgentResult | null = null;\n if (record.lastRun) {\n const saved = await savedRun(record.lastRun, this.store.home);\n if (saved.manifest.sourceRoot !== this.settings.root || saved.manifest.mode !== record.settings.mode || !saved.result?.sessionId) throw new Error('This conversation has no resumable Hermes session. Use /new.');\n await fs.access(saved.manifest.root);\n if (this.settings.checks && !saved.manifest.permissions.checks || this.settings.github && !saved.manifest.permissions.github) throw new Error('Resume cannot expand permissions. Turn them off first or use /new.');\n result = saved.result;\n }\n // Restore the model and task target, while retaining the permissions chosen in this application.\n const changed = record.settings.checks !== this.settings.checks || record.settings.github !== this.settings.github;\n record.settings.checks = this.settings.checks; record.settings.github = this.settings.github;\n if (changed) record.lastRun = null;\n this.record = record; this.lastResult = changed ? null : result;\n this.say(`Resumed conversation ${id}.\\n${this.status()}${changed ? '\\nPermissions changed; the next task starts a new Hermes session.' : ''}`);\n const last = record.turns.at(-1); if (last) this.say('Last answer\\n' + last.answer);\n }\n private async run(task: string, displayPrompt = task) {\n if (!task.trim() || task.length > 16000) throw new Error('Messages must contain 1–16000 characters.');\n const s = this.settings, start = Date.now();\n const request: AgentRequest = { root: s.root, mode: s.mode, task, model: s.model, provider: s.provider, pr: s.pr, issue: s.issue,\n base: s.base, allowChecks: s.checks, allowGithubWrites: s.github, timeoutSeconds: s.timeout, maxTurns: s.maxTurns,\n ...(this.record.lastRun ? { resume: this.record.lastRun } : {}) };\n this.ports.output({ type: 'start', prompt: terminalText(redact(displayPrompt, this.ports.runner?.env)), mode: s.mode });\n let result: Awaited<ReturnType<typeof runAgent>>, sessionStarted = false;\n try {\n result = await (this.ports.run || runAgent)(request, { ...this.ports.runner, signal: this.abort!.signal,\n onEvent: event => {\n if (['text', 'tool_use', 'tool_result'].includes(event.type)) sessionStarted = true;\n this.ports.output({ type: 'event', event });\n } });\n } catch (e) {\n // Validation can reject before a run exists. Finish the UI without inventing a saved run.\n this.say('Task could not start: ' + (e instanceof Error ? e.message : String(e))); return;\n }\n if ('dryRun' in result) throw new Error('Chat requires a live agent result.');\n this.lastResult = result;\n // Failed startup can emit an ID without creating a usable Hermes session.\n // Keep the previous working session on failure; new failures start fresh.\n if (result.sessionId && (result.status === 'completed' || result.status === 'cancelled' && sessionStarted)) this.record.lastRun = result.id;\n this.record.turns.push({ at: new Date().toISOString(), prompt: displayPrompt, answer: result.answer, run: result.id, status: result.status });\n this.record.turns = this.record.turns.slice(-100);\n this.ports.output({ type: 'end', result, elapsed: Date.now() - start });\n await this.persist();\n }\n}\n"]}
@@ -68,6 +68,7 @@ interface ToolStatus {
68
68
  available: boolean;
69
69
  how?: string | null;
70
70
  reason?: string | null;
71
+ purpose?: string;
71
72
  }
72
73
  interface Finding {
73
74
  path?: string;
@@ -118,6 +118,8 @@ export function formatEngines(status) {
118
118
  for (const [id, tool] of Object.entries(status)) {
119
119
  const state = !tool.available ? 'missing' : tool.how === 'path' ? 'installed' : 'runnable';
120
120
  lines.push(` ${state} ${tool.label} (${id}) · ${tool.kind}`);
121
+ if (tool.purpose)
122
+ lines.push(` ${tool.purpose}`);
121
123
  lines.push(` ${tool.available ? tool.how || 'available' : tool.reason || 'Not installed'}`);
122
124
  }
123
125
  lines.push('', ' Run: deep <engine> or deep all');
@@ -167,6 +169,8 @@ export function formatDeepAnalysis(report) {
167
169
  for (const finding of report.findings.slice(0, 40)) {
168
170
  const place = finding.path || finding.file || '(repository)';
169
171
  lines.push(` ${finding.severity || 'info'} ${place}${finding.line ? `:${finding.line}` : ''} ${finding.rule || finding.message || ''}`);
172
+ if (finding.message && finding.rule)
173
+ lines.push(` ${finding.message}`);
170
174
  }
171
175
  if (report.findings.length > 40)
172
176
  lines.push(` … ${report.findings.length - 40} more findings.`);
@@ -1 +1 @@
1
- {"version":3,"file":"featureViews.js","sourceRoot":"","sources":["../../src/cli/explorer/featureViews.ts"],"names":[],"mappings":"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","sourcesContent":["/** Terminal projections of data already used by the web views. */\n\ninterface WorkflowStep { name: string; uses?: string | null }\ninterface WorkflowJob { name: string; runsOn?: string; needs?: string[]; steps?: WorkflowStep[] }\ninterface Workflow { name: string; file: string; triggers?: string[]; jobs?: WorkflowJob[] }\n\ninterface License { id: string; name?: string; type?: string }\ninterface Package { name: string; version: string; ecosystem: string; isDev: boolean; license?: License }\ninterface LicenseReport {\n projectLicense: License;\n sbom: Package[];\n counts: { total: number; permissive: number; copyleft: number; weakCopyleft: number; unknown: number };\n complianceStatus: string;\n}\n\ninterface DiffLine { type: 'add' | 'del' | 'context'; text: string }\ninterface DiffHunk { header: string; lines: DiffLine[] }\ninterface DiffFile {\n oldPath: string; newPath: string; status: string;\n additions: number; deletions: number; hunks: DiffHunk[];\n}\ninterface GitDiff {\n files: DiffFile[];\n stats: { additions: number; deletions: number };\n}\n\ninterface ToolStatus {\n label: string; kind: string; available: boolean;\n how?: string | null; reason?: string | null;\n}\ninterface Finding {\n path?: string; file?: string; line?: number;\n severity?: string; rule?: string; message?: string; tool?: string;\n}\ninterface AnalysisPass {\n id: string; label: string; ok: boolean; available: boolean;\n findings: Finding[]; reason?: string; ms?: number;\n}\ninterface AnalysisReport { passes: AnalysisPass[]; findings: Finding[]; ms: number }\n\nfunction columns(): number {\n const env = Number(process.env.COLUMNS);\n return Number.isInteger(env) && env > 0 ? env : process.stdout.columns || 80;\n}\n\nfunction fit(value: unknown, width = columns()): string {\n const text = String(value ?? '').replace(/[\\r\\n\\t]/g, ' ');\n if (width <= 0) return '';\n const points = [...text];\n return points.length <= width ? text : points.slice(0, Math.max(0, width - 1)).join('') + (width > 1 ? '…' : '');\n}\n\nfunction screen(title: string, lines: string[]): string {\n const width = columns();\n const rule = '─'.repeat(Math.max(0, Math.min(width - 2, 48)));\n return ['', fit(` ${title.toUpperCase()}`), fit(` ${rule}`), ...lines.map((line) => fit(line)), ''].join('\\n');\n}\n\nexport function formatWorkflows(workflows: Workflow[]): string {\n if (!workflows.length) return screen('Workflows', [\n ' No GitHub Actions workflows found in .github/workflows/.',\n ]);\n const lines: string[] = [` ${workflows.length} workflow${workflows.length === 1 ? '' : 's'}`];\n for (const workflow of workflows) {\n lines.push('', ` ${workflow.name} · ${workflow.file}`);\n lines.push(` Triggers: ${(workflow.triggers || []).join(', ') || 'none detected'}`);\n for (const job of workflow.jobs || []) {\n lines.push(` ${job.name} ${job.runsOn || ''}`);\n if (job.needs?.length) lines.push(` After: ${job.needs.join(', ')}`);\n for (const step of job.steps || []) lines.push(` · ${step.name}${step.uses ? ` (${step.uses})` : ''}`);\n }\n if (!workflow.jobs?.length) lines.push(' No jobs parsed.');\n }\n return screen('Workflows', lines);\n}\n\nexport function formatSbom(report: LicenseReport | null | undefined, filter = ''): string {\n if (!report) return screen('Software bill of materials', [' Dependency inventory is unavailable for this scan.']);\n const packages = report.sbom || [];\n const q = filter.toLowerCase().trim();\n const selected = q ? packages.filter((item) =>\n item.name.toLowerCase().includes(q) || item.ecosystem.toLowerCase().includes(q)\n || item.license?.id.toLowerCase().includes(q)) : packages;\n const lines = [\n ` Project license ${report.projectLicense?.id || 'unknown'}`,\n ` Dependencies ${report.counts.total} declared · ${report.counts.copyleft} copyleft · ${report.counts.unknown} unknown`,\n ` License review ${report.complianceStatus}${report.counts.unknown ? ' (unknown licenses need checking)' : ''}`,\n '',\n ];\n if (!selected.length) lines.push(q ? ` No dependency matches \"${filter}\".` : ' No dependencies declared.');\n else {\n for (const item of selected.slice(0, 100)) {\n lines.push(` ${item.name} ${item.version} ${item.ecosystem} ${item.isDev ? 'dev' : 'prod'} ${item.license?.id || 'unknown'}`);\n }\n if (selected.length > 100) lines.push(` … ${selected.length - 100} more; use sbom <filter> to narrow the list.`);\n }\n lines.push('', ' Licenses for some packages are inferred; verify them before compliance decisions.');\n return screen('Software bill of materials', lines);\n}\n\nexport function formatDiff(diff: GitDiff, importers: Record<string, string[]>, totalFiles: number, selectedPath = ''): string {\n const files = diff.files || [];\n const changed = new Set(files.map((file) => file.newPath || file.oldPath));\n const impacted = new Set<string>();\n const queue = [...changed];\n for (let cursor = 0; cursor < queue.length; cursor++) {\n for (const dependent of importers[queue[cursor]] || []) {\n if (!changed.has(dependent) && !impacted.has(dependent)) {\n impacted.add(dependent);\n queue.push(dependent);\n }\n }\n }\n const lines = [\n ` ${files.length} changed files · +${diff.stats.additions} / -${diff.stats.deletions}`,\n ` ${impacted.size} dependent files may be affected (${Math.round(impacted.size / Math.max(1, totalFiles) * 100)}% of scanned files)`,\n '',\n ];\n if (!files.length) lines.push(' No tracked changes found for these refs.');\n for (const file of files.slice(0, 100)) {\n lines.push(` ${file.status.padEnd(8)} ${file.newPath || file.oldPath} +${file.additions}/-${file.deletions}`);\n }\n if (files.length > 100) lines.push(` … ${files.length - 100} more files.`);\n if (selectedPath) {\n const file = files.find((item) => item.newPath === selectedPath || item.oldPath === selectedPath);\n lines.push('');\n if (!file) lines.push(` ${selectedPath} is not in this diff.`);\n else {\n lines.push(` PATCH ${selectedPath}`);\n let budget = 120;\n for (const hunk of file.hunks) {\n if (budget-- <= 0) break;\n lines.push(` ${hunk.header}`);\n for (const line of hunk.lines) {\n if (budget-- <= 0) break;\n const marker = line.type === 'add' ? '+' : line.type === 'del' ? '-' : ' ';\n lines.push(` ${marker}${line.text}`);\n }\n }\n if (budget <= 0) lines.push(' … patch output limited to 120 lines.');\n }\n } else if (files.length) lines.push('', ' Use diff <base> <head> <file> to read a patch.');\n return screen('Diff and blast radius', lines);\n}\n\nexport function formatEngines(status: Record<string, ToolStatus>): string {\n const lines: string[] = [];\n for (const [id, tool] of Object.entries(status)) {\n const state = !tool.available ? 'missing' : tool.how === 'path' ? 'installed' : 'runnable';\n lines.push(` ${state} ${tool.label} (${id}) · ${tool.kind}`);\n lines.push(` ${tool.available ? tool.how || 'available' : tool.reason || 'Not installed'}`);\n }\n lines.push('', ' Run: deep <engine> or deep all');\n lines.push(' npx/uvx runners may fetch a tool when you run it.');\n return screen('Deep analysis engines', lines);\n}\n\nexport function formatAtlas(entries: string[], hubs: Array<{ path: string }>, folders: Array<{ path: string }>): string {\n const paths = [...new Set([...entries, ...hubs.map((hub) => hub.path)])].slice(0, 12);\n const lines = [\n ' Whole repository diagram',\n ' Architecture layers layers-diagram',\n ' Folder traffic coupling',\n ' Dependency impact graph <file> / blast <file>',\n '',\n ' SUGGESTED FILE DIAGRAMS',\n ...paths.map((path) => ` ${path} → diagram ${path}`),\n '',\n ` ${folders.length} folders available; use tree <folder> or find <query> to navigate.`,\n ];\n return screen('Diagram atlas', lines);\n}\n\ninterface FileInspector {\n path: string; role: string; loc: number; complexity: number; risk: number;\n imports: string[]; importers: string[];\n exports: Array<{ name: string }>;\n findings: Array<{ severity?: string; rule?: string; message?: string; line?: number }>;\n}\n\nexport function formatInspector(file: FileInspector): string {\n const lines = [\n ` Role ${file.role} · ${file.loc} lines · complexity ${file.complexity} · risk ${file.risk}/100`,\n '',\n ` IMPORTS (${file.imports.length})`,\n ...file.imports.slice(0, 12).map((path) => ` → ${path}`),\n ` IMPORTED BY (${file.importers.length})`,\n ...file.importers.slice(0, 12).map((path) => ` ← ${path}`),\n ` EXPORTS (${file.exports.length})`,\n ...file.exports.slice(0, 12).map((symbol) => ` ${symbol.name}`),\n ` HEURISTIC FINDINGS (${file.findings.length})`,\n ...file.findings.slice(0, 8).map((finding) => ` ${finding.severity || 'info'}${finding.line ? ':' + finding.line : ''} ${finding.rule || finding.message || ''}`),\n '',\n ` Next: show ${file.path} · graph ${file.path} · blame ${file.path}`,\n ];\n return screen(`File inspector ${file.path}`, lines);\n}\n\nexport function formatDeepAnalysis(report: AnalysisReport): string {\n const lines = [` ${report.passes.filter((pass) => pass.ok).length}/${report.passes.length} engines ran · ${report.findings.length} findings · ${report.ms} ms`];\n for (const pass of report.passes) {\n const state = pass.ok ? `${pass.findings.length} findings` : pass.available ? `failed: ${pass.reason || 'unknown error'}` : `unavailable: ${pass.reason || 'not installed'}`;\n lines.push(` ${pass.label} ${state}`);\n }\n if (report.findings.length) {\n lines.push('', ' FINDINGS');\n for (const finding of report.findings.slice(0, 40)) {\n const place = finding.path || finding.file || '(repository)';\n lines.push(` ${finding.severity || 'info'} ${place}${finding.line ? `:${finding.line}` : ''} ${finding.rule || finding.message || ''}`);\n }\n if (report.findings.length > 40) lines.push(` … ${report.findings.length - 40} more findings.`);\n lines.push('', ' Findings are candidates; review test and vendored files before acting.');\n }\n if (!report.passes.some((pass) => pass.ok)) lines.push('', ' No external engine ran; built-in security remains available with `security`.');\n return screen('Deep analysis', lines);\n}\n"]}
1
+ {"version":3,"file":"featureViews.js","sourceRoot":"","sources":["../../src/cli/explorer/featureViews.ts"],"names":[],"mappings":"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","sourcesContent":["/** Terminal projections of data already used by the web views. */\n\ninterface WorkflowStep { name: string; uses?: string | null }\ninterface WorkflowJob { name: string; runsOn?: string; needs?: string[]; steps?: WorkflowStep[] }\ninterface Workflow { name: string; file: string; triggers?: string[]; jobs?: WorkflowJob[] }\n\ninterface License { id: string; name?: string; type?: string }\ninterface Package { name: string; version: string; ecosystem: string; isDev: boolean; license?: License }\ninterface LicenseReport {\n projectLicense: License;\n sbom: Package[];\n counts: { total: number; permissive: number; copyleft: number; weakCopyleft: number; unknown: number };\n complianceStatus: string;\n}\n\ninterface DiffLine { type: 'add' | 'del' | 'context'; text: string }\ninterface DiffHunk { header: string; lines: DiffLine[] }\ninterface DiffFile {\n oldPath: string; newPath: string; status: string;\n additions: number; deletions: number; hunks: DiffHunk[];\n}\ninterface GitDiff {\n files: DiffFile[];\n stats: { additions: number; deletions: number };\n}\n\ninterface ToolStatus {\n label: string; kind: string; available: boolean;\n how?: string | null; reason?: string | null; purpose?: string;\n}\ninterface Finding {\n path?: string; file?: string; line?: number;\n severity?: string; rule?: string; message?: string; tool?: string;\n}\ninterface AnalysisPass {\n id: string; label: string; ok: boolean; available: boolean;\n findings: Finding[]; reason?: string; ms?: number;\n}\ninterface AnalysisReport { passes: AnalysisPass[]; findings: Finding[]; ms: number }\n\nfunction columns(): number {\n const env = Number(process.env.COLUMNS);\n return Number.isInteger(env) && env > 0 ? env : process.stdout.columns || 80;\n}\n\nfunction fit(value: unknown, width = columns()): string {\n const text = String(value ?? '').replace(/[\\r\\n\\t]/g, ' ');\n if (width <= 0) return '';\n const points = [...text];\n return points.length <= width ? text : points.slice(0, Math.max(0, width - 1)).join('') + (width > 1 ? '…' : '');\n}\n\nfunction screen(title: string, lines: string[]): string {\n const width = columns();\n const rule = '─'.repeat(Math.max(0, Math.min(width - 2, 48)));\n return ['', fit(` ${title.toUpperCase()}`), fit(` ${rule}`), ...lines.map((line) => fit(line)), ''].join('\\n');\n}\n\nexport function formatWorkflows(workflows: Workflow[]): string {\n if (!workflows.length) return screen('Workflows', [\n ' No GitHub Actions workflows found in .github/workflows/.',\n ]);\n const lines: string[] = [` ${workflows.length} workflow${workflows.length === 1 ? '' : 's'}`];\n for (const workflow of workflows) {\n lines.push('', ` ${workflow.name} · ${workflow.file}`);\n lines.push(` Triggers: ${(workflow.triggers || []).join(', ') || 'none detected'}`);\n for (const job of workflow.jobs || []) {\n lines.push(` ${job.name} ${job.runsOn || ''}`);\n if (job.needs?.length) lines.push(` After: ${job.needs.join(', ')}`);\n for (const step of job.steps || []) lines.push(` · ${step.name}${step.uses ? ` (${step.uses})` : ''}`);\n }\n if (!workflow.jobs?.length) lines.push(' No jobs parsed.');\n }\n return screen('Workflows', lines);\n}\n\nexport function formatSbom(report: LicenseReport | null | undefined, filter = ''): string {\n if (!report) return screen('Software bill of materials', [' Dependency inventory is unavailable for this scan.']);\n const packages = report.sbom || [];\n const q = filter.toLowerCase().trim();\n const selected = q ? packages.filter((item) =>\n item.name.toLowerCase().includes(q) || item.ecosystem.toLowerCase().includes(q)\n || item.license?.id.toLowerCase().includes(q)) : packages;\n const lines = [\n ` Project license ${report.projectLicense?.id || 'unknown'}`,\n ` Dependencies ${report.counts.total} declared · ${report.counts.copyleft} copyleft · ${report.counts.unknown} unknown`,\n ` License review ${report.complianceStatus}${report.counts.unknown ? ' (unknown licenses need checking)' : ''}`,\n '',\n ];\n if (!selected.length) lines.push(q ? ` No dependency matches \"${filter}\".` : ' No dependencies declared.');\n else {\n for (const item of selected.slice(0, 100)) {\n lines.push(` ${item.name} ${item.version} ${item.ecosystem} ${item.isDev ? 'dev' : 'prod'} ${item.license?.id || 'unknown'}`);\n }\n if (selected.length > 100) lines.push(` … ${selected.length - 100} more; use sbom <filter> to narrow the list.`);\n }\n lines.push('', ' Licenses for some packages are inferred; verify them before compliance decisions.');\n return screen('Software bill of materials', lines);\n}\n\nexport function formatDiff(diff: GitDiff, importers: Record<string, string[]>, totalFiles: number, selectedPath = ''): string {\n const files = diff.files || [];\n const changed = new Set(files.map((file) => file.newPath || file.oldPath));\n const impacted = new Set<string>();\n const queue = [...changed];\n for (let cursor = 0; cursor < queue.length; cursor++) {\n for (const dependent of importers[queue[cursor]] || []) {\n if (!changed.has(dependent) && !impacted.has(dependent)) {\n impacted.add(dependent);\n queue.push(dependent);\n }\n }\n }\n const lines = [\n ` ${files.length} changed files · +${diff.stats.additions} / -${diff.stats.deletions}`,\n ` ${impacted.size} dependent files may be affected (${Math.round(impacted.size / Math.max(1, totalFiles) * 100)}% of scanned files)`,\n '',\n ];\n if (!files.length) lines.push(' No tracked changes found for these refs.');\n for (const file of files.slice(0, 100)) {\n lines.push(` ${file.status.padEnd(8)} ${file.newPath || file.oldPath} +${file.additions}/-${file.deletions}`);\n }\n if (files.length > 100) lines.push(` … ${files.length - 100} more files.`);\n if (selectedPath) {\n const file = files.find((item) => item.newPath === selectedPath || item.oldPath === selectedPath);\n lines.push('');\n if (!file) lines.push(` ${selectedPath} is not in this diff.`);\n else {\n lines.push(` PATCH ${selectedPath}`);\n let budget = 120;\n for (const hunk of file.hunks) {\n if (budget-- <= 0) break;\n lines.push(` ${hunk.header}`);\n for (const line of hunk.lines) {\n if (budget-- <= 0) break;\n const marker = line.type === 'add' ? '+' : line.type === 'del' ? '-' : ' ';\n lines.push(` ${marker}${line.text}`);\n }\n }\n if (budget <= 0) lines.push(' … patch output limited to 120 lines.');\n }\n } else if (files.length) lines.push('', ' Use diff <base> <head> <file> to read a patch.');\n return screen('Diff and blast radius', lines);\n}\n\nexport function formatEngines(status: Record<string, ToolStatus>): string {\n const lines: string[] = [];\n for (const [id, tool] of Object.entries(status)) {\n const state = !tool.available ? 'missing' : tool.how === 'path' ? 'installed' : 'runnable';\n lines.push(` ${state} ${tool.label} (${id}) · ${tool.kind}`);\n if (tool.purpose) lines.push(` ${tool.purpose}`);\n lines.push(` ${tool.available ? tool.how || 'available' : tool.reason || 'Not installed'}`);\n }\n lines.push('', ' Run: deep <engine> or deep all');\n lines.push(' npx/uvx runners may fetch a tool when you run it.');\n return screen('Deep analysis engines', lines);\n}\n\nexport function formatAtlas(entries: string[], hubs: Array<{ path: string }>, folders: Array<{ path: string }>): string {\n const paths = [...new Set([...entries, ...hubs.map((hub) => hub.path)])].slice(0, 12);\n const lines = [\n ' Whole repository diagram',\n ' Architecture layers layers-diagram',\n ' Folder traffic coupling',\n ' Dependency impact graph <file> / blast <file>',\n '',\n ' SUGGESTED FILE DIAGRAMS',\n ...paths.map((path) => ` ${path} → diagram ${path}`),\n '',\n ` ${folders.length} folders available; use tree <folder> or find <query> to navigate.`,\n ];\n return screen('Diagram atlas', lines);\n}\n\ninterface FileInspector {\n path: string; role: string; loc: number; complexity: number; risk: number;\n imports: string[]; importers: string[];\n exports: Array<{ name: string }>;\n findings: Array<{ severity?: string; rule?: string; message?: string; line?: number }>;\n}\n\nexport function formatInspector(file: FileInspector): string {\n const lines = [\n ` Role ${file.role} · ${file.loc} lines · complexity ${file.complexity} · risk ${file.risk}/100`,\n '',\n ` IMPORTS (${file.imports.length})`,\n ...file.imports.slice(0, 12).map((path) => ` → ${path}`),\n ` IMPORTED BY (${file.importers.length})`,\n ...file.importers.slice(0, 12).map((path) => ` ← ${path}`),\n ` EXPORTS (${file.exports.length})`,\n ...file.exports.slice(0, 12).map((symbol) => ` ${symbol.name}`),\n ` HEURISTIC FINDINGS (${file.findings.length})`,\n ...file.findings.slice(0, 8).map((finding) => ` ${finding.severity || 'info'}${finding.line ? ':' + finding.line : ''} ${finding.rule || finding.message || ''}`),\n '',\n ` Next: show ${file.path} · graph ${file.path} · blame ${file.path}`,\n ];\n return screen(`File inspector ${file.path}`, lines);\n}\n\nexport function formatDeepAnalysis(report: AnalysisReport): string {\n const lines = [` ${report.passes.filter((pass) => pass.ok).length}/${report.passes.length} engines ran · ${report.findings.length} findings · ${report.ms} ms`];\n for (const pass of report.passes) {\n const state = pass.ok ? `${pass.findings.length} findings` : pass.available ? `failed: ${pass.reason || 'unknown error'}` : `unavailable: ${pass.reason || 'not installed'}`;\n lines.push(` ${pass.label} ${state}`);\n }\n if (report.findings.length) {\n lines.push('', ' FINDINGS');\n for (const finding of report.findings.slice(0, 40)) {\n const place = finding.path || finding.file || '(repository)';\n lines.push(` ${finding.severity || 'info'} ${place}${finding.line ? `:${finding.line}` : ''} ${finding.rule || finding.message || ''}`);\n if (finding.message && finding.rule) lines.push(` ${finding.message}`);\n }\n if (report.findings.length > 40) lines.push(` … ${report.findings.length - 40} more findings.`);\n lines.push('', ' Findings are candidates; review test and vendored files before acting.');\n }\n if (!report.passes.some((pass) => pass.ok)) lines.push('', ' No external engine ran; built-in security remains available with `security`.');\n return screen('Deep analysis', lines);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebase-onboarder",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Drop a path. Get a map. A zero-dependency codebase visualizer with a CLI onboarding wizard, a web UI, and an optional key-gated self-hosted mode.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,7 +41,7 @@ export function toolsStatus() {
41
41
  function unavailableReason(def) {
42
42
  return (def.install && def.install.length) ? def.install.join(' ') : 'Not found on PATH.';
43
43
  }
44
- async function runOneTool(def, root, toolOptions = {}) {
44
+ async function runOneTool(def, root, toolOptions = {}, signal) {
45
45
  // A tool that reports through a file (gitleaks) gets a per-run temp path —
46
46
  // never /dev/stdout, which does not exist on Windows, and never a fixed
47
47
  // name, so two concurrent runs cannot read each other's report.
@@ -57,6 +57,7 @@ async function runOneTool(def, root, toolOptions = {}) {
57
57
  const result = await runTool(resolved.argv, {
58
58
  cwd: def.cwd ? root : undefined,
59
59
  timeout: TOOL_TIMEOUT_MS,
60
+ signal,
60
61
  });
61
62
  // Read and remove the report file whatever happened above.
62
63
  let reportText = null;
@@ -77,8 +78,12 @@ async function runOneTool(def, root, toolOptions = {}) {
77
78
  if (!result.ok) {
78
79
  return { ...emptyPass(def.id, def.label, result.error || 'The tool could not be run.'), available: true };
79
80
  }
81
+ if (def.usesReportFile && reportText === null)
82
+ return { ...emptyPass(def.id, def.label, result.stderr || 'The analyzer did not create its report.'), available: true };
80
83
  const stdout = (def.usesReportFile ? (reportText || '') : (result.stdout || '')).trim();
81
84
  if (!stdout) {
85
+ if (result.status !== 0)
86
+ return { ...emptyPass(def.id, def.label, `Exited ${result.status}: ${result.stderr || 'No readable report.'}`), available: true };
82
87
  // A clean pass: the tool ran and found nothing. That is a real answer, and
83
88
  // worth saying — "Gitleaks: no secrets" is the outcome a self-hosting user
84
89
  // runs the tool to hear.
@@ -106,12 +111,21 @@ function passResult(def, resolved, findings, started) {
106
111
  // `options` is per-engine GUI settings, sanitized against the registry schema
107
112
  // before any of it touches a command line.
108
113
  export async function runExternalAnalysis(root, options = {}) {
114
+ options.signal?.throwIfAborted();
109
115
  const kinds = options.kinds ? new Set(options.kinds) : null;
110
116
  const tools = options.tools ? new Set(options.tools) : null;
111
117
  const rawOptions = options.options && typeof options.options === 'object' ? options.options : {};
112
118
  const defs = TOOL_DEFS.filter((d) => (!kinds || kinds.has(d.kind)) && (!tools || tools.has(d.id)));
113
119
  const started = Date.now();
114
- const passes = await Promise.all(defs.map((def) => runOneTool(def, root, sanitizeOptions(def, rawOptions[def.id]))));
120
+ const passes = await Promise.all(defs.map(async (def) => {
121
+ options.signal?.throwIfAborted();
122
+ options.onProgress?.({ phase: 'start', id: def.id, label: def.label });
123
+ const pass = await runOneTool(def, root, sanitizeOptions(def, rawOptions[def.id]), options.signal);
124
+ if (!options.signal?.aborted)
125
+ options.onProgress?.({ phase: 'complete', id: def.id, label: def.label, pass });
126
+ return pass;
127
+ }));
128
+ options.signal?.throwIfAborted();
115
129
  const ran = passes.filter((p) => p.ok);
116
130
  const findings = mergeFindings(...passes.map((p) => p.findings));
117
131
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/server/tools/scan.ts"],"names":[],"mappings":"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","sourcesContent":["// The orchestrator: detect what is on the machine, run each available analyzer\n// against the scanned root, and hand back one normalized report.\n//\n// Two promises drive the shape. First, detection is *honest*: the report always\n// lists every tool and whether it ran, so \"no security issues\" and \"no security\n// tool installed\" are never the same sentence. Second, failure is *local*: a\n// tool that hangs, crashes or prints garbage fails its own pass and nothing\n// else — the scan the person asked for already succeeded, and this is a bonus\n// layer over it, exactly the way `collectHistory` treats git.\n\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { emptyPass, runTool, toolArgv, TOOL_TIMEOUT_MS } from '../tools.js';\nimport { defaultOptions, sanitizeOptions, TOOL_DEFS } from './registry.js';\nimport { mergeFindings } from './parse.js';\n\n// What is installed, for the UI's \"engines\" panel. Detection is cached by\n// `which`, so asking is cheap. The payload also carries each tool's option\n// schema and defaults, so the GUI can render a form for what the engine\n// actually offers without hard-coding a flag anywhere in the front end.\nexport function toolsStatus() {\n const out: Record<string, any> = {};\n for (const def of TOOL_DEFS) {\n const resolved = toolArgv(def, '.');\n out[def.id] = {\n id: def.id,\n label: def.label,\n kind: def.kind,\n purpose: def.purpose,\n available: !!resolved,\n how: resolved ? resolved.how : null,\n command: resolved ? resolved.display : null,\n reason: resolved ? null : unavailableReason(def),\n options: def.options || [],\n defaults: defaultOptions(def),\n installable: true,\n platform: process.platform,\n };\n }\n return out;\n}\n\nfunction unavailableReason(def) {\n return (def.install && def.install.length) ? def.install.join(' ') : 'Not found on PATH.';\n}\n\nasync function runOneTool(def, root, toolOptions: Record<string, any> = {}) {\n // A tool that reports through a file (gitleaks) gets a per-run temp path —\n // never /dev/stdout, which does not exist on Windows, and never a fixed\n // name, so two concurrent runs cannot read each other's report.\n const ctx: Record<string, any> = {};\n if (def.usesReportFile) {\n ctx.reportPath = path.join(os.tmpdir(), `onboarder-${def.id}-${Date.now()}-${Math.floor(Math.random() * 1e6)}.json`);\n }\n\n const resolved = toolArgv(def, root, toolOptions, ctx);\n if (!resolved) {\n return emptyPass(def.id, def.label, unavailableReason(def));\n }\n\n const started = Date.now();\n const result = await runTool(resolved.argv, {\n cwd: def.cwd ? root : undefined,\n timeout: TOOL_TIMEOUT_MS,\n });\n\n // Read and remove the report file whatever happened above.\n let reportText = null;\n if (ctx.reportPath) {\n try {\n reportText = fs.readFileSync(ctx.reportPath, 'utf8');\n } catch {\n reportText = null; // a crashed tool may never have written it\n }\n try { fs.unlinkSync(ctx.reportPath); } catch { /* already gone */ }\n }\n\n if (result.timedOut) return { ...emptyPass(def.id, def.label, result.error), available: true };\n if (!result.ok) {\n return { ...emptyPass(def.id, def.label, result.error || 'The tool could not be run.'), available: true };\n }\n\n const stdout = (def.usesReportFile ? (reportText || '') : (result.stdout || '')).trim();\n if (!stdout) {\n // A clean pass: the tool ran and found nothing. That is a real answer, and\n // worth saying — \"Gitleaks: no secrets\" is the outcome a self-hosting user\n // runs the tool to hear.\n return passResult(def, resolved, [], started);\n }\n\n try {\n const findings = def.parse(stdout, root);\n return passResult(def, resolved, findings, started);\n } catch (err) {\n return { ...emptyPass(def.id, def.label, 'Its output could not be read: ' + err.message), available: true };\n }\n}\n\nfunction passResult(def, resolved, findings, started) {\n return {\n id: def.id, label: def.label, kind: def.kind, ok: true, available: true,\n findings, source: 'external', tool: def.id, how: resolved.how, ms: Date.now() - started,\n };\n}\n\n// Tools run concurrently — a scan is I/O-bound and the analyzers are\n// independent — but a repo with zero analyzers still gets a well-formed report,\n// so the frontend renders the built-in floor and the \"what to install\" list.\n// `kinds` narrows by purpose, `tools` narrows to named engines; both exist so\n// the UI can offer \"run just the secrets scan\" as readily as \"run everything\".\n// `options` is per-engine GUI settings, sanitized against the registry schema\n// before any of it touches a command line.\nexport async function runExternalAnalysis(root, options: Record<string, any> = {}) {\n const kinds = options.kinds ? new Set(options.kinds) : null;\n const tools = options.tools ? new Set(options.tools) : null;\n const rawOptions = options.options && typeof options.options === 'object' ? options.options : {};\n const defs = TOOL_DEFS.filter((d) => (!kinds || kinds.has(d.kind)) && (!tools || tools.has(d.id)));\n\n const started = Date.now();\n const passes = await Promise.all(defs.map((def) => runOneTool(def, root, sanitizeOptions(def, rawOptions[def.id]))));\n\n const ran = passes.filter((p) => p.ok);\n const findings = mergeFindings(...passes.map((p) => p.findings));\n\n return {\n ms: Date.now() - started,\n passes,\n findings,\n ranCount: ran.length,\n totalTools: defs.length,\n unavailable: passes.filter((p) => !p.available).map((p) => ({ id: p.id, label: p.label, reason: ('reason' in p ? p.reason : undefined) })),\n source: ran.length ? 'external' : 'none',\n };\n}\n"]}
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/server/tools/scan.ts"],"names":[],"mappings":"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","sourcesContent":["// The orchestrator: detect what is on the machine, run each available analyzer\n// against the scanned root, and hand back one normalized report.\n//\n// Two promises drive the shape. First, detection is *honest*: the report always\n// lists every tool and whether it ran, so \"no security issues\" and \"no security\n// tool installed\" are never the same sentence. Second, failure is *local*: a\n// tool that hangs, crashes or prints garbage fails its own pass and nothing\n// else — the scan the person asked for already succeeded, and this is a bonus\n// layer over it, exactly the way `collectHistory` treats git.\n\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { emptyPass, runTool, toolArgv, TOOL_TIMEOUT_MS } from '../tools.js';\nimport { defaultOptions, sanitizeOptions, TOOL_DEFS } from './registry.js';\nimport { mergeFindings } from './parse.js';\n\n// What is installed, for the UI's \"engines\" panel. Detection is cached by\n// `which`, so asking is cheap. The payload also carries each tool's option\n// schema and defaults, so the GUI can render a form for what the engine\n// actually offers without hard-coding a flag anywhere in the front end.\nexport function toolsStatus() {\n const out: Record<string, any> = {};\n for (const def of TOOL_DEFS) {\n const resolved = toolArgv(def, '.');\n out[def.id] = {\n id: def.id,\n label: def.label,\n kind: def.kind,\n purpose: def.purpose,\n available: !!resolved,\n how: resolved ? resolved.how : null,\n command: resolved ? resolved.display : null,\n reason: resolved ? null : unavailableReason(def),\n options: def.options || [],\n defaults: defaultOptions(def),\n installable: true,\n platform: process.platform,\n };\n }\n return out;\n}\n\nfunction unavailableReason(def) {\n return (def.install && def.install.length) ? def.install.join(' ') : 'Not found on PATH.';\n}\n\nasync function runOneTool(def, root, toolOptions: Record<string, any> = {}, signal?: AbortSignal) {\n // A tool that reports through a file (gitleaks) gets a per-run temp path —\n // never /dev/stdout, which does not exist on Windows, and never a fixed\n // name, so two concurrent runs cannot read each other's report.\n const ctx: Record<string, any> = {};\n if (def.usesReportFile) {\n ctx.reportPath = path.join(os.tmpdir(), `onboarder-${def.id}-${Date.now()}-${Math.floor(Math.random() * 1e6)}.json`);\n }\n\n const resolved = toolArgv(def, root, toolOptions, ctx);\n if (!resolved) {\n return emptyPass(def.id, def.label, unavailableReason(def));\n }\n\n const started = Date.now();\n const result = await runTool(resolved.argv, {\n cwd: def.cwd ? root : undefined,\n timeout: TOOL_TIMEOUT_MS,\n signal,\n });\n\n // Read and remove the report file whatever happened above.\n let reportText = null;\n if (ctx.reportPath) {\n try {\n reportText = fs.readFileSync(ctx.reportPath, 'utf8');\n } catch {\n reportText = null; // a crashed tool may never have written it\n }\n try { fs.unlinkSync(ctx.reportPath); } catch { /* already gone */ }\n }\n\n if (result.timedOut) return { ...emptyPass(def.id, def.label, result.error), available: true };\n if (!result.ok) {\n return { ...emptyPass(def.id, def.label, result.error || 'The tool could not be run.'), available: true };\n }\n if (def.usesReportFile && reportText === null) return { ...emptyPass(def.id, def.label, result.stderr || 'The analyzer did not create its report.'), available: true };\n\n const stdout = (def.usesReportFile ? (reportText || '') : (result.stdout || '')).trim();\n if (!stdout) {\n if (result.status !== 0) return { ...emptyPass(def.id, def.label, `Exited ${result.status}: ${result.stderr || 'No readable report.'}`), available: true };\n // A clean pass: the tool ran and found nothing. That is a real answer, and\n // worth saying — \"Gitleaks: no secrets\" is the outcome a self-hosting user\n // runs the tool to hear.\n return passResult(def, resolved, [], started);\n }\n\n try {\n const findings = def.parse(stdout, root);\n return passResult(def, resolved, findings, started);\n } catch (err) {\n return { ...emptyPass(def.id, def.label, 'Its output could not be read: ' + err.message), available: true };\n }\n}\n\nfunction passResult(def, resolved, findings, started) {\n return {\n id: def.id, label: def.label, kind: def.kind, ok: true, available: true,\n findings, source: 'external', tool: def.id, how: resolved.how, ms: Date.now() - started,\n };\n}\n\n// Tools run concurrently — a scan is I/O-bound and the analyzers are\n// independent — but a repo with zero analyzers still gets a well-formed report,\n// so the frontend renders the built-in floor and the \"what to install\" list.\n// `kinds` narrows by purpose, `tools` narrows to named engines; both exist so\n// the UI can offer \"run just the secrets scan\" as readily as \"run everything\".\n// `options` is per-engine GUI settings, sanitized against the registry schema\n// before any of it touches a command line.\nexport async function runExternalAnalysis(root, options: Record<string, any> = {}) {\n options.signal?.throwIfAborted();\n const kinds = options.kinds ? new Set(options.kinds) : null;\n const tools = options.tools ? new Set(options.tools) : null;\n const rawOptions = options.options && typeof options.options === 'object' ? options.options : {};\n const defs = TOOL_DEFS.filter((d) => (!kinds || kinds.has(d.kind)) && (!tools || tools.has(d.id)));\n\n const started = Date.now();\n const passes = await Promise.all(defs.map(async def => {\n options.signal?.throwIfAborted();\n options.onProgress?.({ phase: 'start', id: def.id, label: def.label });\n const pass = await runOneTool(def, root, sanitizeOptions(def, rawOptions[def.id]), options.signal);\n if (!options.signal?.aborted) options.onProgress?.({ phase: 'complete', id: def.id, label: def.label, pass });\n return pass;\n }));\n options.signal?.throwIfAborted();\n\n const ran = passes.filter((p) => p.ok);\n const findings = mergeFindings(...passes.map((p) => p.findings));\n\n return {\n ms: Date.now() - started,\n passes,\n findings,\n ranCount: ran.length,\n totalTools: defs.length,\n unavailable: passes.filter((p) => !p.available).map((p) => ({ id: p.id, label: p.label, reason: ('reason' in p ? p.reason : undefined) })),\n source: ran.length ? 'external' : 'none',\n };\n}\n"]}
package/server/tools.d.ts CHANGED
@@ -5,6 +5,7 @@ export interface ToolResult {
5
5
  stderr?: string;
6
6
  error?: string;
7
7
  timedOut?: boolean;
8
+ cancelled?: boolean;
8
9
  code?: number;
9
10
  ms?: number;
10
11
  }
package/server/tools.js CHANGED
@@ -155,9 +155,13 @@ export function runTool(argv, options = {}) {
155
155
  const timeout = options.timeout || TOOL_TIMEOUT_MS;
156
156
  const { command, args } = spawnArgv(argv);
157
157
  return new Promise((resolve) => {
158
+ if (options.signal?.aborted) {
159
+ resolve({ ok: false, stdout: '', cancelled: true, error: 'Analysis cancelled.' });
160
+ return;
161
+ }
158
162
  let child;
159
163
  try {
160
- child = spawn(command, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'], env: options.env });
164
+ child = spawn(command, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'], env: options.env, detached: process.platform !== 'win32' });
161
165
  }
162
166
  catch (err) {
163
167
  resolve({ ok: false, status: -1, stdout: '', stderr: String(err && err.message || err), timedOut: false });
@@ -166,27 +170,63 @@ export function runTool(argv, options = {}) {
166
170
  let stdout = '';
167
171
  let stderr = '';
168
172
  let settled = false;
173
+ let stopped = null, bytes = 0;
174
+ const stop = (reason) => {
175
+ if (settled || stopped)
176
+ return;
177
+ stopped = reason;
178
+ if (process.platform === 'win32' && child.pid) {
179
+ const killer = spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { stdio: 'ignore' });
180
+ killer.on('error', () => child.kill());
181
+ killer.unref();
182
+ }
183
+ else {
184
+ try {
185
+ process.kill(-child.pid, 'SIGKILL');
186
+ }
187
+ catch {
188
+ child.kill('SIGKILL');
189
+ }
190
+ }
191
+ };
192
+ const abort = () => stop({ ok: false, cancelled: true, error: 'Analysis cancelled.' });
169
193
  const finish = (extra) => {
170
194
  if (settled)
171
195
  return;
172
196
  settled = true;
173
197
  clearTimeout(timer);
198
+ options.signal?.removeEventListener('abort', abort);
174
199
  resolve({ status: child.exitCode, stdout, stderr, ...extra });
175
200
  };
176
201
  const cap = (chunk, into) => {
177
202
  const next = into + chunk;
178
203
  return next.length > MAX_OUTPUT_BYTES ? next.slice(0, MAX_OUTPUT_BYTES) : next;
179
204
  };
180
- child.stdout.on('data', (c) => { stdout = cap(c.toString(), stdout); });
181
- child.stderr.on('data', (c) => { stderr = cap(c.toString(), stderr).slice(-4000); });
205
+ child.stdout.setEncoding('utf8');
206
+ child.stderr.setEncoding('utf8');
207
+ const collect = (chunk, stderrChunk = false) => {
208
+ bytes += Buffer.byteLength(chunk);
209
+ if (bytes > MAX_OUTPUT_BYTES) {
210
+ stop({ ok: false, error: 'Analyzer output exceeded the size limit.' });
211
+ return;
212
+ }
213
+ if (stderrChunk)
214
+ stderr = cap(chunk, stderr).slice(-4000);
215
+ else
216
+ stdout = cap(chunk, stdout);
217
+ };
218
+ child.stdout.on('data', c => collect(c));
219
+ child.stderr.on('data', c => collect(c, true));
182
220
  const timer = setTimeout(() => {
183
- child.kill('SIGKILL');
184
- finish({ ok: false, timedOut: true, error: `${argv[0]} took too long and was stopped.` });
221
+ stop({ ok: false, timedOut: true, error: `${argv[0]} took too long and was stopped.` });
185
222
  }, timeout);
186
223
  child.on('error', (err) => {
187
224
  finish({ ok: false, timedOut: false, error: 'Could not run ' + argv[0] + ': ' + err.message });
188
225
  });
189
- child.on('close', () => finish({ ok: true, timedOut: false }));
226
+ child.on('close', () => finish(stopped || { ok: true, timedOut: false }));
227
+ options.signal?.addEventListener('abort', abort, { once: true });
228
+ if (options.signal?.aborted)
229
+ abort();
190
230
  });
191
231
  }
192
232
  // The contract every analyzer hands back: findings normalized to the shape the