dsh-pentester 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -5
- package/agents/impact/profile.yml +19 -0
- package/agents/recon/profile.yml +23 -0
- package/agents/reporting/REPORT_TEMPLATE.md +333 -0
- package/agents/reporting/profile.yml +45 -0
- package/agents/threat-model/profile.yml +19 -0
- package/agents/validation/profile.yml +20 -0
- package/agents/vulnerability/profile.yml +19 -0
- package/agents/web/profile.yml +19 -0
- package/cordis.dev.patch.yml +16 -0
- package/cordis.patch.yml +2 -0
- package/docker/README.md +60 -0
- package/docker/kali/Dockerfile +881 -0
- package/docker/kali/README.md +104 -0
- package/docker/kali/REPORT_TEMPLATE.md +333 -0
- package/docker/kali/TOOL_PROMPT.md +362 -0
- package/docker/kali/bin/clone-kb +39 -0
- package/docker/kali/bin/entrypoint.sh +9 -0
- package/docker/kali/bin/gen-tools-json.sh +246 -0
- package/docker/kali/bin/record-traffic.sh +32 -0
- package/docker/kali/bin/tool-info +31 -0
- package/docker/kali/bin/tool-list +17 -0
- package/lib/catalog-BmeOyr6n.js +231 -0
- package/lib/catalog-BmeOyr6n.js.map +1 -0
- package/lib/catalog-DhE_r18k.js +231 -0
- package/lib/catalog-DhE_r18k.js.map +1 -0
- package/lib/client.js +15234 -0
- package/lib/client.js.map +7 -0
- package/lib/container-listing-BI6Xj8l2.js +56 -0
- package/lib/container-listing-BI6Xj8l2.js.map +1 -0
- package/lib/container-listing-BWZoBnN_.js +56 -0
- package/lib/container-listing-BWZoBnN_.js.map +1 -0
- package/lib/container-listing-CE5t-Y_H.js +56 -0
- package/lib/container-listing-CE5t-Y_H.js.map +1 -0
- package/lib/container-listing-DZPBvrLD.js +56 -0
- package/lib/container-listing-DZPBvrLD.js.map +1 -0
- package/lib/docker-tar-_wf8UrSj.js +66 -0
- package/lib/docker-tar-_wf8UrSj.js.map +1 -0
- package/lib/engagement-container-store-B9D8g0wq.js +641 -0
- package/lib/engagement-container-store-B9D8g0wq.js.map +1 -0
- package/lib/engagement-container-store-Cf-h0B4F.js +641 -0
- package/lib/engagement-container-store-Cf-h0B4F.js.map +1 -0
- package/lib/engagement-container-store-Cu1wuur1.js +639 -0
- package/lib/engagement-container-store-Cu1wuur1.js.map +1 -0
- package/lib/engagement-container-store-L_Gms-zi.js +632 -0
- package/lib/engagement-container-store-L_Gms-zi.js.map +1 -0
- package/lib/index.d.ts +41 -0
- package/lib/index.js +3200 -0
- package/lib/index.js.map +1 -0
- package/lib/model-CZoiogVs.js +149 -0
- package/lib/model-CZoiogVs.js.map +1 -0
- package/lib/model-DKZ5Rjik.js +145 -0
- package/lib/model-DKZ5Rjik.js.map +1 -0
- package/lib/worker-events-jFvaBp9x.js +351 -0
- package/lib/worker-events-jFvaBp9x.js.map +1 -0
- package/lib/worker-events-juSf0EDW.js +347 -0
- package/lib/worker-events-juSf0EDW.js.map +1 -0
- package/package.json +89 -8
- package/presets/pentester/agent.cordis.yml +194 -0
- package/presets/pentester/preset.yml +2 -0
- package/presets/pentester/run-state.mjs +210 -0
- package/index.js +0 -5
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["imageReadyOn"],"sources":["../src/dsh.ts","../src/stages.ts","../src/model.ts","../src/store.ts","../src/workspace.ts","../src/delegations.ts","../src/pentest/assets.ts","../src/pentest/findings.ts","../src/tools.ts","../src/profiles.ts","../src/docker/host.ts","../src/docker/images.ts","../src/docker/runtime.ts","../src/worker-tools.ts","../src/settings-store.ts","../node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.1.0-rc.7_@deepseek-ai+cordis@4.0.1_@deepseek-ai+dsh-_d73d8b8dfb7ef1310693b69e6082fcb0/node_modules/@deepseek-ai/dsh-typert-protocol/lib/index.js","../src/invocations.ts","../src/docker/connection.ts","../src/rpc.ts","../src/git.ts","../src/index.ts"],"sourcesContent":["/**\n * dsh.ts — official DeepSeek Harness Continuable Subagent seam adapter.\n *\n * Worker execution = `ctx.subagents.startContinuable()` (provider `spawn`,\n * registered by dsh-base). DSH manages durable child Session, Activation,\n * cold resume, and FIFO inbox — this plugin only manages PTES domain state.\n *\n * One-shot `SubagentRun` / `run.result` / `run.dispose()` / `ctx.jobs` are\n * removed: continuable children have no run handle and no job wrapper.\n *\n * Worker toolFilter 使用 deny-list:Worker 继承 Parent pentester preset 的\n * standing scope,deny 只移除 Root 编排能力 + 用户交互 + 递归派生。\n */\nimport type { Agent } from '@deepseek-ai/dsh-agent'\nimport type { MessageId } from '@deepseek-ai/dsh-llm'\nimport type { SessionId } from '@deepseek-ai/dsh-session'\nimport type { ToolRestriction } from '@deepseek-ai/dsh-tools'\nimport type {\n ContinuableStart,\n ContinuableStartSpec,\n SubagentInterruptAuthority,\n SubagentRuntime,\n} from '@deepseek-ai/dsh-subagent'\n\nexport const PRESET_ID = 'pentester'\n\n/** dsh-base 已注册的官方 in-process spawn provider 名。 */\nexport const SUBAGENT_PROVIDER = 'spawn'\n\n/**\n * Worker 工具面:deny Root 编排能力 + 用户交互。\n *\n * 使用 deny-list 而非 allow-list:Worker 继承 Parent 的 pentester preset\n * standing scope。deny 只移除 Worker 不应拥有的工具,其余继承能力完整保留。\n *\n * 重要:deny 中只能出现当前 composition 中确实注册过的工具名。\n * DSH tools.restrict() 对未知名字做严格存在性校验。\n */\nexport const WORKER_TOOL_FILTER: ToolRestriction = {\n deny: [\n 'pentester_delegate',\n 'pentester_cancel_delegation',\n 'pentester_advance_stage',\n 'pentester_rollback_stage',\n 'ask_user_question',\n ],\n}\n\nexport function isPentesterAgentPreset(preset: string | undefined): boolean {\n return preset === PRESET_ID\n}\n\n// ── trusted caller identity (from exec.agent; never model-supplied) ─────────\n\nexport interface TrustedCaller {\n readonly sessionId: string\n readonly agentPreset?: string\n readonly isSubagent: boolean\n readonly isPentesterRoot: boolean\n readonly cwd?: string\n}\n\ninterface SessionHeaderLike {\n readonly origin?: 'subagent' | string\n readonly delegationDepth?: number\n readonly agentPreset?: string\n readonly id?: string\n readonly cwd?: string\n}\n\ninterface SessionEventLike {\n readonly type: string\n readonly data?: unknown\n}\n\ninterface LiveAgentLike {\n readonly id?: string\n readonly session: {\n readonly id?: string\n readonly header: SessionHeaderLike\n readonly events?: readonly SessionEventLike[]\n }\n}\n\nfunction resolveSessionPreset(session: {\n readonly header: SessionHeaderLike\n readonly events?: readonly SessionEventLike[]\n}): string | undefined {\n const events = session.events ?? []\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type !== 'agent-preset/selected') continue\n const data = event.data as { agentPreset?: unknown } | undefined\n if (typeof data?.agentPreset === 'string' && data.agentPreset.length > 0) return data.agentPreset\n }\n return session.header.agentPreset\n}\n\nexport function trustedCallerFromAgent(agent: unknown): TrustedCaller | undefined {\n if (agent === null || typeof agent !== 'object') return undefined\n const record = agent as LiveAgentLike\n const session = record.session\n if (session === null || typeof session !== 'object'\n || session.header === null || typeof session.header !== 'object') return undefined\n const sessionId = typeof record.id === 'string' && record.id.length > 0 ? record.id : session.id\n if (typeof sessionId !== 'string' || sessionId.length === 0) return undefined\n const agentPreset = resolveSessionPreset({ header: session.header, events: session.events })\n const isSubagent =\n session.header.origin === 'subagent'\n || (typeof session.header.delegationDepth === 'number' && session.header.delegationDepth >= 1)\n return {\n sessionId,\n ...(agentPreset === undefined ? {} : { agentPreset }),\n isSubagent,\n isPentesterRoot: !isSubagent && isPentesterAgentPreset(agentPreset),\n ...(typeof session.header.cwd === 'string' && session.header.cwd.length > 0\n ? { cwd: session.header.cwd }\n : {}),\n }\n}\n\nfunction legacySessionIdFromExec(exec: unknown): string | undefined {\n if (exec === null || typeof exec !== 'object') return undefined\n const record = exec as Record<string, unknown>\n if (typeof record.sessionId === 'string' && record.sessionId.length > 0) return record.sessionId\n const session = record.session\n if (session !== null && typeof session === 'object') {\n const id = (session as { id?: unknown }).id\n if (typeof id === 'string') return id\n }\n return undefined\n}\n\nexport function trustedCallerFromExec(exec: unknown): TrustedCaller | undefined {\n const agent = exec === null || typeof exec !== 'object'\n ? undefined\n : (exec as Record<string, unknown>).agent\n const fromAgent = agent !== null && typeof agent === 'object' ? trustedCallerFromAgent(agent) : undefined\n if (fromAgent !== undefined) return fromAgent\n const sessionId = legacySessionIdFromExec(exec)\n if (sessionId === undefined) return undefined\n return { sessionId, isSubagent: false, isPentesterRoot: false }\n}\n\n// ── continuable subagent adapter ─────────────────────────────────────────────\n\nexport interface CreateWorkerInput {\n /** child 展示标签(subagent label)。 */\n readonly label: string\n /** child persona:WORKER_BASELINE + AgentProfile.systemPrompt。 */\n readonly persona: string\n /** child 首轮 user message:standalone task context + task_prompt。 */\n readonly prompt: string\n readonly model?: string\n}\n\n/** startContinuable 返回:child 已接受初始 prompt,但尚未开始执行。 */\nexport interface ContinuableWorkerStart {\n /** durable child session id,稳定跨 Activation。 */\n readonly childId: SessionId\n /** 初始 prompt 的 inbox message id。 */\n readonly messageId: MessageId\n}\n\n/**\n * 本插件用到的 harness 服务子集。只依赖 subagents;不再需要 ctx.jobs。\n */\nexport interface NativeHarnessContext {\n readonly subagents: SubagentRuntime\n}\n\nexport class DshClient {\n private readonly ctx: NativeHarnessContext\n\n constructor(ctx: NativeHarnessContext) {\n this.ctx = ctx\n }\n\n get subagentAvailable(): boolean {\n return this.ctx.subagents !== undefined\n && this.ctx.subagents.getProvider(SUBAGENT_PROVIDER) !== undefined\n }\n\n /**\n * 创建 continuable Worker:reserve durable child id → resolve provider\n * creation spec → create child Agent → submit initial prompt。\n * resolve 时 child 已接受 prompt 但尚未开始执行 —— 不等于 Worker 已完成。\n */\n async startContinuableWorker(\n input: CreateWorkerInput,\n parent: Agent,\n signal: AbortSignal,\n ): Promise<ContinuableWorkerStart> {\n if (!this.subagentAvailable) {\n throw new Error(`subagent provider \"${SUBAGENT_PROVIDER}\" is unavailable`)\n }\n const spec: ContinuableStartSpec = {\n provider: SUBAGENT_PROVIDER,\n label: input.label,\n request: {\n prompt: [{ type: 'text', text: input.prompt }],\n parent,\n toolFilter: WORKER_TOOL_FILTER,\n persona: input.persona,\n maxDepth: 1,\n ...(input.model === undefined ? {} : { agentOptions: { model: input.model } }),\n },\n signal,\n }\n const start: ContinuableStart = await this.ctx.subagents.startContinuable(spec)\n return { childId: start.childId, messageId: start.messageId }\n }\n\n /**\n * 中断 continuable child 的当前轮次。fire-and-return:cancel signal 发出后\n * 立即返回;child 观察到 signal 后当前轮结束,未消费的 inbox 消息保留。\n * 不存在的 target 是 accepted no-op。\n */\n interruptWorker(\n targetSessionId: SessionId,\n authority: SubagentInterruptAuthority,\n ): void {\n this.ctx.subagents.interrupt(targetSessionId, authority)\n }\n}","/**\n * stages.ts — the seven PTES StageDefinitions. exitCriteria are judgement\n * material for the Root Agent's prompt; the host never evaluates them.\n */\nimport type { StageDefinition } from './model.js'\n\nexport const STAGE_DEFINITIONS: readonly StageDefinition[] = [\n {\n id: 'pre-engagement',\n name: 'Pre-engagement',\n goal: '与用户确认目标、授权范围和交战规则,建立 PentestRun 基线。',\n instructions: '收集并确认 objectives、targets、Rules of Engagement。所有输入必须经 ask_user_question 与用户确认。',\n exitCriteria: [\n '测试目标已经明确并经用户确认',\n '授权范围(targets / 排除项)已经记录',\n 'Rules of Engagement 已确认(时间窗、强度、凭据模式)',\n ],\n deliverables: ['scope-summary'],\n agentIds: [],\n },\n {\n id: 'intelligence-gathering',\n name: 'Intelligence Gathering',\n goal: '获得足够的目标资产、服务和技术栈信息。',\n instructions: '尽可能建立目标攻击面认知。避免重复已经完成的侦察;复用 pentest/intelligence-gathering/ 下已有成果。',\n exitCriteria: [\n '目标范围已经明确',\n '主要资产已经识别',\n '重要开放服务已经识别',\n 'Web/API 技术栈已有基本认知',\n ],\n deliverables: ['assets', 'services', 'technology-summary'],\n agentIds: ['recon', 'web'],\n },\n {\n id: 'threat-modeling',\n name: 'Threat Modeling',\n goal: '从攻击者视角梳理攻击路径与优先级。',\n instructions: '基于情报阶段成果建模:入口、信任边界、高价值资产、候选攻击路径。',\n exitCriteria: [\n '攻击面已梳理成结构化模型',\n '候选攻击路径已按价值与可行性排序',\n '明确了后续验证的优先级清单',\n ],\n deliverables: ['threat-model'],\n agentIds: ['threat-model'],\n },\n {\n id: 'vulnerability-analysis',\n name: 'Vulnerability Analysis',\n goal: '识别并评估候选安全问题。',\n instructions: '针对威胁模型优先级验证候选问题,输出带证据的 findings。',\n exitCriteria: [\n '优先攻击路径均已分析',\n '候选问题有可复验的证据支撑',\n '每个问题标注了置信度与建议验证方式',\n ],\n deliverables: ['findings'],\n agentIds: ['web', 'vulnerability'],\n },\n {\n id: 'exploitation',\n name: 'Exploitation',\n goal: '在授权范围内验证可利用性并确认影响。',\n instructions: '只验证已确认的候选问题;控制强度与影响;保留过程证据。',\n exitCriteria: [\n '高价值候选问题已完成验证(可利用 / 不可利用)',\n '每次验证有可复现步骤与证据',\n '未验证项已记录原因',\n ],\n deliverables: ['validation-results'],\n agentIds: ['validation'],\n },\n {\n id: 'post-exploitation',\n name: 'Post Exploitation',\n goal: '评估横向移动、持久性与业务影响。',\n instructions: '基于已验证的立足点评估影响范围;遵守 RoE 边界;不做超出授权的影响操作。',\n exitCriteria: [\n '影响范围已评估',\n '业务影响已量化或明确描述',\n '清理与恢复动作已记录',\n ],\n deliverables: ['impact-assessment'],\n agentIds: ['impact'],\n },\n {\n id: 'reporting',\n name: 'Reporting',\n goal: '产出最终交付报告。',\n instructions: 'reporter 读取整个 pentest/ 目录,整理最终报告写入 reporting/report.md。报告是普通 Stage:delegate reporter 即可。',\n exitCriteria: [\n 'report.md 已生成且覆盖全部阶段成果',\n '每个确认的问题有证据、影响与修复建议',\n '用户已确认报告可交付',\n ],\n deliverables: ['report.md'],\n agentIds: ['reporting'],\n },\n]\n\nexport function stageDefinition(stage: string): StageDefinition | undefined {\n return STAGE_DEFINITIONS.find(definition => definition.id === stage)\n}\n","/**\n * model.ts — the 6 domain concepts (see docs/plan.md §1 and CONTEXT.md).\n * Deliverables are files; there are no store entities beyond Delegation records.\n */\n\nexport const STAGE_IDS = [\n 'pre-engagement',\n 'intelligence-gathering',\n 'threat-modeling',\n 'vulnerability-analysis',\n 'exploitation',\n 'post-exploitation',\n 'reporting',\n] as const\n\nexport type StageId = (typeof STAGE_IDS)[number]\n\n/** Stage 生命周期状态(run.json 记录;pending → active → reviewing → completed)。 */\nexport type StageStatus = 'pending' | 'active' | 'reviewing' | 'completed'\n\n/** 阶段目录名:`01-pre-engagement` … `07-reporting`(与 STAGE_IDS 同序)。 */\nexport function stageDir(stage: StageId): string {\n const index = STAGE_IDS.indexOf(stage)\n return `${String(index + 1).padStart(2, '0')}-${stage}`\n}\n\nexport interface StageDefinition {\n readonly id: StageId\n readonly name: string\n readonly goal: string\n readonly instructions: string\n /** Judged by the Root Agent's prompt — never by TypeScript rules. */\n readonly exitCriteria: readonly string[]\n readonly deliverables: readonly string[]\n readonly agentIds: readonly string[]\n}\n\nexport interface AgentProfile {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly systemPrompt: string\n readonly skills: readonly string[]\n readonly mcpServers: readonly string[]\n readonly model?: string\n}\n\n/**\n * Delegation 生命周期状态。\n *\n * - starting: child 已创建但尚未接受初始 prompt\n * - active: durable child 已建立,可以持续交互\n * - interrupted: 当前执行被中断,但 Delegation/Session 仍可继续\n * - closed: PTES Root 明确结束这个 Delegation\n * - failed: child provisioning / infrastructure 出错\n *\n * child 某一轮 idle 不代表 Delegation completed —— idle 是 DSH runtime 状态,\n * active/closed 是 PTES domain 状态。\n */\nexport type DelegationStatus =\n | 'starting'\n | 'active'\n | 'interrupted'\n | 'closed'\n | 'failed'\n\n/**\n * One Delegation = one DSH child session. `objective` and `taskPrompt` are\n * an immutable snapshot of why the Root Agent created this worker.\n */\nexport interface Delegation {\n readonly id: string\n readonly stageId: StageId\n readonly agentId: string\n sessionId?: string\n readonly objective: string\n readonly taskPrompt: string\n readonly workspaceDir: string\n status: DelegationStatus\n resultSummary?: string\n readonly createdAt: string\n finishedAt?: string\n}\n\nexport interface StageEntry {\n readonly stage: StageId\n readonly enteredAt: string\n readonly reason?: string\n}\n\nexport interface PentestRun {\n readonly schemaVersion: 1\n readonly id: string\n readonly createdAt: string\n /** User-confirmed test entries; recorded on first delegation after confirmation. */\n targets: string[]\n rulesOfEngagement?: string\n /** 产出语言(pre-engagement 记录,默认 zh-CN);宿主生成文件用它。 */\n language?: string\n /** run 状态:active(缺省)→ 最后 stage(reporting)完成时 completed。 */\n status?: 'active' | 'completed'\n currentStage: StageId | null\n readonly stageHistory: StageEntry[]\n /** 各阶段生命周期状态(缺省视为 pending;currentStage 为 active)。 */\n stageStatuses?: Partial<Record<StageId, StageStatus>>\n delegations: Delegation[]\n}\n\nexport function nextStage(stage: StageId): StageId | undefined {\n const index = STAGE_IDS.indexOf(stage)\n if (index < 0 || index === STAGE_IDS.length - 1) return undefined\n return STAGE_IDS[index + 1]\n}\n\nexport function isStageId(value: string): value is StageId {\n return (STAGE_IDS as readonly string[]).includes(value)\n}\n","/**\n * store.ts — the single run.json snapshot per Project (docs/workspace.md).\n * Atomic write via tmp+rename; no event log, no replay.\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isStageId, nextStage, stageDir, type Delegation, type PentestRun, type StageId } from './model.js'\n\nexport const RUN_DIR = '.dsh-pentester'\nexport const RUN_FILE = 'run.json'\n/** 工作区交付树:`<project>/workspace` = 容器 `/workspace`(共享 volume 的宿主镜像)。 */\nexport const WORKSPACE_DIR = 'workspace'\n\nexport class StoreError extends Error {}\n\nexport function runFilePath(projectDir: string): string {\n // run.json 位于 workspace 树内的 .dsh-pentester/(git 全跟踪,checkpoint/rollback 可恢复状态)。\n return join(workspaceDir(projectDir), RUN_DIR, RUN_FILE)\n}\n\nexport function workspaceDir(projectDir: string): string {\n return join(projectDir, WORKSPACE_DIR)\n}\n\n/**\n * 非异常版加载:文件不存在返回 null(不要用 try/catch 判存在性);\n * 文件损坏仍抛 StoreError(不吞损坏,防止用新 Run 覆盖坏文件)。\n */\n/**\n * 唯一 PentestRun 解析入口(docs/plan.md §6):文件不存在 → null;\n * 文件损坏 → StoreError。插件侧所有消费者统一走这里。\n */\nexport async function resolvePentestRun(projectDir: string): Promise<PentestRun | null> {\n return tryLoadRun(projectDir)\n}\n\nexport async function tryLoadRun(projectDir: string): Promise<PentestRun | null> {\n const file = runFilePath(projectDir)\n if (!existsSync(file)) return null\n let parsed: unknown\n try {\n parsed = JSON.parse(await readFile(file, 'utf8'))\n } catch (error) {\n throw new StoreError(`run.json is corrupted: ${error instanceof Error ? error.message : String(error)}`)\n }\n return validateRun(parsed, file)\n}\n\n/** 兼容入口:tryLoadRun 的 undefined 形态(调用方要区分“缺失”时请用 tryLoadRun)。 */\nexport async function loadRun(projectDir: string): Promise<PentestRun | undefined> {\n return (await tryLoadRun(projectDir)) ?? undefined\n}\n\nexport async function ensureRun(projectDir: string): Promise<PentestRun> {\n const existing = await loadRun(projectDir)\n if (existing !== undefined) return existing\n const created: PentestRun = {\n schemaVersion: 1,\n id: crypto.randomUUID(),\n createdAt: new Date().toISOString(),\n targets: [],\n currentStage: 'pre-engagement',\n stageHistory: [{ stage: 'pre-engagement', enteredAt: new Date().toISOString() }],\n delegations: [],\n }\n await saveRun(projectDir, created)\n return created\n}\n\nexport async function saveRun(projectDir: string, run: PentestRun): Promise<void> {\n const file = runFilePath(projectDir)\n await mkdir(join(workspaceDir(projectDir), RUN_DIR), { recursive: true })\n // 唯一 tmp 文件名:防止 updateRun 的串行队列与 delegations 的直接 saveRun 并发\n // 写同一 tmp 文件(一个 rename 成功后另一个找不到源文件 → ENOENT)。\n const tmp = `${file}.${crypto.randomUUID().slice(0, 8)}.tmp`\n await writeFile(tmp, `${JSON.stringify(run, null, 2)}\\n`)\n await rename(tmp, file)\n}\n\n// ── 串行写保护(docs/plan.md §7)────────────────────────────────────────\n\n/** 每个 projectDir 一个 pending write promise,形成自然串行队列。 */\nconst serialQueue = new Map<string, Promise<void>>()\n\n/**\n * 串行 read-modify-write:读 run.json → 回调修改 → 原子写回。\n * 同一 projectDir 的并发调用自动排队,防止 lost update。\n * 回调在锁内同步/异步执行,返回值忽略(run 是 mutable 引用)。\n */\nexport async function updateRun(\n projectDir: string,\n fn: (run: PentestRun) => void | Promise<void>,\n): Promise<void> {\n const prev = serialQueue.get(projectDir) ?? Promise.resolve()\n const next = prev.then(async () => {\n const run = await resolvePentestRun(projectDir)\n if (run === null) throw new StoreError('cannot update a PentestRun that does not exist')\n await fn(run)\n await saveRun(projectDir, run)\n })\n // 不 await:让调用方可以 fire-and-forget(不等待写回完成)。\n // 但把链尾存回 Map,后续调用排在这个 promise 后面。\n serialQueue.set(projectDir, next.catch(() => undefined).then(() => {}))\n return next\n}\n\n/** Linear advance only; the host never judges information sufficiency. */\nexport function advanceStage(run: PentestRun, reason: string): StageId | null {\n if (run.currentStage === null || run.status === 'completed') {\n throw new StoreError('run is already completed; cannot advance')\n }\n const current = run.currentStage\n const target = nextStage(current)\n if (target === undefined) {\n // 最后 stage(reporting)完成 → run completed,currentStage = null(§23)。\n const statuses = { ...(run.stageStatuses ?? {}) }\n statuses[current] = 'completed'\n run.stageStatuses = statuses\n run.status = 'completed'\n run.currentStage = null\n return null\n }\n const statuses = { ...(run.stageStatuses ?? {}) }\n statuses[current] = 'completed'\n statuses[target] = 'active'\n run.stageStatuses = statuses\n run.currentStage = target\n run.stageHistory.push({ stage: target, enteredAt: new Date().toISOString(), reason })\n return target\n}\n\n/** 当前 stage 状态(缺省:currentStage=active,其余=pending)。 */\n\n/** 把当前 stage 标为 reviewing(最后一个 delegation 结算时调用)。 */\nexport function markStageReviewing(run: PentestRun): void {\n if (run.currentStage === null) return\n run.stageStatuses = { ...(run.stageStatuses ?? {}), [run.currentStage]: 'reviewing' }\n}\n\n/** 当前 stage 的 delegation 目录:`workspace/stages/<NN>-<stage>/delegations/`。 */\nexport function stageDelegationsDir(projectDir: string, stage: StageId): string {\n return join(workspaceDir(projectDir), 'stages', stageDir(stage), 'delegations')\n}\n\n/** 某 delegation 的工作区目录:`workspace/stages/<NN>-<stage>/delegations/D-00N`。 */\nexport function delegationWorkspaceDir(projectDir: string, stage: StageId, id: string): string {\n return join(stageDelegationsDir(projectDir, stage), id)\n}\n\nexport function nextDelegationId(run: PentestRun): string {\n let max = 0\n for (const delegation of run.delegations) {\n const match = /^D-(\\d+)$/.exec(delegation.id)\n if (match !== null) max = Math.max(max, Number(match[1]))\n }\n return `D-${String(max + 1).padStart(3, '0')}`\n}\n\nexport function findDelegation(run: PentestRun, id: string): Delegation | undefined {\n return run.delegations.find(delegation => delegation.id === id)\n}\n\nfunction validateRun(value: unknown, file: string): PentestRun {\n if (value === null || typeof value !== 'object') {\n throw new StoreError(`${file}: run.json must be an object`)\n }\n const record = value as Record<string, unknown>\n if (record.schemaVersion !== 1) {\n throw new StoreError(`${file}: unsupported schemaVersion ${String(record.schemaVersion)}`)\n }\n if (record.currentStage !== null\n && (typeof record.currentStage !== 'string' || !isStageId(record.currentStage))) {\n throw new StoreError(`${file}: invalid currentStage`)\n }\n if (!Array.isArray(record.delegations)) {\n throw new StoreError(`${file}: delegations must be an array`)\n }\n return record as unknown as PentestRun\n}\n","/**\n * workspace.ts — 工作区布局初始化与宿主侧产物。\n *\n * 固定骨架(每次 run 结构完全一致,见 docs/workspace.md):\n *\n * <project>/workspace/ = 容器 /workspace(共享 volume 的宿主镜像)\n * ├── .gitignore # traffic/ *.pcap *.mitm tmp/ cache/ *.log\n * ├── STATUS.md # 宿主自动生成的可读状态\n * ├── target/ target.json scope/ roe/ inputs/\n * ├── assets/ assets.json\n * ├── stages/ <NN>-<stage>/ summary.md delegations/\n * ├── findings/\n * ├── report/\n * └── traffic/\n *\n * 宿主侧状态(不随 volume 同步):<project>/.dsh-pentester/run.json、\n * workspace.json、events.jsonl(append-only)。\n */\nimport { mkdir, readFile, writeFile, appendFile, copyFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { STAGE_IDS, stageDir, type PentestRun, type StageId } from './model.js'\nimport { RUN_DIR, workspaceDir } from './store.js'\n\nexport interface WorkspaceMeta {\n readonly schemaVersion: 1\n readonly id: string\n readonly target?: string\n readonly language: string\n readonly createdAt: string\n readonly gitBranch: string\n}\n\nexport function workspaceFilePath(projectDir: string): string {\n return join(workspaceDir(projectDir), RUN_DIR, 'workspace.json')\n}\n\nexport function eventsFilePath(projectDir: string): string {\n return join(workspaceDir(projectDir), RUN_DIR, 'events.jsonl')\n}\n\n/** 事件行(append-only;宿主侧审计)。 */\nexport interface WorkspaceEvent {\n readonly ts: string\n readonly type: string\n readonly data?: unknown\n}\n\n/** 追加一条事件(失败不阻塞主流程)。 */\nexport async function appendEvent(projectDir: string, event: WorkspaceEvent): Promise<void> {\n try {\n await appendFile(\n eventsFilePath(projectDir),\n `${JSON.stringify({ ts: event.ts, type: event.type, data: event.data } as WorkspaceEvent)}\\n`,\n 'utf8',\n )\n } catch {\n // best-effort audit trail\n }\n}\n\n/**\n * 初始化工作区固定骨架 + 宿主侧状态文件。幂等:已存在则只补齐缺失目录。\n * @param target 初始目标(pre-engagement 确认后写入 target/target.json)。\n * @param scope 用户确认后的 Scope 文本(写入 target/scope.md,不做机器 enforcement)。\n * @param roe 用户确认后的 RoE / Authorization 事实(写入 target/roe.md,不做程序级语义解析)。\n */\nexport async function initWorkspace(\n projectDir: string,\n options: { target?: string; language?: string; scope?: string; roe?: string } = {},\n): Promise<WorkspaceMeta> {\n const root = workspaceDir(projectDir)\n const metaPath = workspaceFilePath(projectDir)\n await mkdir(join(root, RUN_DIR), { recursive: true })\n let meta: WorkspaceMeta\n if (existsSync(metaPath)) {\n meta = JSON.parse(await readFile(metaPath, 'utf8')) as WorkspaceMeta\n } else {\n meta = {\n schemaVersion: 1,\n id: crypto.randomUUID(),\n target: options.target,\n language: options.language ?? 'zh-CN',\n createdAt: new Date().toISOString(),\n gitBranch: 'main',\n }\n await writeFile(metaPath, `${JSON.stringify(meta, null, 2)}\\n`, 'utf8')\n await appendEvent(projectDir, { ts: meta.createdAt, type: 'run.created', data: { target: meta.target } })\n }\n await mkdir(root, { recursive: true })\n const dirs = [\n 'target/inputs',\n 'assets', 'findings', 'report', 'traffic',\n ...STAGE_IDS.map(stage => join('stages', stageDir(stage), 'delegations')),\n ]\n for (const dir of dirs) {\n await mkdir(join(root, dir), { recursive: true })\n }\n const gitignore = join(root, '.gitignore')\n if (!existsSync(gitignore)) {\n // §25:全 Workspace git 跟踪 —— work/ traffic/ pcap/mitm 都不忽略(完整回溯)。\n await writeFile(gitignore, `tmp/\\ncache/\\n*.log\\n`, 'utf8')\n }\n if (options.target !== undefined && meta.target === undefined) {\n meta = { ...meta, target: options.target }\n await writeFile(metaPath, `${JSON.stringify(meta, null, 2)}\\n`, 'utf8')\n }\n await writeTarget(projectDir, meta.target)\n if (options.scope !== undefined) {\n await writeFile(join(root, 'target', 'scope.md'), options.scope.endsWith('\\n') ? options.scope : `${options.scope}\\n`, 'utf8')\n }\n if (options.roe !== undefined) {\n await writeFile(join(root, 'target', 'roe.md'), options.roe.endsWith('\\n') ? options.roe : `${options.roe}\\n`, 'utf8')\n }\n return meta\n}\n\n/** 写 target/target.json(幂等;仅当文件不存在或 target 变化时更新)。 */\nexport async function writeTarget(projectDir: string, target: string | undefined): Promise<void> {\n if (target === undefined) return\n const file = join(workspaceDir(projectDir), 'target', 'target.json')\n const existing = existsSync(file) ? JSON.parse(await readFile(file, 'utf8')) as { target?: string } : undefined\n if (existing?.target === target) return\n await writeFile(file, `${JSON.stringify({ target, updatedAt: new Date().toISOString() }, null, 2)}\\n`, 'utf8')\n}\n\n/**\n * 写 stage 的 summary.md(Stage handoff)。内容由 Root 通过\n * pentester_advance_stage(summary) 提供,Host 只负责写磁盘、不解析。\n */\nexport async function writeStageSummary(\n projectDir: string,\n stage: StageId,\n summary: string,\n): Promise<void> {\n const text = summary.trim()\n if (text === '') return\n await writeFile(\n join(workspaceDir(projectDir), 'stages', stageDir(stage), 'summary.md'),\n `# ${stageDir(stage)}\\n\\n${text}\\n`,\n 'utf8',\n )\n}\n\n/**\n * 提升某 delegation 目录中的 canonical 产物(仅 threat-model.md)。\n * assets.json 和 findings.md 现在由 promoteAssets / promoteFindings\n * (src/pentest/)负责聚合提升,不再走简单 copyFile。\n */\nexport async function promoteDeliverables(\n projectDir: string,\n dir: string,\n): Promise<void> {\n const root = workspaceDir(projectDir)\n const mappings: ReadonlyArray<readonly [string, string]> = [\n ['threat-model.md', 'findings/threat-model.md'],\n ]\n for (const [name, relative] of mappings) {\n const source = join(dir, name)\n if (!existsSync(source)) continue\n const target = join(root, relative)\n await mkdir(dirname(target), { recursive: true })\n await copyFile(source, target)\n }\n}\n\n/**\n * 将 Pre-engagement 用户确认的完整授权信息写入\n * `target/inputs/pre-engagement.md` 作为原始输入 provenance。\n * 在 bootstrap(首次 advance)时调用。\n */\nexport async function writePreEngagementInput(\n projectDir: string,\n options: {\n targets: readonly string[]\n scope: string\n roe: string\n language: string\n },\n): Promise<void> {\n const inputsDir = join(workspaceDir(projectDir), 'target', 'inputs')\n await mkdir(inputsDir, { recursive: true })\n const content = [\n '# Pre-engagement Confirmation',\n '',\n `**Recorded**: ${new Date().toISOString()}`,\n '',\n '## Target',\n ...options.targets.map(t => `- ${t}`),\n '',\n '## Scope',\n options.scope,\n '',\n '## Rules of Engagement',\n options.roe,\n '',\n '## Language',\n options.language,\n '',\n ].join('\\n')\n await writeFile(join(inputsDir, 'pre-engagement.md'), `${content}\\n`, 'utf8')\n}\n","/**\n * delegations.ts — Delegation lifecycle: one Delegation = one DSH continuable\n * child Session (docs/plan.md §3, §26).\n *\n * Worker execution uses the DeepSeek Harness official Continuable Subagent seam\n * (`ctx.subagents.startContinuable()` → provider `spawn`). The child is a\n * durable Session that survives across turns and can accept followup messages\n * from Root or user. The plugin only manages PTES domain state.\n *\n * 目录契约(docs/workspace.md):`workspace/stages/<NN>-<stage>/delegations/D-00N/`\n * input/ work/ artifacts/ evidence/ result.md\n * Worker 只写自己的 delegation 目录;宿主写 input/task_prompt.md 快照。\n * result.md 是当前 Delegation 的\"最新正式可交付结果\",不是 child Session\n * 终止标记。Worker 后续可以更新 result.md。\n */\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { Agent } from '@deepseek-ai/dsh-agent'\nimport type { SessionId } from '@deepseek-ai/dsh-session'\nimport type { AgentProfile, Delegation, PentestRun } from './model.js'\nimport { stageDefinition } from './stages.js'\nimport {\n delegationWorkspaceDir,\n findDelegation,\n markStageReviewing,\n nextDelegationId,\n saveRun,\n updateRun,\n} from './store.js'\nimport { appendEvent } from './workspace.js'\nimport { DshClient, type CreateWorkerInput } from './dsh.js'\nimport { DockerRuntime } from './docker/runtime.js'\n\n/** Profile → category 映射:决定 compact catalog 中哪些工具标记为 Recommended。 */\nconst PROFILE_CATEGORIES: Record<string, string[]> = {\n recon: ['network-discovery', 'dns-osint', 'web-discovery', 'network'],\n web: ['web-discovery', 'vulnerability'],\n vulnerability: ['vulnerability', 'web-discovery'],\n validation: ['vulnerability', 'password', 'smb-ad'],\n impact: ['smb-ad', 'network', 'misc'],\n reporting: [],\n 'threat-model': [],\n}\n\nexport interface Assignment {\n readonly agent: string\n readonly objective: string\n readonly taskPrompt: string\n}\n\nexport class DelegationError extends Error {}\n\nexport interface DelegateDeps {\n readonly projectDir: string\n readonly run: PentestRun\n readonly profiles: ReadonlyMap<string, AgentProfile>\n readonly rootSessionId: string\n /** 发起调用的 live Root Agent(continuable child parent)。 */\n readonly parent: Agent\n /** 调用方取消信号。 */\n readonly signal: AbortSignal\n}\n\n/**\n * Worker persona(官方 ContinuableStartSpec.request.persona):常驻规则 +\n * AgentProfile 角色。Worker 是长期存在的 continuable child,可能收到多轮\n * 来自 Root 或用户的消息。\n */\nconst WORKER_BASELINE = `You are a long-lived PTES execution worker — a continuable child agent.\n\nYou may receive multiple rounds of tasks from:\n- The Root Agent (via send_message)\n- A human user (direct chat in your session)\n\nAll messages belong to the same ongoing Delegation Session. You must retain\ncontext from previous turns and build on earlier results.\n\nYour responsibilities:\n- Execute the assigned task using available tools.\n- Stay inside the Primary Target, Scope, and Rules of Engagement.\n- Produce reusable artifacts and evidence.\n- Write or update result.md as the current formal deliverable of this Delegation.\n- When an important finding affects the Root's next step, use the report tool\n to notify the Root Agent proactively.\n\nYou must NOT:\n- Advance or rollback PTES stages (Root-only).\n- Create or cancel delegations (Root-only).\n- Ask the user questions (Root-only).\n- Create more subagents or fork yourself.\n- Expand scope beyond what is authorized.\n\nStanding rules:\n- Operate only within the authorized assessment recorded for this run.\n- Execute commands via available tools.\n- NEVER run git commands. The host owns git checkpoints; .git is not present\n in the container.\n- ALL container network traffic is recorded (pcap + optional mitmproxy on\n :8080). This is an audit trail, not a limitation.\n- Write ALL output in the language of your task prompt: your final response\n AND the content of every file you generate, including reports. Tool raw\n output stays as-is.\n- One round ending does NOT mean your Delegation is permanently over. You may\n receive follow-up messages from Root or a user.\n- Your final response each round must summarize: what you did, what you found,\n which files you wrote, and what you recommend investigating next.`\n\nexport function buildWorkerPersona(profile: AgentProfile, catalogText?: string, toolPrompt?: string): string {\n const parts = [WORKER_BASELINE]\n if (toolPrompt !== undefined && toolPrompt.length > 0) {\n parts.push(toolPrompt)\n }\n parts.push(`# Agent Profile: ${profile.name}`, profile.systemPrompt)\n if (catalogText !== undefined && catalogText.length > 0) {\n parts.push(catalogText)\n }\n return parts.join('\\n\\n')\n}\n\n/**\n * Worker 首轮 user message(官方 ContinuableStartSpec.request.prompt):\n * standalone task context。官方 continuable child 不继承 parent transcript,\n * 所以这里必须自包含:Delegation ID / Stage / Target / Scope / RoE /\n * 目录路径 / 完成契约 / task_prompt。\n */\nexport function buildWorkerTaskPrompt(options: {\n readonly run: PentestRun\n readonly delegation: Delegation\n readonly projectDir: string\n}): string {\n const { run, delegation, projectDir } = options\n const stage = stageDefinition(delegation.stageId)\n const containerDir = delegation.workspaceDir.startsWith(projectDir)\n ? delegation.workspaceDir.slice(projectDir.length).replace(/\\\\/g, '/')\n : `/workspace/stages/${stage === undefined ? delegation.stageId : stage.id}`\n const metadata = [\n `Delegation ID: ${delegation.id}`,\n `Stage: ${delegation.stageId}${stage === undefined ? '' : ` — ${stage.name}`}`,\n `Project workspace root: /workspace (READ-ONLY outside your own directory)`,\n `Your deliverable directory: ${containerDir}`,\n ` work/ scratch working files (default container cwd)`,\n ` artifacts/ final deliverables for later workers`,\n ` evidence/ reproducible evidence (commands + outputs)`,\n ` result.md current formal deliverable — write/update it as results accumulate`,\n `Write policy: write files ONLY inside ${containerDir}; never modify`,\n ` .git/, .dsh-pentester/, target/, other delegation directories or the workspace root.`,\n run.targets.length > 0 ? `Targets: ${run.targets.join(', ')}` : 'Targets: (not yet recorded)',\n run.rulesOfEngagement === undefined ? '' : `Rules of Engagement: ${run.rulesOfEngagement}`,\n ].filter(line => line !== '')\n return [\n `# Task for ${delegation.id}`,\n '',\n ...metadata,\n '',\n `# Objective`,\n delegation.objective,\n '',\n `# task_prompt (task context from the Root Agent)`,\n delegation.taskPrompt,\n '',\n `# Completion contract`,\n `- This is a continuable session. You may receive follow-up messages.`,\n `- When you have results, write or update result.md in ${containerDir}`,\n ` (summary + what you found). result.md is the current formal deliverable —`,\n ` it does NOT terminate your session.`,\n `- If you discover something important that affects the Root's next step,`,\n ` use the report tool to notify the Root Agent.`,\n ].join('\\n')\n}\n\n/**\n * 把 tools.json 的 categories 渲染成 compact 文本,注入 Worker persona。\n * 先输出 profile 匹配的 Recommended 工具,再输出 Other。\n * raw 格式由 gen-tools-json.sh 固定(categories: { name, bin, description, examples }[])。\n */\nfunction renderToolCatalog(raw: unknown, profileId: string): string {\n const data = raw as Record<string, unknown> | null | undefined\n if (data === null || data === undefined) return ''\n const categories = data.categories as Record<string, Array<{ name: string; description: string }>> | undefined\n if (categories === undefined) return ''\n const image = typeof data.image === 'string' ? data.image : 'dsh-pentester-kali'\n const recommended = PROFILE_CATEGORIES[profileId]\n const recommendedSet = recommended !== undefined ? new Set(recommended) : new Set<string>()\n const recLines: string[] = []\n const otherLines: string[] = []\n for (const [catName, tools] of Object.entries(categories)) {\n if (!Array.isArray(tools)) continue\n const lines = recommendedSet.has(catName) ? recLines : otherLines\n for (const tool of tools) {\n if (typeof tool.name !== 'string' || typeof tool.description !== 'string') continue\n lines.push(` ${tool.name} — ${tool.description}`)\n }\n }\n const parts: string[] = [\n '## Toolbox Capabilities',\n '',\n `Image: ${image} · All execution via \\`pentester_container_exec\\`.`,\n 'Discovery: \\`tool-list\\` for full catalog, \\`tool-info <name>\\` for single tool details.',\n 'If you need specific parameters, use \\`<tool> -h\\` or \\`<tool> --help\\`.',\n ]\n if (recLines.length > 0) {\n parts.push('', '### Recommended for this profile', ...recLines)\n }\n if (otherLines.length > 0) {\n parts.push('', '### Other capabilities', ...otherLines)\n }\n parts.push(\n '',\n '## Tool Selection',\n '',\n '1. Match tool to task — prefer narrow specialized tools over curl/bash scripts.',\n '2. Do NOT run multiple overlapping scanners without a specific reason.',\n '3. Broad scanners are discovery aids, not vulnerability proof.',\n '4. Validate important findings before reporting them.',\n '5. Stay strictly within Target / Scope / RoE.',\n )\n return parts.join('\\n')\n}\n\nexport class DelegationService {\n private readonly dsh: DshClient\n private readonly docker: DockerRuntime\n\n constructor(dsh: DshClient, docker: DockerRuntime) {\n this.dsh = dsh\n this.docker = docker\n }\n\n /**\n * 创建一个或多个 continuable Worker。\n *\n * 流程:\n * validate PentestRun → validate Stage → validate AgentProfile →\n * allocate D-xxx → scaffold Delegation → build standalone initial prompt →\n * persist Delegation → ctx.subagents.startContinuable() →\n * 得到 childId + messageId → Delegation.childSessionId = childId →\n * Delegation.status = active → persist run.json → return\n *\n * startContinuable() resolve 的含义只是初始 prompt 已进入 child inbox,\n * 不是 Worker 已完成任务。\n */\n async delegate(deps: DelegateDeps, assignments: readonly Assignment[]): Promise<Delegation[]> {\n if (assignments.length === 0) throw new DelegationError('assignments must not be empty')\n if (deps.run.status === 'completed' || deps.run.currentStage === null) {\n throw new DelegationError('PentestRun is completed; cannot delegate new work')\n }\n const stage = stageDefinition(deps.run.currentStage)\n if (stage === undefined) throw new DelegationError(`unknown stage: ${deps.run.currentStage}`)\n if (!this.dsh.subagentAvailable) {\n throw new DelegationError('subagent infrastructure unavailable: ctx.subagents provider \"spawn\" is not registered')\n }\n const created: Delegation[] = []\n for (const assignment of assignments) {\n const profile = deps.profiles.get(assignment.agent)\n if (profile === undefined) {\n throw new DelegationError(`unknown AgentProfile: ${assignment.agent}`)\n }\n if (!stage.agentIds.includes(profile.id)) {\n throw new DelegationError(\n `AgentProfile ${profile.id} is not attached to current stage ${deps.run.currentStage}. ` +\n `Allowed profiles: ${stage.agentIds.join(', ')}`,\n )\n }\n if (assignment.objective.trim() === '' || assignment.taskPrompt.trim() === '') {\n throw new DelegationError('objective and task_prompt must not be empty')\n }\n if (/delegations\\/D-\\d+/.test(assignment.taskPrompt)) {\n throw new DelegationError(\n 'task_prompt must not contain concrete delegation paths (e.g. delegations/D-001). ' +\n 'The Host manages D-ID allocation and directory structure. ' +\n 'Reference deliverables by their logical names (e.g. \"the recon scan results from intelligence-gathering\").',\n )\n }\n const id = nextDelegationId(deps.run)\n const dir = delegationWorkspaceDir(deps.projectDir, deps.run.currentStage, id)\n await scaffoldDelegationDir(dir, {\n id,\n stage: deps.run.currentStage,\n agent: profile.id,\n objective: assignment.objective,\n taskPrompt: assignment.taskPrompt,\n })\n const delegation: Delegation = {\n id,\n stageId: deps.run.currentStage,\n agentId: profile.id,\n objective: assignment.objective,\n taskPrompt: assignment.taskPrompt,\n workspaceDir: dir,\n status: 'starting',\n createdAt: new Date().toISOString(),\n }\n deps.run.delegations.push(delegation)\n await saveRun(deps.projectDir, deps.run)\n await appendEvent(deps.projectDir, {\n ts: new Date().toISOString(),\n type: 'delegation.created',\n data: { id, agent: profile.id, stage: deps.run.currentStage },\n })\n created.push(delegation)\n }\n await saveRun(deps.projectDir, deps.run)\n // 宿主 scaffold 推进容器,Worker 可见。\n await this.docker.pushWorkspace(deps.run.id, deps.projectDir).catch(() => undefined)\n // 解析 containerId 供 catalog 读取。\n const toolbox = await this.docker.ensureImage('kali')\n const containerId = await this.docker.ensureRunContainer({ runId: deps.run.id, toolbox, projectDir: deps.projectDir })\n // 逐个派发 continuable child。\n for (const delegation of created) {\n await this.dispatch(deps, delegation, containerId)\n }\n await saveRun(deps.projectDir, deps.run)\n return created\n }\n\n /**\n * 派发一个 delegation:创建 continuable child。\n * startContinuable() resolve 时 child 已接受 prompt 但尚未开始执行。\n * 之后 child 作为 durable Session 持续存在,可接受 followup。\n */\n private async dispatch(deps: DelegateDeps, delegation: Delegation, containerId: string): Promise<void> {\n const profile = deps.profiles.get(delegation.agentId)!\n // 读取 Toolbox 工具目录,渲染为 compact 能力摘要。\n let catalogText: string | undefined\n try {\n const raw = await this.docker.readToolCatalog(containerId)\n catalogText = renderToolCatalog(raw, delegation.agentId)\n } catch {\n // catalog 读取失败不阻塞 Worker 创建 — Worker 仍可通过 tool-list 发现。\n }\n // 读取 TOOL_PROMPT.md(工具使用指引),注入 Worker persona。\n let toolPrompt: string | undefined\n try {\n const result = await this.docker.exec(containerId, { argv: ['cat', '/pentester/PROMPT.md'] })\n toolPrompt = result.stdout\n } catch {\n // PROMPT.md 读取失败不阻塞 Worker 创建。\n }\n const input: CreateWorkerInput = {\n label: `${delegation.id} · ${profile.name}`,\n persona: buildWorkerPersona(profile, catalogText, toolPrompt),\n prompt: buildWorkerTaskPrompt({ run: deps.run, delegation, projectDir: deps.projectDir }),\n ...(profile.model === undefined ? {} : { model: profile.model }),\n }\n const start = await this.dsh.startContinuableWorker(\n input,\n deps.parent,\n deps.signal,\n )\n // child 已接受初始 prompt → 绑定 childId 并落盘。\n delegation.sessionId = start.childId\n delegation.status = 'active'\n await saveRun(deps.projectDir, deps.run)\n await appendEvent(deps.projectDir, {\n ts: new Date().toISOString(),\n type: 'delegation.dispatched',\n data: { id: delegation.id, childId: start.childId, messageId: start.messageId },\n })\n }\n\n /**\n * 关闭 PTES Delegation。\n *\n * 流程:\n * resolve D-ID → resolve childSessionId → 如有 live turn:interrupt child →\n * Delegation.status = closed → persist。\n *\n * 不删除 durable Child Session transcript。用户以后仍然可以看到历史。\n */\n async cancel(\n deps: { projectDir: string; run: PentestRun },\n delegationId: string,\n reason?: string,\n ): Promise<Delegation> {\n const delegation = findDelegation(deps.run, delegationId)\n if (delegation === undefined) throw new DelegationError(`unknown delegation: ${delegationId}`)\n // 如有 live child,中断当前轮次。\n if (delegation.sessionId !== undefined) {\n try {\n this.dsh.interruptWorker(delegation.sessionId as SessionId, { kind: 'user', parentSessionId: delegation.sessionId as SessionId })\n } catch {\n // interrupt 对不存在的 target 是 no-op;这里吞掉其他错误以免阻塞 cancel。\n }\n }\n delegation.status = 'closed'\n delegation.resultSummary = reason ?? 'closed by Root'\n delegation.finishedAt = new Date().toISOString()\n await saveRun(deps.projectDir, deps.run)\n await appendEvent(deps.projectDir, {\n ts: new Date().toISOString(),\n type: 'delegation.closed',\n data: { id: delegationId, reason },\n })\n return delegation\n }\n\n /**\n * 当前 stage 全部 delegation 是否都已 settled(没有 active/starting)。\n * 用于 advance 前的机械检查。\n */\n stageHasPendingWork(run: PentestRun, stageId: string): boolean {\n return run.delegations.some(d =>\n d.stageId === stageId && (d.status === 'active' || d.status === 'starting'))\n }\n\n /**\n * 当前 stage 全部 delegation 中没有 active/starting → 标记 reviewing。\n */\n async maybeMarkReviewing(deps: { projectDir: string; run: PentestRun }): Promise<void> {\n if (deps.run.currentStage === null) return\n if (this.stageHasPendingWork(deps.run, deps.run.currentStage)) return\n markStageReviewing(deps.run)\n await saveRun(deps.projectDir, deps.run)\n await appendEvent(deps.projectDir, {\n ts: new Date().toISOString(),\n type: 'stage.reviewing',\n data: { stage: deps.run.currentStage },\n })\n }\n\n}\n\n/** 预建 delegation 目录骨架 + input/task_prompt 快照。 */\nasync function scaffoldDelegationDir(\n dir: string,\n info: {\n id: string\n stage: string\n agent: string\n objective: string\n taskPrompt: string\n },\n): Promise<void> {\n for (const sub of ['input', 'work', 'artifacts', 'evidence']) {\n await mkdir(join(dir, sub), { recursive: true })\n }\n await writeFile(join(dir, 'input', 'task_prompt.md'), info.taskPrompt, 'utf8')\n}","/**\n * assets.ts — PentestRun canonical asset inventory promotion.\n *\n * Workers produce local `artifacts/assets.json` and `artifacts/services.json`\n * inside their delegation directories. On stage advance, the host aggregates\n * every delegation's assets from the completed stage, deduplicates them, and\n * writes the canonical `assets/assets.json` and `assets/services.json` at the\n * workspace root. Worker-local artifacts are never moved or deleted.\n *\n * Dedup keys:\n * asset: type + normalized value\n * service: asset value + protocol + port\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { workspaceDir } from '../store.js'\n\n// ── canonical types ──────────────────────────────────────────────────────────\n\nexport interface CanonicalAsset {\n readonly type: 'host' | 'ip' | 'domain' | 'subdomain' | 'application' | 'endpoint' | 'unknown'\n readonly value: string\n /** Additional metadata from the worker (e.g. OS, banners). */\n readonly meta?: Record<string, unknown>\n /** First delegation that discovered this asset. */\n readonly sourceDelegationId: string\n readonly sourceStage: string\n /** ISO timestamp of last promotion. */\n readonly updatedAt: string\n}\n\nexport interface CanonicalService {\n readonly asset: string\n readonly protocol: string\n readonly port: number\n readonly name?: string\n readonly version?: string\n readonly banner?: string\n readonly meta?: Record<string, unknown>\n readonly sourceDelegationId: string\n readonly sourceStage: string\n readonly updatedAt: string\n}\n\n// ── dedup keys ────────────────────────────────────────────────────────────────\n\nfunction assetKey(entry: Record<string, unknown>): string {\n const type = typeof entry.type === 'string' ? entry.type : 'unknown'\n const value = typeof entry.value === 'string' ? entry.value.trim().toLowerCase() : ''\n if (value === '') return ''\n return `${type}:${value}`\n}\n\nfunction serviceKey(entry: Record<string, unknown>): string {\n const asset = typeof entry.asset === 'string' ? entry.asset.trim().toLowerCase() : ''\n const protocol = typeof entry.protocol === 'string' ? entry.protocol.trim().toLowerCase() : ''\n const port = typeof entry.port === 'number' ? entry.port : 0\n if (asset === '' || protocol === '' || port === 0) return ''\n return `${asset}:${protocol}:${port}`\n}\n\n/** Normalize a worker's asset entry to canonical form. */\nfunction normalizeAsset(entry: Record<string, unknown>, sourceDelegationId: string, sourceStage: string, updatedAt: string): CanonicalAsset {\n return {\n type: (typeof entry.type === 'string' && entry.type.length > 0\n ? entry.type : 'unknown') as CanonicalAsset['type'],\n value: typeof entry.value === 'string' ? entry.value.trim() : '',\n ...(entry.meta !== undefined && typeof entry.meta === 'object' && entry.meta !== null\n ? { meta: entry.meta as Record<string, unknown> }\n : {}),\n sourceDelegationId,\n sourceStage,\n updatedAt,\n }\n}\n\n/** Normalize a worker's service entry to canonical form. */\nfunction normalizeService(entry: Record<string, unknown>, sourceDelegationId: string, sourceStage: string, updatedAt: string): CanonicalService {\n return {\n asset: typeof entry.asset === 'string' ? entry.asset.trim() : '',\n protocol: typeof entry.protocol === 'string' ? entry.protocol.trim() : '',\n port: typeof entry.port === 'number' ? entry.port : 0,\n ...(typeof entry.name === 'string' && entry.name.length > 0 ? { name: entry.name } : {}),\n ...(typeof entry.version === 'string' && entry.version.length > 0 ? { version: entry.version } : {}),\n ...(typeof entry.banner === 'string' && entry.banner.length > 0 ? { banner: entry.banner } : {}),\n ...(entry.meta !== undefined && typeof entry.meta === 'object' && entry.meta !== null\n ? { meta: entry.meta as Record<string, unknown> }\n : {}),\n sourceDelegationId,\n sourceStage,\n updatedAt,\n }\n}\n\n// ── read worker artifacts ────────────────────────────────────────────────────\n\nfunction readJsonFile(file: string): unknown {\n if (!existsSync(file)) return undefined\n try {\n return JSON.parse(readFileSync(file, 'utf8'))\n } catch {\n return undefined\n }\n}\n\nfunction readJsonArray(file: string): Record<string, unknown>[] {\n const parsed = readJsonFile(file)\n if (Array.isArray(parsed)) return parsed.filter(entry => entry !== null && typeof entry === 'object')\n return []\n}\n\n// ── public API ────────────────────────────────────────────────────────────────\n\n/**\n * Aggregate assets from every delegation directory in the completed stage,\n * deduplicate, and write the canonical `assets/assets.json` and (if any\n * services found) `assets/services.json`.\n */\nexport async function promoteAssets(\n projectDir: string,\n stage: string,\n delegationDirs: readonly string[],\n delegationIds: readonly string[],\n): Promise<void> {\n const root = workspaceDir(projectDir)\n const updatedAt = new Date().toISOString()\n\n // ── assets ──\n const assetMap = new Map<string, CanonicalAsset>()\n for (let index = 0; index < delegationDirs.length; index += 1) {\n const delegationId = delegationIds[index] ?? `D-${String(index + 1).padStart(3, '0')}`\n const entries = readJsonArray(join(delegationDirs[index], 'assets.json'))\n for (const entry of entries) {\n const key = assetKey(entry)\n if (key === '') continue\n if (!assetMap.has(key)) {\n assetMap.set(key, normalizeAsset(entry, delegationId, stage, updatedAt))\n }\n }\n }\n if (assetMap.size > 0) {\n const assetsDir = join(root, 'assets')\n await mkdir(assetsDir, { recursive: true })\n const canonical = [...assetMap.values()].sort((a, b) => a.value.localeCompare(b.value))\n await writeFile(join(assetsDir, 'assets.json'), `${JSON.stringify(canonical, null, 2)}\\n`, 'utf8')\n }\n\n // ── services ──\n const serviceMap = new Map<string, CanonicalService>()\n for (let index = 0; index < delegationDirs.length; index += 1) {\n const delegationId = delegationIds[index] ?? `D-${String(index + 1).padStart(3, '0')}`\n const entries = readJsonArray(join(delegationDirs[index], 'services.json'))\n for (const entry of entries) {\n const key = serviceKey(entry)\n if (key === '') continue\n if (!serviceMap.has(key)) {\n serviceMap.set(key, normalizeService(entry, delegationId, stage, updatedAt))\n }\n }\n }\n if (serviceMap.size > 0) {\n const assetsDir = join(root, 'assets')\n await mkdir(assetsDir, { recursive: true })\n const canonical = [...serviceMap.values()].sort((a, b) =>\n `${a.asset}:${a.protocol}:${a.port}`.localeCompare(`${b.asset}:${b.protocol}:${b.port}`))\n await writeFile(join(assetsDir, 'services.json'), `${JSON.stringify(canonical, null, 2)}\\n`, 'utf8')\n }\n}","/**\n * findings.ts — PentestRun canonical finding registry promotion.\n *\n * Workers produce `artifacts/findings.md` (human-readable) and optionally\n * `artifacts/findings.json` (structured) inside their delegation directories.\n * On stage advance, the host aggregates every delegation's findings from the\n * completed stage, indexes them in `findings/findings.json`, and writes each\n * delegation's finding detail as `findings/<delegationId>-findings.md` with a\n * provenance header. Worker-local artifacts are never moved.\n *\n * Dedup: within a single stage, findings from the same delegation are kept\n * as one entry (the delegation's findings.md is the authoritative unit).\n * Exploitation updates to an existing finding are reflected in the index\n * when the exploitation stage advances.\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { workspaceDir } from '../store.js'\n\n// ── canonical types ──────────────────────────────────────────────────────────\n\nexport interface CanonicalFindingEntry {\n readonly sourceDelegationId: string\n readonly sourceStage: string\n readonly detailFile: string\n readonly updatedAt: string\n}\n\n// ── public API ────────────────────────────────────────────────────────────────\n\n/**\n * Aggregate findings from every delegation directory in the completed stage,\n * index them in `findings/findings.json`, and write each delegation's detail\n * as `findings/<delegationId>-findings.md`.\n *\n * If a delegation produces `artifacts/findings.md`, its content is copied\n * into the canonical detail file with a provenance header.\n */\nexport async function promoteFindings(\n projectDir: string,\n stage: string,\n delegationDirs: readonly string[],\n delegationIds: readonly string[],\n): Promise<void> {\n const root = workspaceDir(projectDir)\n const findingsDir = join(root, 'findings')\n await mkdir(findingsDir, { recursive: true })\n const updatedAt = new Date().toISOString()\n\n const entries: CanonicalFindingEntry[] = []\n\n // Load existing index so we can update (not replace) entries from earlier stages.\n const existingIndex = loadExistingIndex(findingsDir)\n\n for (let index = 0; index < delegationDirs.length; index += 1) {\n const delegationId = delegationIds[index] ?? `D-${String(index + 1).padStart(3, '0')}`\n const delegationDir = delegationDirs[index]\n const sourceFile = join(delegationDir, 'findings.md')\n if (!existsSync(sourceFile)) continue\n\n const content = readFileSync(sourceFile, 'utf8').trim()\n if (content === '') continue\n\n const detailFile = `${delegationId}-findings.md`\n const detailPath = join(findingsDir, detailFile)\n\n // Write detail file with provenance header.\n await writeFile(\n detailPath,\n `# ${delegationId} Findings\\n\\n`\n + `**Source Stage**: ${stage}\\n`\n + `**Updated**: ${updatedAt}\\n\\n`\n + `---\\n\\n`\n + `${content}\\n`,\n 'utf8',\n )\n\n // Upsert into index: same delegationId → update timestamp.\n const existing = existingIndex.get(delegationId)\n if (existing !== undefined) {\n existingIndex.set(delegationId, { ...existing, updatedAt, sourceStage: stage })\n } else {\n entries.push({ sourceDelegationId: delegationId, sourceStage: stage, detailFile, updatedAt })\n }\n }\n\n // Merge: existing entries that weren't touched by this stage stay.\n for (const [id, entry] of existingIndex) {\n if (!delegationIds.includes(id)) {\n entries.push(entry)\n }\n }\n\n // Sort by delegation id for stable output.\n entries.sort((a, b) => a.sourceDelegationId.localeCompare(b.sourceDelegationId))\n\n if (entries.length > 0) {\n await writeFile(\n join(findingsDir, 'findings.json'),\n `${JSON.stringify(entries, null, 2)}\\n`,\n 'utf8',\n )\n }\n}\n\n// ── helpers ───────────────────────────────────────────────────────────────────\n\nfunction loadExistingIndex(findingsDir: string): Map<string, CanonicalFindingEntry> {\n const file = join(findingsDir, 'findings.json')\n if (!existsSync(file)) return new Map()\n try {\n const parsed = JSON.parse(readFileSync(file, 'utf8'))\n if (!Array.isArray(parsed)) return new Map()\n const map = new Map<string, CanonicalFindingEntry>()\n for (const entry of parsed) {\n if (entry !== null && typeof entry === 'object'\n && typeof (entry as Record<string, unknown>).sourceDelegationId === 'string') {\n const id = (entry as Record<string, unknown>).sourceDelegationId as string\n map.set(id, entry as CanonicalFindingEntry)\n }\n }\n return map\n } catch {\n return new Map()\n }\n}","/**\n * tools.ts — the four Root-Agent tools (docs/plan.md §0). The host checks\n * caller identity, stage linearity and path legality only; information\n * sufficiency is always the Root Agent's judgement.\n */\nimport type { Agent } from '@deepseek-ai/dsh-agent'\nimport { isStageId, nextStage, stageDir, type AgentProfile, type PentestRun, type StageId } from './model.js'\nimport { trustedCallerFromExec, type TrustedCaller } from './dsh.js'\nimport { DelegationService, type Assignment } from './delegations.js'\nimport { advanceStage, resolvePentestRun, saveRun } from './store.js'\nimport { stageDefinition } from './stages.js'\nimport { appendEvent, initWorkspace, promoteDeliverables, writePreEngagementInput, writeStageSummary } from './workspace.js'\nimport { promoteAssets } from './pentest/assets.js'\nimport { promoteFindings } from './pentest/findings.js'\n\nexport interface DshToolsService {\n register(definition: {\n name: string\n description: string\n parameters?: Record<string, unknown>\n output?: { schema: unknown; render?: (args: unknown, value: unknown) => unknown }\n execute: (args: Record<string, unknown>, exec?: unknown) => Promise<unknown> | unknown\n }): unknown\n}\n\n/**\n * 宿主发布的 `pentester` service(index.ts `ctx.provide`)。preset 行\n * (run-state.mjs)只负责在 pentester preset 的 standing scope 里注册工具,\n * 工具实现全部留在宿主 bundle(本文件 + worker-tools.ts)。\n */\nexport interface PentesterService {\n registerRootTools(tools: DshToolsService): readonly string[]\n registerContainerExecTool(tools: { register(definition: Record<string, unknown>): unknown }): void\n}\n\nexport const ROOT_TOOL_SCHEMAS: Readonly<Record<string, Record<string, unknown>>> = {\n pentester_delegate: {\n type: 'object',\n additionalProperties: false,\n required: ['assignments'],\n properties: {\n assignments: {\n type: 'array',\n minItems: 1,\n description: 'Parallel delegations; each spawns one continuable worker session with its own deliverable directory.',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['agent', 'objective', 'task_prompt'],\n properties: {\n agent: { type: 'string', description: 'AgentProfile id attached to the current Stage (see Available AgentProfiles in your run state).' },\n objective: { type: 'string', description: 'One-line objective (recorded in run.json).' },\n task_prompt: { type: 'string', description: 'Full task context for the worker: known facts, gaps to close, references to existing deliverables.' },\n },\n },\n },\n },\n },\n pentester_cancel_delegation: {\n type: 'object',\n additionalProperties: false,\n required: ['delegation_id'],\n properties: {\n delegation_id: { type: 'string' },\n reason: { type: 'string' },\n },\n },\n pentester_advance_stage: {\n type: 'object',\n additionalProperties: false,\n required: ['summary'],\n properties: {\n summary: { type: 'string', description: 'Stage handoff summary (what was done, confirmed, key results, next-stage focus). The host writes it to stages/<stage>/summary.md verbatim and never parses it.' },\n run: {\n type: 'object',\n additionalProperties: false,\n description: 'Only for the FIRST advance of a new run (bootstrap): records the user-confirmed targets/RoE and output language. The host creates the PentestRun and completes pre-engagement.',\n properties: {\n targets: { type: 'array', items: { type: 'string' } },\n rules_of_engagement: { type: 'string' },\n language: { type: 'string', description: 'Output language for host-generated files (e.g. zh-CN, en).' },\n },\n },\n },\n },\n pentester_rollback_stage: {\n type: 'object',\n additionalProperties: false,\n required: ['stage', 'reason'],\n properties: {\n stage: { type: 'string', description: 'Domain StageId to roll back to (e.g. intelligence-gathering); its completed checkpoint becomes the new timeline root.' },\n reason: { type: 'string', description: 'Why the stage result needs rework.' },\n },\n },\n}\n\nexport interface RootToolDeps {\n readonly delegations: DelegationService\n readonly profiles: ReadonlyMap<string, AgentProfile>\n readonly git: {\n init(projectDir: string, target?: string): Promise<void>\n checkpointStage(projectDir: string, stage: StageId): Promise<string>\n currentBranch(projectDir: string): Promise<string>\n hasChanges(projectDir: string): Promise<boolean>\n findStageCheckpoint(projectDir: string, stage: StageId): Promise<string | undefined>\n createBackupBranch(projectDir: string, stage: string): Promise<string>\n createReworkBranch(projectDir: string, checkpoint: string, nextStageSlug: string): Promise<string>\n }\n readonly pushWorkspace: (projectDir: string, run: PentestRun) => Promise<void>\n readonly syncWorkspace: (projectDir: string, run: PentestRun) => Promise<void>\n}\n\nexport function requireRootCaller(exec: unknown): TrustedCaller {\n const caller = trustedCallerFromExec(exec)\n if (caller === undefined || !caller.isPentesterRoot) {\n throw new Error('this tool is reserved for the Pentester Root Agent')\n }\n if (caller.cwd === undefined) {\n throw new Error('Root session has no trusted workspace cwd')\n }\n return caller\n}\n\nfunction agentOf(exec: unknown): Agent | undefined {\n if (exec === null || typeof exec !== 'object') return undefined\n const agent = (exec as Record<string, unknown>).agent\n return agent !== null && typeof agent === 'object' ? agent as Agent : undefined\n}\n\nfunction signalOf(exec: unknown): AbortSignal {\n if (exec !== null && typeof exec === 'object') {\n const signal = (exec as { signal?: unknown }).signal\n if (signal instanceof AbortSignal) return signal\n }\n return new AbortController().signal\n}\n\nexport function registerRootTools(\n tools: DshToolsService,\n deps: RootToolDeps,\n): readonly string[] {\n const output = {\n schema: { type: 'object', additionalProperties: true },\n render: (_args: unknown, value: unknown) => [{ type: 'text', text: JSON.stringify(value) }],\n }\n tools.register({\n name: 'pentester_delegate',\n description: ROOT_TOOL_DESCRIPTIONS.pentester_delegate,\n parameters: ROOT_TOOL_SCHEMAS.pentester_delegate,\n output,\n execute: (args, exec) => delegate(deps, args, exec),\n })\n tools.register({\n name: 'pentester_cancel_delegation',\n description: ROOT_TOOL_DESCRIPTIONS.pentester_cancel_delegation,\n parameters: ROOT_TOOL_SCHEMAS.pentester_cancel_delegation,\n output,\n execute: (args, exec) => cancel(deps, args, exec),\n })\n tools.register({\n name: 'pentester_advance_stage',\n description: ROOT_TOOL_DESCRIPTIONS.pentester_advance_stage,\n parameters: ROOT_TOOL_SCHEMAS.pentester_advance_stage,\n output,\n execute: (args, exec) => advance(deps, args, exec),\n })\n tools.register({\n name: 'pentester_rollback_stage',\n description: ROOT_TOOL_DESCRIPTIONS.pentester_rollback_stage,\n parameters: ROOT_TOOL_SCHEMAS.pentester_rollback_stage,\n output,\n execute: (args, exec) => rollback(deps, args, exec),\n })\n return ['pentester_delegate', 'pentester_cancel_delegation', 'pentester_advance_stage', 'pentester_rollback_stage']\n}\n\nconst ROOT_TOOL_DESCRIPTIONS = {\n pentester_delegate:\n 'Creates a new long-lived continuable PTES worker. IMPORTANT: Before calling this tool, first tell the user which worker you are creating, what it will do, and why the current PTES stage needs it. Do not call this tool silently. Each call creates a NEW durable child Session. For follow-up work with an existing child, do not call pentester_delegate again; use send_message through the continuation interface.',\n pentester_cancel_delegation:\n 'Close a PTES Delegation. Interrupts the live child turn if active, then marks the Delegation as closed. The child Session transcript is preserved for future reference. Use send_message/interrupt_agent for follow-up or interruption without closing.',\n pentester_advance_stage:\n 'Advance to the next PTES stage after you judge the exit criteria satisfied. The host only verifies linear order and that no active/starting delegations remain. On the FIRST call (no PentestRun yet) pass run (targets / rules_of_engagement / language) + summary: the host bootstraps the workspace, run.json, target files, git and completes pre-engagement.',\n pentester_rollback_stage:\n 'Roll the timeline back to a completed stage checkpoint and start a rework branch from the next stage. Closes active delegations, saves a WIP backup branch, never rewrites history.',\n} as const\n\nexport async function delegate(\n deps: RootToolDeps,\n args: Record<string, unknown>,\n exec: unknown,\n): Promise<unknown> {\n const caller = requireRootCaller(exec)\n const projectDir = caller.cwd!\n const parent = agentOf(exec)\n if (parent === undefined) {\n throw new Error('pentester_delegate requires a calling agent (exec.agent was undefined)')\n }\n const signal = signalOf(exec)\n const run = await requireRun(caller, deps)\n const assignments = parseAssignments(args.assignments)\n const created = await deps.delegations.delegate(\n {\n projectDir,\n run,\n profiles: deps.profiles,\n rootSessionId: caller.sessionId,\n parent,\n signal,\n },\n assignments,\n )\n return {\n ...rootState(run, deps.profiles),\n created: created.map(d => ({\n id: d.id,\n agent: d.agentId,\n status: d.status,\n ...(d.sessionId === undefined ? {} : { childSessionId: d.sessionId }),\n })),\n }\n}\n\nexport async function cancel(\n deps: RootToolDeps,\n args: Record<string, unknown>,\n exec: unknown,\n): Promise<unknown> {\n const caller = requireRootCaller(exec)\n const run = await requireRun(caller, deps)\n const delegationId = typeof args.delegation_id === 'string' ? args.delegation_id : ''\n const reason = typeof args.reason === 'string' ? args.reason : undefined\n const cancelled = await deps.delegations.cancel({ projectDir: caller.cwd!, run }, delegationId, reason)\n return {\n cancelled: { id: cancelled.id, status: cancelled.status },\n ...rootState(run, deps.profiles),\n }\n}\n\nexport async function advance(\n deps: RootToolDeps,\n args: Record<string, unknown>,\n exec: unknown,\n): Promise<unknown> {\n const caller = requireRootCaller(exec)\n const projectDir = caller.cwd!\n const summary = typeof args.summary === 'string' ? args.summary : ''\n if (summary.trim() === '') {\n throw new Error('pentester_advance_stage requires a non-empty summary (stage handoff text)')\n }\n let run = await resolvePentestRun(projectDir)\n if (run === null) {\n run = await bootstrapRun(deps, projectDir, parseRunInfo(args.run))\n } else {\n await initWorkspace(projectDir, { language: run.language })\n }\n if (run.status === 'completed' || run.currentStage === null) {\n throw new Error('PentestRun is already completed; no stage to advance')\n }\n const previous = run.currentStage\n // mechanical validation:当前 stage 不能有 active/starting delegation。\n if (deps.delegations.stageHasPendingWork(run, previous)) {\n throw new Error(\n `stage ${previous} still has active or starting delegations; ` +\n `close them with pentester_cancel_delegation before advancing`,\n )\n }\n // 1) 远程阶段边界:advance 前 remote → local 同步 Worker 数据。\n await deps.syncWorkspace(projectDir, run).catch(() => undefined)\n // 2) promotion:把 canonical 产物提升到 workspace 根。\n const stageDelegations = run.delegations.filter(d => d.stageId === previous)\n const delegationDirs = stageDelegations.map(d => d.workspaceDir)\n const delegationIds = stageDelegations.map(d => d.id)\n // assets: aggregate from all delegations, dedup, write canonical assets/\n await promoteAssets(projectDir, previous, delegationDirs, delegationIds)\n // findings: aggregate from all delegations, index, write canonical findings/\n await promoteFindings(projectDir, previous, delegationDirs, delegationIds)\n // threat-model.md: simple copy (single document per stage, not aggregated)\n for (const delegation of stageDelegations) {\n await promoteDeliverables(projectDir, delegation.workspaceDir)\n }\n // 3) summary.md:Root 提供的 stage handoff。\n await writeStageSummary(projectDir, previous, summary)\n // 4) run transition:completed → next active。\n const target = advanceStage(run, summary)\n await saveRun(projectDir, run)\n // 5) git checkpoint。\n const tag = await deps.git.checkpointStage(projectDir, previous)\n await appendEvent(projectDir, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: previous, tag, next: target },\n })\n // 6) push 新 stage scaffold 进容器。\n await deps.pushWorkspace(projectDir, run).catch(() => undefined)\n return {\n previous,\n ...(target === null ? { completed: true } : { next: target }),\n tag,\n ...rootState(run, deps.profiles),\n }\n}\n\nexport async function rollback(\n deps: RootToolDeps,\n args: Record<string, unknown>,\n exec: unknown,\n): Promise<unknown> {\n const caller = requireRootCaller(exec)\n const projectDir = caller.cwd!\n const run = await requireRun(caller, deps)\n const stageArg = typeof args.stage === 'string' ? args.stage : ''\n const reason = typeof args.reason === 'string' ? args.reason : ''\n if (!isStageId(stageArg)) {\n throw new Error(`pentester_rollback_stage: unknown stage \"${stageArg}\"`)\n }\n const next = nextStage(stageArg)\n if (next === undefined) {\n throw new Error(`pentester_rollback_stage: cannot roll back to the final stage ${stageArg}`)\n }\n const completed = run.stageHistory.some(entry => entry.stage === stageArg)\n if (!completed) {\n throw new Error(`pentester_rollback_stage: stage ${stageArg} has no completed checkpoint on this timeline`)\n }\n // 1) 关闭当前 active/starting delegation。\n const active = run.delegations.filter(d =>\n d.status === 'active' || d.status === 'starting')\n for (const delegation of active) {\n await deps.delegations.cancel({ projectDir, run }, delegation.id, 'rolled back by Root')\n }\n // 2) dirty → backup branch + WIP commit。\n let backup: string | undefined\n if (await deps.git.hasChanges(projectDir)) {\n backup = await deps.git.createBackupBranch(projectDir, stageArg)\n }\n // 3) 找目标 stage 的 completion checkpoint。\n const checkpoint = await deps.git.findStageCheckpoint(projectDir, stageArg)\n if (checkpoint === undefined) {\n throw new Error(`pentester_rollback_stage: no checkpoint commit found for stage ${stageArg}`)\n }\n // 4) 从 checkpoint 建 rework branch 并 checkout。\n const branch = await deps.git.createReworkBranch(projectDir, checkpoint, stageDir(next))\n // 5) 重新解析权威 PentestRun。\n const authoritativeRun = await resolvePentestRun(projectDir)\n if (authoritativeRun === null) {\n throw new Error('pentester_rollback_stage: run.json disappeared after checkout — this is a bug')\n }\n await appendEvent(projectDir, {\n ts: new Date().toISOString(),\n type: 'stage.rollback',\n data: { stage: stageArg, checkpoint, branch, backup, reason },\n })\n await deps.pushWorkspace(projectDir, authoritativeRun).catch(() => undefined)\n return {\n reopenedStage: stageArg,\n currentStage: stageArg,\n branch,\n ...(backup === undefined ? {} : { backupBranch: backup }),\n reason,\n ...rootState(authoritativeRun, deps.profiles),\n }\n}\n\nconst NO_RUN_MESSAGE =\n 'No PentestRun exists. Complete pre-engagement and call pentester_advance_stage first — pass run (targets / rules_of_engagement / language) + summary to initialize the run.'\n\nexport async function requireRun(\n caller: TrustedCaller,\n _deps?: RootToolDeps,\n): Promise<PentestRun> {\n const projectDir = caller.cwd!\n await initWorkspace(projectDir, { language: undefined })\n const run = await resolvePentestRun(projectDir)\n if (run === null) {\n throw new Error(NO_RUN_MESSAGE)\n }\n return run\n}\n\nasync function bootstrapRun(\n deps: RootToolDeps,\n projectDir: string,\n runInfo: { targets?: string[]; rulesOfEngagement?: string; language?: string } | undefined,\n): Promise<PentestRun> {\n if (runInfo === undefined || runInfo.targets === undefined || runInfo.targets.length === 0) {\n throw new Error(NO_RUN_MESSAGE)\n }\n const primary = runInfo.targets[0]\n await initWorkspace(projectDir, {\n target: primary,\n language: runInfo.language,\n scope: renderScope(runInfo.targets),\n roe: runInfo.rulesOfEngagement,\n })\n await writePreEngagementInput(projectDir, {\n targets: runInfo.targets,\n scope: renderScope(runInfo.targets),\n roe: runInfo.rulesOfEngagement ?? 'Standard RoE',\n language: runInfo.language ?? 'zh-CN',\n })\n const created: PentestRun = {\n schemaVersion: 1,\n id: crypto.randomUUID(),\n createdAt: new Date().toISOString(),\n targets: [...runInfo.targets],\n ...(runInfo.rulesOfEngagement === undefined ? {} : { rulesOfEngagement: runInfo.rulesOfEngagement }),\n ...(runInfo.language === undefined ? {} : { language: runInfo.language }),\n status: 'active',\n currentStage: 'pre-engagement',\n stageHistory: [{ stage: 'pre-engagement', enteredAt: new Date().toISOString() }],\n delegations: [],\n }\n await saveRun(projectDir, created)\n await deps.git.init(projectDir, primary)\n return created\n}\n\nfunction renderScope(targets: readonly string[]): string {\n return [\n '# Scope',\n '',\n `- Primary Target: ${targets[0] ?? ''}`,\n ...targets.slice(1).map(target => `- ${target}`),\n '',\n ].join('\\n')\n}\n\nfunction parseAssignments(value: unknown): Assignment[] {\n if (!Array.isArray(value) || value.length === 0) {\n throw new Error('assignments must be a non-empty array')\n }\n return value.map(entry => {\n if (entry === null || typeof entry !== 'object') throw new Error('invalid assignment')\n const record = entry as Record<string, unknown>\n if (typeof record.agent !== 'string' || typeof record.objective !== 'string'\n || typeof record.task_prompt !== 'string') {\n throw new Error('assignment requires agent, objective and task_prompt')\n }\n return { agent: record.agent, objective: record.objective, taskPrompt: record.task_prompt }\n })\n}\n\nfunction parseRunInfo(value: unknown): { targets?: string[]; rulesOfEngagement?: string; language?: string } | undefined {\n if (value === undefined) return undefined\n if (value === null || typeof value !== 'object') throw new Error('invalid run info')\n const record = value as Record<string, unknown>\n const targets = Array.isArray(record.targets) ? record.targets.map(String) : undefined\n const roe = typeof record.rules_of_engagement === 'string' ? record.rules_of_engagement : undefined\n const language = typeof record.language === 'string' && record.language.length > 0 ? record.language : undefined\n return {\n ...(targets === undefined ? {} : { targets }),\n ...(roe === undefined ? {} : { rulesOfEngagement: roe }),\n ...(language === undefined ? {} : { language }),\n }\n}\n\nfunction rootState(run: PentestRun, profiles: ReadonlyMap<string, AgentProfile>): Record<string, unknown> {\n const stage = run.currentStage === null ? undefined : stageDefinition(run.currentStage)\n const allowedProfiles = (stage?.agentIds ?? [])\n .map(id => profiles.get(id))\n .filter((profile): profile is AgentProfile => profile !== undefined)\n .map(profile => ({ id: profile.id, name: profile.name }))\n return {\n run: {\n currentStage: run.currentStage,\n status: run.status ?? 'active',\n targets: run.targets,\n },\n stage: stage === undefined\n ? null\n : {\n id: stage.id,\n name: stage.name,\n goal: stage.goal,\n exitCriteria: stage.exitCriteria,\n allowedProfiles,\n },\n delegations: run.delegations.map(d => ({\n id: d.id,\n stage: d.stageId,\n agent: d.agentId,\n status: d.status,\n ...(d.sessionId === undefined ? {} : { childSessionId: d.sessionId }),\n ...(d.finishedAt === undefined ? {} : { finishedAt: d.finishedAt }),\n })),\n }\n}\n\nexport { ROOT_TOOL_DESCRIPTIONS }","/**\n * profiles.ts — AgentProfile registry loaded from agents/<id>/profile.yml.\n * The YAML subset is fixed by this schema: scalar keys, one block scalar\n * (`systemPrompt: |`), and two string lists. No external yaml dependency.\n */\nimport { readdirSync, readFileSync, type Dirent } from 'node:fs'\nimport { join } from 'node:path'\nimport type { AgentProfile } from './model.js'\n\nexport class ProfileError extends Error {}\n\nfunction parseProfileYaml(text: string, file: string): AgentProfile {\n const lines = text.split('\\n')\n const scalars = new Map<string, string>()\n const lists = new Map<string, string[]>()\n let key: string | undefined\n let block: string[] | undefined\n let listKey: string | undefined\n\n const closeBlock = (): void => {\n if (key !== undefined && block !== undefined) {\n scalars.set(key, block.join('\\n').replace(/\\n+$/, ''))\n }\n key = undefined\n block = undefined\n }\n\n for (const raw of lines) {\n if (block !== undefined && (raw.startsWith(' ') || raw.trim() === '')) {\n block.push(raw.replace(/^ {2}/, ''))\n continue\n }\n closeBlock()\n const line = raw.trimEnd()\n if (line.trim() === '' || line.trim().startsWith('#')) continue\n const listItem = /^\\s*-\\s+(.*)$/.exec(line)\n if (listItem !== null && listKey !== undefined) {\n lists.get(listKey)!.push(listItem[1].trim())\n continue\n }\n const pair = /^([A-Za-z][A-Za-z0-9]*):\\s*(.*)$/.exec(line)\n if (pair === null) {\n throw new ProfileError(`${file}: unparsable line: ${line}`)\n }\n const [, name, value] = pair\n if (value === '|' || value === '|-' || value === '>') {\n key = name\n block = []\n listKey = undefined\n continue\n }\n if (value === '') {\n listKey = name\n lists.set(name, [])\n continue\n }\n scalars.set(name, value.trim())\n listKey = undefined\n }\n closeBlock()\n\n const id = scalars.get('id')\n const name = scalars.get('name')\n const description = scalars.get('description')\n const systemPrompt = scalars.get('systemPrompt')\n if (id === undefined || name === undefined || systemPrompt === undefined) {\n throw new ProfileError(`${file}: id, name and systemPrompt are required`)\n }\n return {\n id,\n name,\n description: description ?? '',\n systemPrompt,\n skills: lists.get('skills') ?? [],\n mcpServers: lists.get('mcpServers') ?? [],\n ...(scalar(scalars, 'model') === undefined ? {} : { model: scalar(scalars, 'model') }),\n }\n}\n\nfunction scalar(scalars: Map<string, string>, key: string): string | undefined {\n const value = scalars.get(key)\n return value !== undefined && value.length > 0 ? value : undefined\n}\n\nexport function loadAgentProfiles(root: string): ReadonlyMap<string, AgentProfile> {\n const profiles = new Map<string, AgentProfile>()\n let entries: readonly Dirent[]\n try {\n entries = readdirSync(root, { withFileTypes: true })\n } catch {\n return profiles\n }\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const file = join(root, entry.name, 'profile.yml')\n let text: string\n try {\n text = readFileSync(file, 'utf8')\n } catch {\n continue\n }\n const profile = parseProfileYaml(text, file)\n if (profiles.has(profile.id)) {\n throw new ProfileError(`duplicate AgentProfile id: ${profile.id}`)\n }\n profiles.set(profile.id, profile)\n }\n return profiles\n}\n","/**\n * docker/host.ts — docker 连接层:host 解析(本地优先回退链)、连接探测、\n * 引擎连接构造。与执行细节无关,可独立测试。\n */\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport Dockerode from 'dockerode'\n\nexport const DEFAULT_UNIX_SOCKET = '/var/run/docker.sock'\n\nexport class DockerError extends Error {}\n\n// ── docker host resolution: config > DOCKER_HOST > platform default ─────────\n\nexport interface DockerHost {\n /** unix socket path (local daemon) */\n readonly socketPath?: string\n /** remote daemon over http(s) */\n readonly protocol?: 'http' | 'https'\n readonly host?: string\n readonly port?: number\n}\n\nexport function parseDockerHost(value: string): DockerHost {\n const raw = value.trim()\n if (raw === '') throw new DockerError('empty docker host')\n if (raw.startsWith('unix://')) return { socketPath: raw.slice('unix://'.length) || DEFAULT_UNIX_SOCKET }\n if (raw.startsWith('/') && !raw.includes('://')) return { socketPath: raw }\n for (const scheme of ['tcp://', 'http://', 'https://'] as const) {\n if (!raw.startsWith(scheme)) continue\n const protocol = scheme === 'tcp://' ? 'http' : (scheme.replace('://', '') as 'http' | 'https')\n const authority = raw.slice(scheme.length).replace(/\\/.*$/, '')\n const [host, portText] = authority.split(':')\n if (host === undefined || host === '') throw new DockerError(`docker host missing hostname: ${raw}`)\n const port = portText === undefined ? 2375 : Number(portText)\n if (!Number.isInteger(port)) throw new DockerError(`docker host invalid port: ${raw}`)\n return { protocol, host, port }\n }\n if (/^[^/:]+:\\d+$/.test(raw)) {\n const [host, portText] = raw.split(':')\n return { protocol: 'http' as const, host, port: Number(portText) }\n }\n throw new DockerError(\n `unsupported docker host: ${raw} (use unix:///path, tcp://host:port or http://host:port)`,\n )\n}\n\n/**\n * 本地 Docker socket 候选路径(按平台常见布局,先命中先用)。\n * macOS:OrbStack / Docker Desktop;Linux:系统 socket。\n */\nexport function localSocketCandidates(): readonly string[] {\n const home = process.env.HOME ?? ''\n return [\n DEFAULT_UNIX_SOCKET,\n ...(home === '' ? [] : [\n join(home, '.orbstack', 'run', 'docker.sock'),\n join(home, '.docker', 'run', 'docker.sock'),\n ]),\n ]\n}\n\nexport interface ResolveDockerHostDeps {\n /** 判断本地 socket 是否存在(可注入以便测试)。默认用 existsSync。 */\n readonly socketExists?: (path: string) => boolean\n}\n\n/**\n * 解析全局 docker host。优先级:\n * 1. 显式配置(settings.json / 插件配置)\n * 2. 本地 socket(候选路径中第一个存在的 —— “未指定优先使用本地的”)\n * 3. DOCKER_HOST 环境变量\n * 4. 默认 unix socket\n */\nexport function resolveDockerHost(configured?: string, deps: ResolveDockerHostDeps = {}): DockerHost {\n if (configured !== undefined && configured.trim() !== '') return parseDockerHost(configured)\n return resolveDockerHostWithSource('', '', deps).host\n}\n\n/** host 解析来源(供 Settings UI 与显示对齐,不留白)。 */\nexport type DockerHostSource = 'settings' | 'config' | 'local' | 'env' | 'default'\n\nexport interface ResolvedDockerHost {\n readonly host: DockerHost\n readonly source: DockerHostSource\n}\n\n/**\n * 带来源的完整解析。优先级:\n * settings.json(Settings UI 保存的显式配置)\n * > 插件配置 dockerHost\n * > 本地 socket(自动发现 —— “未指定优先使用本地的”)\n * > DOCKER_HOST 环境变量\n * > 默认 unix socket\n */\nexport function resolveDockerHostWithSource(\n settingsHost: string,\n configHost: string,\n deps: ResolveDockerHostDeps = {},\n): ResolvedDockerHost {\n if (settingsHost.trim() !== '') return { host: parseDockerHost(settingsHost), source: 'settings' }\n if (configHost.trim() !== '') return { host: parseDockerHost(configHost), source: 'config' }\n const exists = deps.socketExists ?? existsSync\n const local = localSocketCandidates().find(candidate => exists(candidate))\n if (local !== undefined) return { host: { socketPath: local }, source: 'local' }\n const env = process.env.DOCKER_HOST\n if (env !== undefined && env.trim() !== '') return { host: parseDockerHost(env), source: 'env' }\n return { host: { socketPath: DEFAULT_UNIX_SOCKET }, source: 'default' }\n}\n\n/** 连接探测结果(测试 DOCKER HOST 用)。 */\nexport interface DockerProbe {\n readonly reachable: boolean\n readonly endpoint: string\n readonly version?: string\n readonly apiVersion?: string\n readonly os?: string\n readonly error?: string\n}\n\n/**\n * 探测一个 docker host 是否可用(GET /version)。engine 可注入用于测试。\n */\nexport async function probeDockerHost(\n host: DockerHost,\n engine?: DockerEngineLike,\n): Promise<DockerProbe> {\n const target = engine ?? engineFromOptions({ host })\n const endpoint = formatDockerHost(host)\n try {\n const info = await target.version()\n return {\n reachable: true,\n endpoint,\n ...(typeof info.Version === 'string' ? { version: info.Version } : {}),\n ...(typeof info.ApiVersion === 'string' ? { apiVersion: info.ApiVersion } : {}),\n ...(typeof info.Os === 'string' ? { os: info.Os } : {}),\n }\n } catch (error) {\n return {\n reachable: false,\n endpoint,\n error: error instanceof Error ? error.message : String(error),\n }\n }\n}\n\nexport function isRemoteHost(host: DockerHost): boolean {\n return host.protocol !== undefined\n}\n\nexport function formatDockerHost(host: DockerHost): string {\n if (host.socketPath !== undefined) return `unix://${host.socketPath}`\n return `${host.protocol}://${host.host}:${host.port}`\n}\n\nexport interface DockerEngineLike {\n version(): Promise<{ Version?: string; ApiVersion?: string; Os?: string }>\n /** dockerode pull(ref, opts, cb):opts.abortSignal 取消请求;返回进度流(JSON 行)。 */\n pull(\n ref: string,\n options: { abortSignal?: AbortSignal },\n callback: (error?: Error | null, stream?: NodeJS.ReadableStream) => void,\n ): NodeJS.ReadableStream\n /** dockerode buildImage(file, options, callback):file 是 tar 上下文。 */\n buildImage(\n file: NodeJS.ReadableStream | Buffer | string,\n options: { t: string; buildargs?: Record<string, string> },\n callback: (error?: Error | null, stream?: NodeJS.ReadableStream) => void,\n ): NodeJS.ReadableStream\n getImage(name: string): { inspect(): Promise<unknown> }\n listContainers(options: Record<string, unknown>): Promise<Array<Record<string, unknown>>>\n createVolume(options: Record<string, unknown>): Promise<{ Name: string }>\n /** dockerode getVolume(name).inspect():volume 不存在时 reject(recovery 探测用)。 */\n getVolume(name: string): { inspect(): Promise<unknown> }\n createContainer(options: Record<string, unknown>): Promise<{\n id: string\n start(): Promise<void>\n inspect(): Promise<Record<string, unknown>>\n }>\n getContainer(id: string): {\n inspect(): Promise<Record<string, unknown>>\n remove(options?: Record<string, unknown>): Promise<void>\n exec(options: Record<string, unknown>): Promise<{\n start(options: Record<string, unknown>): Promise<NodeJS.ReadableStream & { destroy?(error?: Error): void; on: (event: string, listener: (...args: unknown[]) => void) => void }>\n inspect(): Promise<{ ExitCode?: number }>\n }>\n getArchive(options: Record<string, unknown>): Promise<NodeJS.ReadableStream>\n /** dockerode putArchive(file, {path}):把 tar 流解压进容器目录(push 方向)。 */\n putArchive(\n file: NodeJS.ReadableStream | Buffer,\n options: Record<string, unknown>,\n ): Promise<unknown>\n }\n}\n\nexport function engineFromOptions(options: { host?: DockerHost }): DockerEngineLike {\n const host = options.host\n const connection = host === undefined || host.socketPath !== undefined\n ? { socketPath: host?.socketPath ?? DEFAULT_UNIX_SOCKET }\n : { protocol: host.protocol, host: host.host, port: host.port }\n return new Dockerode(connection as ConstructorParameters<typeof Dockerode>[0]) as unknown as DockerEngineLike\n}\n","/**\n * docker/images.ts — 镜像层:Toolbox 白名单、inspect 原语。\n * 函数式无状态,引擎实例由调用方传入。\n */\nimport { DockerError, type DockerEngineLike } from './host.js'\n\nexport interface ToolboxSpec {\n readonly name: string\n readonly image: string\n}\n\nexport const TOOLBOX_ALLOWLIST: readonly ToolboxSpec[] = [\n { name: 'kali', image: 'fb0sh/dsh-pentester-kali:latest' },\n]\n\nexport function toolboxFor(name: string, overrides?: Readonly<Record<string, string>>): ToolboxSpec {\n const spec = TOOLBOX_ALLOWLIST.find(toolbox => toolbox.name === name)\n if (spec === undefined) throw new DockerError(`unknown toolbox: ${name}`)\n const image = overrides?.[name]\n return image === undefined ? spec : { ...spec, image }\n}\n\n/** 镜像是否已就绪(本地存在)。 */\nexport async function imageReady(engine: DockerEngineLike, image: string): Promise<boolean> {\n try {\n await engine.getImage(image).inspect()\n return true\n } catch {\n return false\n }\n}\n","/**\n * docker/runtime.ts — 执行运行时:硬化 HostConfig、容器/卷生命周期、\n * exec demux、volume→本地镜像同步、工具目录读取;镜像原语委托给\n * docker/images.ts。不变量见 docs/plan.md 与 ADR 0007。\n */\nimport { createHash, randomBytes } from 'node:crypto'\nimport { mkdir, readdir, rm, stat, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix } from 'node:path'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport tar from 'tar-stream'\nimport { DEFAULT_UNIX_SOCKET, DockerError, engineFromOptions, formatDockerHost, isRemoteHost, type DockerEngineLike, type DockerHost } from './host.js'\nimport { imageReady as imageReadyOn, toolboxFor, type ToolboxSpec } from './images.js'\nimport { workspaceDir } from '../store.js'\n\nexport interface ExecInput {\n readonly argv: readonly string[]\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly timeoutMs?: number\n}\n\nexport interface ExecResult {\n readonly exitCode: number\n readonly stdout: string\n readonly stderr: string\n readonly timedOut: boolean\n}\n\nexport const MAX_EXEC_TIMEOUT_MS = 10 * 60 * 1000\nconst MAX_OUTPUT_CHARS = 200_000\nconst BLOCKED_ENV_PREFIXES = ['DOCKER', 'DSH_'] as const\nconst CAP_ADD_ALLOWLIST = ['NET_ADMIN', 'NET_RAW', 'NET_BIND_SERVICE'] as const\n\n/** Toolbox container name: dsh-pentester-xxxxxxxx (8 lowercase hex). */\nexport function createToolboxContainerName(): string {\n return `dsh-pentester-${randomBytes(4).toString('hex')}`\n}\n\n/** 固定注入 Toolbox 容器的代理环境变量(容器内部代理服务)。 */\nconst FIXED_CONTAINER_ENV: readonly string[] = [\n 'HTTP_PROXY=http://127.0.0.1:8080',\n 'HTTPS_PROXY=http://127.0.0.1:8080',\n]\n\n/** Defense in depth: validate the HostConfig we are about to submit. */\nexport function assertSafeHostConfig(hostConfig: Record<string, unknown>): void {\n if (hostConfig.Privileged === true) throw new DockerError('privileged containers are forbidden')\n if (hostConfig.NetworkMode === 'host') throw new DockerError('host network is forbidden')\n if (hostConfig.PidMode === 'host') throw new DockerError('host pid namespace is forbidden')\n if (hostConfig.IpcMode === 'host') throw new DockerError('host ipc namespace is forbidden')\n const binds = hostConfig.Binds\n if (Array.isArray(binds)) {\n for (const bind of binds) {\n if (typeof bind !== 'string') continue\n const source = bind.split(':')[0]\n if (source === '/' || source.endsWith('/docker.sock')) {\n throw new DockerError(`forbidden bind source: ${source}`)\n }\n }\n }\n const capAdd = hostConfig.CapAdd\n if (Array.isArray(capAdd)) {\n for (const cap of capAdd) {\n if (typeof cap === 'string' && !(CAP_ADD_ALLOWLIST as readonly string[]).includes(cap)) {\n throw new DockerError(`capability ${cap} is not in the allowlist`)\n }\n }\n }\n}\n\nexport function safeEnv(env: Readonly<Record<string, string>> | undefined): Record<string, string> {\n const safe: Record<string, string> = {}\n for (const [key, value] of Object.entries(env ?? {})) {\n if (BLOCKED_ENV_PREFIXES.some(prefix => key.startsWith(prefix))) {\n throw new DockerError(`environment key ${key} is not allowed`)\n }\n safe[key] = value\n }\n return safe\n}\n\nexport interface RunContainerOptions {\n readonly runId: string\n readonly toolbox: ToolboxSpec\n /** Trusted project root; derives the shared volume name and local mirror. */\n readonly projectDir: string\n}\n\nexport function volumeNameFor(projectDir: string): string {\n const digest = createHash('sha1').update(projectDir).digest('hex').slice(0, 12)\n return `dsh-pentester-ws-${digest}`\n}\n\nexport function localMirrorDir(projectDir: string): string {\n // 交付树根 = workspace/(容器 /workspace 的宿主镜像)。\n return workspaceDir(projectDir)\n}\n\nexport class DockerRuntime {\n private engine: DockerEngineLike\n private host: DockerHost\n private imageOverrides?: Readonly<Record<string, string>>\n private readonly ensuring = new Map<string, Promise<string>>()\n private readonly volumes = new Set<string>()\n private readonly syncing = new Map<string, Promise<void>>()\n private readonly pushing = new Map<string, Promise<void>>()\n\n constructor(options: { host?: DockerHost; imageOverrides?: Readonly<Record<string, string>>; engine?: DockerEngineLike }) {\n this.engine = options.engine ?? engineFromOptions(options)\n this.host = options.host ?? { socketPath: DEFAULT_UNIX_SOCKET }\n this.imageOverrides = options.imageOverrides\n }\n\n /** 更新 toolbox 镜像覆盖(Settings UI 保存后热生效)。 */\n updateToolboxImage(toolbox: string, image: string | undefined): void {\n const next = { ...(this.imageOverrides ?? {}) }\n if (image === undefined || image.trim() === '') delete next[toolbox]\n else next[toolbox] = image.trim()\n this.imageOverrides = next\n }\n\n /**\n * 切换 docker host(Settings UI 保存后调用)。重建底层连接并清空\n * 卷/容器缓存;卷与容器按标签在新 daemon 上重新发现。\n */\n updateHost(host: DockerHost): void {\n this.engine = engineFromOptions({ host })\n this.host = host\n this.volumes.clear()\n this.ensuring.clear()\n }\n\n get endpoint(): string {\n return formatDockerHost(this.host)\n }\n\n get remote(): boolean {\n return isRemoteHost(this.host)\n }\n\n async ensureImage(toolboxName: string): Promise<ToolboxSpec> {\n const spec = toolboxFor(toolboxName, this.imageOverrides)\n try {\n await this.engine.getImage(spec.image).inspect()\n return spec\n } catch {\n throw new DockerError(\n `toolbox image ${spec.image} not found; ensure the image exists on the Docker host`,\n )\n }\n }\n\n /**\n * One docker volume per project (all stages, all containers of the project\n * mount the same volume at /workspace). The container is per PentestRun and\n * reused while running.\n */\n async ensureRunContainer(options: RunContainerOptions): Promise<string> {\n const volume = this.remote ? await this.ensureWorkspaceVolume(options.projectDir) : undefined\n const label = 'dsh.pentester.run'\n const existing = await this.engine.listContainers({\n all: true,\n filters: { label: [`${label}=${options.runId}`] },\n })\n for (const match of existing) {\n if (match.State === 'running') return String(match.Id)\n await this.engine.getContainer(String(match.Id)).remove({ force: true }).catch(() => undefined)\n }\n let ensure = this.ensuring.get(options.runId)\n if (ensure === undefined) {\n ensure = this.createRunContainer(options, volume, label)\n this.ensuring.set(options.runId, ensure)\n void ensure.finally(() => this.ensuring.delete(options.runId))\n }\n const containerId = await ensure\n // recovery:volume 新建(container+volume 双失)且本地 mirror 有数据 →\n // 把本地 workspace 恢复到新 volume(§24;绝不覆盖仍存在的 remote)。\n if (this.remote && volume?.created === true) {\n await this.pushLocalMirror(containerId, options.projectDir).catch(() => undefined)\n }\n return containerId\n }\n\n /**\n * 远程 workspace volume:存在则复用(§24 recovery 优先级),不存在才创建。\n * `created: true` 表示本轮新建 —— 调用方据此决定是否从本地恢复数据。\n */\n private async ensureWorkspaceVolume(projectDir: string): Promise<{ name: string; created: boolean }> {\n const volume = volumeNameFor(projectDir)\n if (this.volumes.has(volume)) return { name: volume, created: false }\n const existing = await this.engine.getVolume(volume).inspect().then(\n () => true,\n () => false,\n )\n if (existing) {\n this.volumes.add(volume)\n return { name: volume, created: false }\n }\n const created = await this.engine.createVolume({\n Name: volume,\n Labels: { 'dsh.pentester.managed': 'true', 'dsh.pentester.project': volume },\n })\n this.volumes.add(created.Name)\n return { name: created.Name, created: true }\n }\n\n private async createRunContainer(options: RunContainerOptions, volume: { name: string; created: boolean } | undefined, label: string): Promise<string> {\n const mount = volume === undefined\n ? { Type: 'bind' as const, Source: localMirrorDir(options.projectDir), Target: '/workspace' }\n : { Type: 'volume' as const, Source: volume.name, Target: '/workspace' }\n const hostConfig = {\n Mounts: [mount],\n CapAdd: [...CAP_ADD_ALLOWLIST],\n AutoRemove: false,\n }\n assertSafeHostConfig(hostConfig)\n const containerName = createToolboxContainerName()\n const container = await this.engine.createContainer({\n name: containerName,\n Image: options.toolbox.image,\n Env: [...FIXED_CONTAINER_ENV],\n Labels: {\n [label]: options.runId,\n 'dsh.pentester.managed': 'true',\n },\n HostConfig: hostConfig,\n WorkingDir: '/workspace',\n Tty: false,\n OpenStdin: false,\n Cmd: ['sleep', 'infinity'],\n })\n await container.start()\n // 全流量记录(只记录不分析):容器一起动就开 tcpdump + mitmdump。\n void this.exec(container.id, {\n argv: ['/pentester/bin/record-traffic.sh'],\n }).catch(() => undefined)\n return container.id\n }\n\n private readonly catalogs = new Map<string, Promise<unknown>>()\n\n /**\n * 读取镜像内的工具目录(/pentester/tools.json),按 containerId 缓存一次。\n * 供 worker prompt 注入“有什么工具、怎么用”的摘要。\n */\n async readToolCatalog(containerId: string): Promise<unknown> {\n let cached = this.catalogs.get(containerId)\n if (cached === undefined) {\n cached = this.exec(containerId, { argv: ['cat', '/pentester/tools.json'] })\n .then(result => JSON.parse(result.stdout) as unknown)\n this.catalogs.set(containerId, cached)\n void cached.catch(() => this.catalogs.delete(containerId))\n }\n return cached\n }\n\n async stopRunContainer(runId: string): Promise<void> {\n const matches = await this.engine.listContainers({\n all: true,\n filters: { label: [`dsh.pentester.run=${runId}`] },\n })\n for (const match of matches) {\n const container = this.engine.getContainer(String(match.Id))\n await container.remove({ force: true }).catch(() => undefined)\n }\n }\n\n /**\n * Delegation settle 的轻量交付读取(§12:settle 不做全量 Workspace sync)。\n * 远程模式直接通过 exec 读 result.md 并列出 delegation 目录文件;\n * 本地 bind mount 下 host == container,直接读本地文件系统。\n * @returns result.md 内容(缺失 undefined)与相对文件清单。\n */\n async readDelegationDelivery(\n runId: string,\n projectDir: string,\n delegationDir: string,\n ): Promise<{ result?: string; files: string[] }> {\n if (!this.remote) {\n const { readdir, readFile } = await import('node:fs/promises')\n const { join } = await import('node:path')\n const walk = async (dir: string, prefix: string, out: string[]): Promise<void> => {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return\n }\n for (const entry of entries) {\n const abs = join(dir, entry)\n const rel = prefix === '' ? entry : `${prefix}/${entry}`\n const info = await import('node:fs').then(fs => fs.statSync(abs)).catch(() => undefined)\n if (info?.isDirectory()) await walk(abs, rel, out)\n else out.push(rel)\n }\n }\n const files: string[] = []\n await walk(delegationDir, '', files)\n let result: string | undefined\n try {\n result = await readFile(join(delegationDir, 'result.md'), 'utf8')\n } catch {\n result = undefined\n }\n return { result, files: files.sort() }\n }\n // 远程:exec 原语。容器路径 = 宿主 delegationDir 去掉 projectDir 前缀。\n const containerPath = delegationDir.startsWith(projectDir)\n ? delegationDir.slice(projectDir.length).replace(/\\\\/g, '/')\n : '/workspace'\n const containerId = await this.findRunContainer(runId)\n if (containerId === undefined) return { files: [] }\n const list = await this.exec(containerId, { argv: ['sh', '-c', `find '${containerPath}' -type f | sort`] }).catch(() => undefined)\n const files = (list?.stdout ?? '')\n .split('\\n')\n .map(line => line.trim())\n .filter(line => line.startsWith(`${containerPath}/`))\n .map(line => line.slice(containerPath.length + 1))\n const resultText = await this.exec(containerId, { argv: ['cat', `${containerPath}/result.md`] }).catch(() => undefined)\n const result = resultText !== undefined && resultText.exitCode === 0 && resultText.stdout.trim() !== ''\n ? resultText.stdout\n : undefined\n return { result, files }\n }\n\n /**\n * Push 方向:把宿主侧 workspace/(本地镜像)打包解压进容器 /workspace。\n * 派发 delegation / advance 后调用,让 Worker 看到宿主写好的\n * target/、stage scaffold。排除 .git(Worker 不可改 Git)。\n * 本地 bind mount 下 host == container,无操作直接返回。\n */\n async pushWorkspace(runId: string, projectDir: string): Promise<void> {\n if (!this.remote) return\n const key = `${runId}:${projectDir}`\n const inFlight = this.pushing.get(key)\n if (inFlight !== undefined) return inFlight\n const task = this.findRunContainer(runId)\n .then(containerId =>\n containerId === undefined\n ? undefined\n : this.pushLocalMirror(containerId, projectDir),\n )\n .finally(() => this.pushing.delete(key))\n this.pushing.set(key, task)\n return task\n }\n\n private async pushLocalMirror(containerId: string, projectDir: string): Promise<void> {\n const localDir = localMirrorDir(projectDir)\n const archive = await packDirectory(localDir, { exclude: name => name === '.git' })\n const container = this.engine.getContainer(containerId)\n await container.putArchive(archive, { path: '/workspace' })\n }\n\n /**\n * Pull the volume's /workspace tree down into the local mirror. Works for\n * remote daemons; concurrent calls coalesce. Fire-and-forget after writes,\n * awaited before the Root wake. 本地 bind mount 下 host == container,无操作。\n * Mirror 语义(§20):create/update/delete 都反映 —— 容器中不存在的本地\n * 幽灵文件会被删除。Host 控制态(.git / .dsh-pentester)不参与 pull,\n * 防止 remote stale state 覆盖宿主 run.json(§19)。\n */\n async syncWorkspace(runId: string, projectDir: string): Promise<void> {\n if (!this.remote) return\n const key = `${runId}:${projectDir}`\n const inFlight = this.syncing.get(key)\n if (inFlight !== undefined) return inFlight\n const task = this.findRunContainer(runId)\n .then(containerId =>\n containerId === undefined\n ? undefined\n : this.pullWorkspace(containerId, projectDir),\n )\n .finally(() => this.syncing.delete(key))\n this.syncing.set(key, task)\n return task\n }\n\n private async findRunContainer(runId: string): Promise<string | undefined> {\n const matches = await this.engine.listContainers({\n all: true,\n filters: { label: [`dsh.pentester.run=${runId}`], status: ['running'] },\n })\n return matches.length > 0 ? String(matches[0].Id) : undefined\n }\n\n private async pullWorkspace(containerId: string, projectDir: string): Promise<void> {\n const localDir = localMirrorDir(projectDir)\n const tarStream = await this.engine.getContainer(containerId).getArchive({ path: '/workspace' })\n const extract = tar.extract()\n const done = new Promise<void>((resolve, reject) => {\n extract.on('error', reject)\n extract.on('finish', () => resolve())\n })\n const seen = new Set<string>()\n extract.on('entry', async (header, entryStream, next) => {\n try {\n const relative = normalizeArchivePath(header.name)\n if (relative !== undefined && header.type === 'file') {\n seen.add(relative)\n const target = join(localDir, relative)\n await mkdir(dirname(target), { recursive: true })\n const chunks: Buffer[] = []\n entryStream.on('data', (chunk: Buffer) => chunks.push(chunk))\n entryStream.on('end', () => {\n void writeFile(target, Buffer.concat(chunks)).then(next, next)\n })\n } else {\n entryStream.resume()\n entryStream.on('end', next)\n }\n } catch (error) {\n extract.destroy(error as Error)\n }\n })\n await Promise.all([\n pipeline(Readable.from(tarStream), extract),\n done,\n ])\n // Mirror 语义:删除容器中已不存在的本地幽灵文件(排除 Host 控制态)。\n await deleteMissing(localDir, seen, new Set(['.git', '.dsh-pentester']))\n }\n\n /** 镜像是否已就绪(本地存在)。 */\n async imageReady(image: string): Promise<boolean> {\n return imageReadyOn(this.engine, image)\n }\n\n async exec(containerId: string, input: ExecInput): Promise<ExecResult> {\n if (input.argv.length === 0) throw new DockerError('argv must not be empty')\n const timeoutMs = Math.min(input.timeoutMs ?? MAX_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const exec = await this.engine.getContainer(containerId).exec({\n Cmd: [...input.argv],\n AttachStdout: true,\n AttachStderr: true,\n ...(input.cwd === undefined ? {} : { WorkingDir: input.cwd }),\n Env: Object.entries(safeEnv(input.env)).map(([key, value]) => `${key}=${value}`),\n })\n const stdoutChunks: Buffer[] = []\n const stderrChunks: Buffer[] = []\n const stream = await exec.start({ hijack: true, stdin: false })\n const demux = demuxChunks(stream, stdoutChunks, stderrChunks)\n let timedOut = false\n const timer = setTimeout(() => {\n timedOut = true\n stream.destroy?.(new Error('exec timeout'))\n }, timeoutMs)\n let exitCode = 0\n try {\n await demux\n // 真实退出码来自 exec inspect(流本身不携带)。\n const info = await exec.inspect().catch(() => undefined)\n exitCode = info?.ExitCode ?? 0\n } finally {\n clearTimeout(timer)\n }\n return {\n exitCode: timedOut ? 124 : exitCode,\n stdout: truncate(Buffer.concat(stdoutChunks).toString('utf8')),\n stderr: truncate(Buffer.concat(stderrChunks).toString('utf8')),\n timedOut,\n }\n }\n}\n\n/** docker cp archive names look like `workspace/stage/D-001/file`; strip the root. */\nfunction normalizeArchivePath(name: string): string | undefined { const cleaned = name.replace(/\\\\/g, '/').replace(/^\\.\\//, '')\n const segments = posix.normalize(cleaned).split('/').filter(segment => segment !== '' && segment !== '.')\n if (segments.length === 0) return undefined\n if (segments[0] === 'workspace') segments.shift()\n if (segments.some(segment => segment === '..')) return undefined\n return segments.join('/')\n}\n\nfunction demuxChunks(\n stream: NodeJS.ReadableStream & { on(event: string, listener: (...args: unknown[]) => void): void },\n stdout: Buffer[],\n stderr: Buffer[],\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let header: Buffer | undefined\n stream.on('data', (chunk: unknown) => {\n let buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))\n while (buffer.length > 0) {\n if (header === undefined) {\n if (buffer.length < 8) {\n header = buffer\n return\n }\n header = buffer.subarray(0, 8)\n buffer = buffer.subarray(8)\n }\n const type = header[0]\n const length = header.readUInt32BE(4)\n const available = Math.min(length, buffer.length)\n const payload = buffer.subarray(0, available)\n if (type === 2) stderr.push(payload)\n else stdout.push(payload)\n buffer = buffer.subarray(available)\n if (available < length) {\n header = undefined\n return\n }\n header = undefined\n }\n })\n stream.on('end', () => resolve())\n stream.on('error', (error: unknown) => reject(error instanceof Error ? error : new Error(String(error))))\n })\n}\n\nfunction truncate(text: string): string {\n return text.length > MAX_OUTPUT_CHARS\n ? `${text.slice(0, MAX_OUTPUT_CHARS)}\\n[output truncated]`\n : text\n}\n\n/**\n * Mirror 语义:递归删除 `root` 下不在 `seen` 中的文件(幽灵文件清理)。\n * `excluded` 顶层目录(如 .git / .dsh-pentester 控制态)整体跳过。\n */\nasync function deleteMissing(\n root: string,\n seen: ReadonlySet<string>,\n excluded: ReadonlySet<string>,\n): Promise<void> {\n const walk = async (dir: string, prefix: string): Promise<void> => {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return\n }\n for (const entry of entries) {\n const rel = prefix === '' ? entry : `${prefix}/${entry}`\n if (prefix === '' && excluded.has(entry)) continue\n const abs = join(dir, entry)\n let info\n try {\n info = await stat(abs)\n } catch {\n continue\n }\n if (info.isDirectory()) {\n await walk(abs, rel)\n // 目录删空后移除空目录(镜像语义:容器侧没有的东西本地也不该有)。\n const remaining = await readdir(abs).catch(() => [])\n if (remaining.length === 0 && !excluded.has(entry)) {\n await rm(abs, { recursive: true, force: true }).catch(() => undefined)\n }\n } else if (!seen.has(rel)) {\n await rm(abs, { force: true }).catch(() => undefined)\n }\n }\n }\n await walk(root, '')\n}\n\n/** 把目录打包成 tar 流(push 方向;可排除顶层子目录如 .git)。 */\nasync function packDirectory(\n root: string,\n options: { exclude?: (name: string) => boolean } = {},\n): Promise<NodeJS.ReadableStream> {\n const { readdir, readFile, stat } = await import('node:fs/promises')\n const pack = tar.pack()\n void (async () => {\n const walk = async (dir: string, prefix: string): Promise<void> => {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return // 目录不存在:空 tar,putArchive 解压为空操作\n }\n for (const entry of entries) {\n if (prefix === '' && options.exclude?.(entry) === true) continue\n const abs = join(dir, entry)\n const rel = prefix === '' ? entry : `${posix.join(prefix, entry)}`\n let info\n try {\n info = await stat(abs)\n } catch {\n continue\n }\n if (info.isDirectory()) {\n await walk(abs, rel)\n } else if (info.isFile()) {\n const content = await readFile(abs)\n await new Promise<void>((resolve, reject) => {\n pack.entry({ name: rel, mode: info.mode, size: content.length }, content, error =>\n error === undefined || error === null ? resolve() : reject(error))\n })\n }\n }\n }\n try {\n await walk(root, '')\n pack.finalize()\n } catch (error) {\n pack.destroy(error instanceof Error ? error : new DockerError(String(error)))\n }\n })()\n return pack\n}\n","/**\n * worker-tools.ts — pentester_container_exec:唯一命令执行工具。\n * Registered inside the pentester preset scope(run-state.mjs 经宿主\n * pentester service);Root 的 per-agent restrict 隐藏、Worker child 经官方\n * toolFilter allow 独享。运行期仍做 caller 授权(§33:child SessionId 必须\n * 已绑定到某个 Delegation)。\n */\nimport { trustedCallerFromExec } from './dsh.js'\nimport { DockerRuntime, type ExecInput } from './docker/runtime.js'\nimport { resolvePentestRun } from './store.js'\nimport type { Delegation } from './model.js'\n\nexport const CONTAINER_EXEC_TOOL = 'pentester_container_exec'\n\nexport const CONTAINER_EXEC_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: false,\n required: ['argv'],\n properties: {\n argv: {\n type: 'array',\n items: { type: 'string' },\n minItems: 1,\n description: 'Command and arguments, no shell. e.g. [\"nmap\", \"-sV\", \"TARGET\"].',\n },\n cwd: { type: 'string', description: 'Working directory inside the container. Defaults to your delegation work/.' },\n env: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description: 'Optional environment variables.',\n },\n timeoutMs: { type: 'number', description: 'Optional timeout in milliseconds (bounded by the host max).' },\n },\n}\n\nexport interface ToolExecResult {\n exitCode: number\n stdout: string\n stderr: string\n timedOut: boolean\n}\n\nexport class WorkerToolError extends Error {}\n\nexport function makeContainerExecExecutor(docker: DockerRuntime, toolboxName = 'kali') {\n return async (args: Record<string, unknown>, exec?: unknown): Promise<ToolExecResult> => {\n const caller = trustedCallerFromExec(exec)\n // 只允许 DSH subagent child(continuable 或 one-shot)使用容器。\n if (caller === undefined || !caller.isSubagent) {\n throw new WorkerToolError('pentester_container_exec is reserved for delegated pentester workers')\n }\n const projectDir = caller.cwd\n if (projectDir === undefined) {\n throw new WorkerToolError('worker session has no trusted workspace cwd')\n }\n const run = await resolvePentestRun(projectDir)\n if (run === null) {\n throw new WorkerToolError('no PentestRun in this project; the Root Agent must start one first')\n }\n // §33:caller child SessionId 必须已绑定到一个 Delegation(host 在 spawn\n // 发布后立即写入 run.json)。找不到 → 拒绝执行,防止任何游离 Session 使用容器。\n const delegation = run.delegations.find(candidate => candidate.sessionId === caller.sessionId)\n if (delegation === undefined) {\n throw new WorkerToolError(\n `session ${caller.sessionId} is not bound to any delegation; only delegated workers may execute commands`,\n )\n }\n const toolbox = await docker.ensureImage(toolboxName)\n const containerId = await docker.ensureRunContainer({ runId: run.id, toolbox, projectDir })\n const input: ExecInput = {\n argv: Array.isArray(args.argv) ? args.argv.map(String) : [],\n ...(typeof args.cwd === 'string' ? { cwd: args.cwd } : { cwd: workerContainerWorkDir(projectDir, delegation) }),\n ...(isStringRecord(args.env) ? { env: args.env } : {}),\n ...(typeof args.timeoutMs === 'number' ? { timeoutMs: args.timeoutMs } : {}),\n }\n const result = await docker.exec(containerId, input)\n // Writes landed in the shared docker volume; pull them into the local\n // mirror asynchronously (remote-daemon friendly).\n void docker.syncWorkspace(run.id, projectDir).catch(() => undefined)\n return result\n }\n}\n\n/** Worker 的容器工作目录:`/workspace/stages/<NN>-<stage>/delegations/D-00N/work`。 */\nfunction workerContainerWorkDir(projectDir: string, delegation: Delegation): string {\n // host workspaceDir = <projectDir>/workspace/stages/...;容器把 <projectDir>/workspace 挂到 /workspace。\n const containerPath = delegation.workspaceDir.startsWith(projectDir)\n ? delegation.workspaceDir.slice(projectDir.length).replace(/\\\\/g, '/')\n : delegation.workspaceDir\n return `${containerPath}/work`\n}\n\n/**\n * 在调用者给定的 tools registry 上注册 pentester_container_exec(run-state.mjs\n * 把它注册进 pentester preset 的 standing scope;Root 看不到、Worker 独享)。\n */\nexport function registerContainerExecTool(\n tools: { register(definition: Record<string, unknown>): unknown },\n docker: DockerRuntime,\n): void {\n const execute = makeContainerExecExecutor(docker)\n tools.register({\n name: 'pentester_container_exec',\n description: 'Execute a command in the project run Toolbox container (/workspace = 共享交付 volume)。pentester 会话专用。',\n parameters: CONTAINER_EXEC_SCHEMA,\n output: {\n schema: { type: 'object', additionalProperties: true },\n render: (_args: unknown, value: unknown) => [{ type: 'text', text: JSON.stringify(value) }],\n },\n execute,\n })\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false\n return Object.values(value).every(entry => typeof entry === 'string')\n}\n","/**\n * settings-store.ts — 插件全局设置存储(Docker Engine 等宿主级偏好)。\n *\n * 存放位置:`$DSH_HOME/dsh-pentester/settings.json`(DSH_HOME 未设置时用\n * `~/.dsh`)。原子写(tmp + rename),单对象快照,无事件日志。\n * 该存储中的 dockerHost 是全局唯一 Docker 连接的显式配置;未设置时\n * 按本地优先的回退链解析(见 docker.ts 的 resolveDockerHost)。\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\n/** 设置文件当前 schema 版本。 */\nconst SETTINGS_VERSION = 1\n\n/** 全局设置快照。 */\nexport interface PentesterSettings {\n readonly schemaVersion: number\n /** 显式 Docker host(unix:///path 或 http(s)://host:port);空 = 未指定。 */\n dockerHost: string\n /** Toolbox 镜像覆盖(key = toolbox 名,如 kali);空 = 用默认镜像名。 */\n toolboxImages: Record<string, string>\n\n}\n\nexport class SettingsError extends Error {}\n\n/** 解析 DSH 根目录(优先 DSH_HOME 环境变量)。 */\nexport function dshHome(): string {\n return process.env.DSH_HOME ?? join(homedir(), '.dsh')\n}\n\nexport function settingsFilePath(home = dshHome()): string {\n return join(home, 'dsh-pentester', 'settings.json')\n}\n\n/** 读取全局设置;文件不存在时返回默认值(不落盘)。 */\nexport async function loadSettings(home = dshHome()): Promise<PentesterSettings> {\n const file = settingsFilePath(home)\n if (!existsSync(file)) {\n return { schemaVersion: SETTINGS_VERSION, dockerHost: '', toolboxImages: {}}\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(await readFile(file, 'utf8'))\n } catch (error) {\n throw new SettingsError(`settings.json 解析失败: ${error instanceof Error ? error.message : String(error)}`)\n }\n if (parsed === null || typeof parsed !== 'object' || (parsed as { schemaVersion?: unknown }).schemaVersion !== SETTINGS_VERSION) {\n throw new SettingsError('settings.json 版本不受支持')\n }\n const record = parsed as { dockerHost?: unknown; toolboxImages?: unknown; kaliSources?: unknown; kaliProxy?: unknown }\n const toolboxImages: Record<string, string> = {}\n if (record.toolboxImages !== null && typeof record.toolboxImages === 'object'\n && !Array.isArray(record.toolboxImages)) {\n for (const [key, value] of Object.entries(record.toolboxImages as Record<string, unknown>)) {\n if (typeof value === 'string' && value.trim() !== '') toolboxImages[key] = value.trim()\n }\n }\n return {\n schemaVersion: SETTINGS_VERSION,\n dockerHost: typeof record.dockerHost === 'string' ? record.dockerHost : '',\n toolboxImages,\n }\n}\n\n/** 确保 settings.json 存在:不存在则立即写入默认值(插件加载时调用)。 */\nexport async function ensureSettings(home = dshHome()): Promise<PentesterSettings> {\n const existing = await loadSettings(home)\n if (!existsSync(settingsFilePath(home))) {\n await saveSettings(existing, home)\n }\n return existing\n}\n\n/** 原子保存全局设置。 */\nexport async function saveSettings(settings: PentesterSettings, home = dshHome()): Promise<void> {\n const file = settingsFilePath(home)\n await mkdir(dirname(file), { recursive: true })\n const tmp = `${file}.tmp`\n await writeFile(tmp, `${JSON.stringify(settings, null, 2)}\\n`)\n await rename(tmp, file)\n}\n","import { Service } from \"@deepseek-ai/cordis\";\n//#region lib/types/index.js\n/**\n* Remote decorators and explicit Gateway bindings backed only by private\n* module state. Strict reflection remains a Typert compiler responsibility.\n* @module @deepseek-ai/dsh-typert-protocol\n*/\nconst TYPERT_REMOTE_SEGMENT_PATTERN = /^[A-Za-z0-9_$.-]+$/;\n/**\n* Test one generated Remote name against the Connection endpoint grammar.\n* @param value - namespace, method, lookup, or Context segment.\n* @returns whether the value can cross the shared RPC carrier unchanged.\n*/\nfunction isTypertRemoteSegment(value) {\n\treturn value !== \".\" && value !== \"..\" && TYPERT_REMOTE_SEGMENT_PATTERN.test(value);\n}\n/**\n* A lookup policy rejection whose typed payload belongs to the active boundary adapter.\n* Gateway adapters preserve this payload instead of collapsing it into an infrastructure failure.\n*/\nvar TypertLookupFailure = class extends Error {\n\t/** Adapter-owned failure returned to the caller. */\n\tfailure;\n\t/**\n\t* Wrap one adapter failure without exposing the rejected identity.\n\t* @param failure - typed failure owned by the active boundary adapter.\n\t*/\n\tconstructor(failure) {\n\t\tsuper(\"Typert lookup policy rejected the requested identity\");\n\t\tthis.name = \"TypertLookupFailure\";\n\t\tthis.failure = failure;\n\t}\n};\nconst markers = /* @__PURE__ */ new WeakMap();\n/**\n* Bind one visible Service field to a Cordis key and Remote namespace.\n* @param service - owning Service instance, normally `this`.\n* @param serviceKey - exact Cordis service key.\n* @param options - optional distinct wire namespace.\n* @returns a frozen, inspectable binding with no compiler-injected metadata.\n*/\nfunction bindTypertRemote(service, serviceKey, options = {}) {\n\tvalidateName(\"service key\", serviceKey);\n\tconst namespace = options.namespace ?? serviceKey;\n\tvalidateName(\"namespace\", namespace);\n\treturn Object.freeze({\n\t\tservice,\n\t\tserviceKey,\n\t\tnamespace\n\t});\n}\n/** Cordis Service base that exposes its registered name through Typert Gateway. */\nvar TypertRemoteService = class extends Service {\n\t/** Visible binding consumed by the Gateway's source-mode discovery. */\n\ttypertRemote;\n\t/**\n\t* Register the Service and bind the same key to Typert Gateway.\n\t* @param ctx - owning Cordis Context.\n\t* @param serviceKey - exact Cordis service key and default wire namespace.\n\t* @param options - optional distinct wire namespace.\n\t*/\n\tconstructor(ctx, serviceKey, options = {}) {\n\t\tsuper(ctx, serviceKey);\n\t\tthis.typertRemote = bindTypertRemote(this, this.name, options);\n\t}\n};\nfunction Remote(methodOrExportName, context) {\n\tif (typeof methodOrExportName === \"string\") {\n\t\tvalidateName(\"Remote export name\", methodOrExportName);\n\t\treturn function(_method, decoratorContext) {\n\t\t\taddMarkerInitializer(decoratorContext, { kind: \"direct\" }, methodOrExportName);\n\t\t};\n\t}\n\tif (context === void 0) throw new TypeError(\"typert-protocol: Remote decorator context is missing\");\n\taddMarkerInitializer(context, { kind: \"direct\" });\n}\n/**\n* Create a decorator for a method resolved from one Remote Scope.\n* @param key - scope key declared through the Context map.\n* @param exportName - optional Remote export name; defaults to the method name.\n* @returns a standard method decorator that records only private module state.\n*/\nfunction RemoteScope(key, exportName) {\n\tvalidateName(\"Scope key\", key);\n\tif (exportName !== void 0) validateName(\"Remote export name\", exportName);\n\treturn function(_method, context) {\n\t\taddMarkerInitializer(context, {\n\t\t\tkind: \"context\",\n\t\t\tcontext: key\n\t\t}, exportName);\n\t};\n}\n/**\n* Read Remote markers attached to a live Service by decorator initializers.\n* The returned snapshot cannot mutate the private marker table.\n* @param service - live Service instance.\n* @returns markers in class declaration order.\n*/\nfunction remoteMethods(service) {\n\tconst prototype = Object.getPrototypeOf(service);\n\tif (prototype === null) return [];\n\treturn [...markers.get(prototype) ?? []].map(([method, marker]) => ({\n\t\tmethod,\n\t\t...marker\n\t}));\n}\nfunction addMarkerInitializer(context, invocation, exportName) {\n\tif (context.private || context.static || typeof context.name !== \"string\") throw new TypeError(\"typert-protocol: Remote decorators require a public instance method with a string name\");\n\tconst method = context.name;\n\tcontext.addInitializer(function() {\n\t\tconst prototype = Object.getPrototypeOf(this);\n\t\tif (prototype === null) throw new TypeError(`typert-protocol: cannot mark Remote method \"${method}\" on an object without a prototype`);\n\t\tmark(prototype, method, invocation, exportName);\n\t});\n}\nfunction mark(prototype, method, invocation, exportName) {\n\tlet table = markers.get(prototype);\n\tif (table === void 0) {\n\t\ttable = /* @__PURE__ */ new Map();\n\t\tmarkers.set(prototype, table);\n\t}\n\tconst marker = {\n\t\t...exportName === void 0 || exportName === method ? {} : { exportName },\n\t\tinvocation: Object.freeze(invocation)\n\t};\n\tconst current = table.get(method);\n\tif (current !== void 0) {\n\t\tif (current.exportName === marker.exportName && sameInvocation(current.invocation, invocation)) return;\n\t\tthrow new Error(`typert-protocol: Remote method \"${method}\" has conflicting invocation markers`);\n\t}\n\ttable.set(method, Object.freeze(marker));\n}\nfunction sameInvocation(left, right) {\n\treturn left.kind === right.kind && (left.kind === \"direct\" || right.kind === \"context\" && left.context === right.context);\n}\nfunction validateName(subject, value) {\n\tif (!isTypertRemoteSegment(value)) throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`);\n}\n//#endregion\nexport { Remote, RemoteScope, TypertLookupFailure, TypertRemoteService, bindTypertRemote, isTypertRemoteSegment, remoteMethods };\n","/**\n * invocations.ts — `remote.pentesterDocker` 的严格调用描述符。\n *\n * 宿主(Typert manifest)与客户端(remote 网关贡献)共用同一份:\n * 官方 api-gateway 契约要求客户端贡献必须携带 strict codec,\n * “Client Remote refuses to mount SRC descriptors that lack strict\n * codecs” —— 缺 codec 的描述符会被客户端网关拒绝挂载(此前 UI 报\n * rpc_unavailable 的根因)。本模块只依赖 zod,两侧均可安全导入。\n */\nimport { z } from 'zod'\n\n/** 传输层输入 schema(宽松外壳,分发前再严格校验)。 */\nexport const dockerRpcInputSchema = z.object({ kind: z.string() }).passthrough()\n\nconst dockerHostStateSchema = z.object({\n dockerHost: z.string(),\n effective: z.string(),\n remote: z.boolean(),\n source: z.enum(['settings', 'config', 'local', 'env', 'default']),\n})\n\nconst dockerProbeSchema = z.object({\n reachable: z.boolean(),\n endpoint: z.string(),\n version: z.string().optional(),\n apiVersion: z.string().optional(),\n os: z.string().optional(),\n error: z.string().optional(),\n})\n\n/** `remote.pentesterDocker.command` 的严格描述符(含 codec 与 result schema)。 */\nexport const PENTESTER_DOCKER_INVOCATION = {\n id: 'dsh-pentester#pentesterDocker/command',\n service: 'pentesterDocker',\n namespace: 'pentesterDocker',\n method: 'command',\n invocation: { kind: 'direct' as const },\n // 全局设置 RPC:无 Agent/scope 上下文 —— Settings 页是根级贡献,单参数。\n parameters: [\n {\n name: 'input',\n wire: 'input',\n source: 'json' as const,\n codec: {\n mode: 'strict' as const,\n typeSymbol: 'dsh-pentester#DockerRpcInput',\n schema: dockerRpcInputSchema,\n },\n },\n ],\n result: {\n mode: 'strict' as const,\n typeSymbol: 'dsh-pentester#DockerRpcResult',\n schema: z.object({\n ok: z.boolean(),\n value: z.union([dockerHostStateSchema, dockerProbeSchema, z.record(z.string(), z.unknown())]).optional(),\n error: z.string().optional(),\n code: z.string().optional(),\n }),\n },\n} as const\n\n/** 客户端 remote 网关的挂载贡献。 */\nexport const PENTESTER_REMOTE = {\n package: 'dsh-pentester',\n descriptors: [PENTESTER_DOCKER_INVOCATION],\n} as const\n","/**\n * docker/connection.ts — 远程 Docker 连接管理(Settings “Docker Host” 卡片的后端)。\n *\n * 职责:连接字符串解析(Node URL 类)、高级连接参数(TLS / SSH)→ dockerode\n * 构造参数、连接测试(GET /version + 超时)。只服务于 Settings 页的“测试连接”,\n * 不改变当前生效连接(全局 host 解析仍走 host.ts)。\n */\nimport Dockerode from 'dockerode'\nimport {\n DEFAULT_UNIX_SOCKET,\n DockerError,\n formatDockerHost,\n type DockerEngineLike,\n type DockerHost,\n type DockerProbe,\n} from './host.js'\n\n/** 解析后的连接规格(connectionString 或 advanced 面板的归一化结果)。 */\nexport interface ConnectionSpec {\n readonly protocol: 'tcp' | 'http' | 'https' | 'unix'\n readonly host?: string\n readonly port?: number\n readonly socketPath?: string\n}\n\n/** 认证方式。TLS:ca/cert/key 原文;SSH:username + password 或 privateKey。 */\nexport type ConnectionAuth =\n | { readonly type: 'none' }\n | { readonly type: 'tls'; readonly ca?: string; readonly cert?: string; readonly key?: string }\n | { readonly type: 'ssh'; readonly username?: string; readonly password?: string; readonly privateKey?: string }\n\n/** 高级连接参数(UI 高级设置面板的完整表达;协议取 UI 下拉的三项)。 */\nexport interface AdvancedConnection {\n readonly protocol: 'tcp' | 'http' | 'unix'\n readonly host: string\n readonly port?: number\n readonly auth?: ConnectionAuth\n}\n\n/** 测试连接请求:connectionString 优先,为空则用 advanced(与规格一致)。 */\nexport interface ConnectionTestInput {\n readonly connectionString?: string\n readonly advanced?: AdvancedConnection\n}\n\n/**\n * 用 Node 内置 URL 类解析连接字符串(与 DOCKER_HOST 同格式)。\n * 支持的协议:tcp: / http: / https: / unix:(或裸 socket 路径)。\n * tcp/http 缺省端口 2375,https 缺省 2376。\n */\nexport function parseConnectionString(value: string): ConnectionSpec {\n const raw = value.trim()\n if (raw === '') throw new DockerError('empty docker host')\n if (raw.startsWith('/') && !raw.includes('://')) return { protocol: 'unix', socketPath: raw }\n // 空 authority(tcp:// 或 tcp://:2375)在 URL 构造前报“缺少主机名”。\n const schemeMatch = /^(tcp|http|https):\\/\\//i.exec(raw)\n if (schemeMatch !== null) {\n const authority = raw.slice(schemeMatch[0].length).replace(/\\/.*$/, '')\n if (authority === '' || authority.startsWith(':')) {\n throw new DockerError(`docker host missing hostname: ${raw}`)\n }\n }\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n throw new DockerError(`无法解析的连接字符串:${raw}`)\n }\n const scheme = url.protocol.replace(':', '')\n if (scheme === 'unix') {\n // 规范形式 unix:///path → pathname 即 socket 路径;兜底 hostname / 默认 socket。\n let socketPath = url.pathname\n if (socketPath === '' || socketPath === '/') {\n socketPath = url.hostname !== '' ? `/${url.hostname}` : DEFAULT_UNIX_SOCKET\n }\n return { protocol: 'unix', socketPath }\n }\n if (scheme !== 'tcp' && scheme !== 'http' && scheme !== 'https') {\n throw new DockerError(\n `unsupported docker host: ${raw} (use tcp://host:port, http://host:port or unix:///path)`,\n )\n }\n if (url.hostname === '') throw new DockerError(`docker host missing hostname: ${raw}`)\n const port = url.port === '' ? (scheme === 'https' ? 2376 : 2375) : Number(url.port)\n if (!Number.isInteger(port)) throw new DockerError(`docker host invalid port: ${raw}`)\n return { protocol: scheme as ConnectionSpec['protocol'], host: url.hostname, port }\n}\n\n/** 高级设置面板 → 连接规格。 */\nexport function advancedToSpec(advanced: AdvancedConnection): ConnectionSpec {\n const host = advanced.host.trim()\n if (host === '') throw new DockerError('高级设置:缺少主机地址')\n if (advanced.protocol === 'unix') return { protocol: 'unix', socketPath: host }\n return { protocol: advanced.protocol, host, port: advanced.port ?? 2375 }\n}\n\n/**\n * 构建 dockerode 构造参数。\n * tcp/http 无 TLS → { host, port };TLS → 附 ca/cert/key(modem 自动切 https)\n * ssh → { protocol:'ssh', username, password | sshOptions.privateKey }\n * unix → { socketPath }\n */\nexport function buildDockerOptions(\n spec: ConnectionSpec,\n auth?: ConnectionAuth,\n): ConstructorParameters<typeof Dockerode>[0] {\n if (spec.protocol === 'unix') return { socketPath: spec.socketPath ?? DEFAULT_UNIX_SOCKET }\n const host = spec.host ?? ''\n const port = spec.port ?? 2375\n if (auth !== undefined && auth.type === 'ssh') {\n const options: Record<string, unknown> = { protocol: 'ssh', host, port }\n if (auth.username !== undefined && auth.username !== '') options.username = auth.username\n if (auth.privateKey !== undefined && auth.privateKey !== '') {\n options.sshOptions = { privateKey: auth.privateKey }\n } else if (auth.password !== undefined && auth.password !== '') {\n options.password = auth.password\n }\n return options as ConstructorParameters<typeof Dockerode>[0]\n }\n if (auth !== undefined && auth.type === 'tls') {\n const options: Record<string, unknown> = { host, port }\n if (auth.ca !== undefined) options.ca = auth.ca\n if (auth.cert !== undefined) options.cert = auth.cert\n if (auth.key !== undefined) options.key = auth.key\n return options as ConstructorParameters<typeof Dockerode>[0]\n }\n if (spec.protocol === 'https') return { protocol: 'https', host, port }\n return { host, port }\n}\n\n/** 探测结果的 endpoint 展示(与 host.ts 的 formatDockerHost 对齐)。 */\nfunction endpointFor(spec: ConnectionSpec, auth?: ConnectionAuth): string {\n if (spec.protocol === 'unix') return `unix://${spec.socketPath ?? DEFAULT_UNIX_SOCKET}`\n if (auth !== undefined && auth.type === 'ssh') {\n const user = auth.username !== undefined && auth.username !== '' ? `${auth.username}@` : ''\n return `ssh://${user}${spec.host}:${spec.port}`\n }\n const host: DockerHost =\n spec.protocol === 'tcp'\n ? { protocol: 'http', host: spec.host, port: spec.port }\n : { protocol: spec.protocol, host: spec.host, port: spec.port }\n return formatDockerHost(host)\n}\n\ninterface ResolvedConnection {\n readonly options: ConstructorParameters<typeof Dockerode>[0]\n readonly endpoint: string\n}\n\n/** 请求 → dockerode 构造参数 + 展示 endpoint。 */\nexport function resolveConnection(input: ConnectionTestInput): ResolvedConnection {\n if (input.connectionString !== undefined && input.connectionString.trim() !== '') {\n const spec = parseConnectionString(input.connectionString)\n return { options: buildDockerOptions(spec), endpoint: endpointFor(spec) }\n }\n if (input.advanced !== undefined) {\n const spec = advancedToSpec(input.advanced)\n const auth = input.advanced.auth\n return { options: buildDockerOptions(spec, auth), endpoint: endpointFor(spec, auth) }\n }\n throw new DockerError('empty docker host')\n}\n\n/** 测试依赖(engine 可注入以便测试;timeoutMs 默认 10s)。 */\nexport interface DockerTestDeps {\n readonly engine?: Pick<DockerEngineLike, 'version'>\n readonly timeoutMs?: number\n}\n\n/**\n * 测试一个(未保存的)连接:GET /version,成功返回版本信息,\n * 失败返回友好错误(含超时)。私钥/密码只进 dockerode 构造,不回传。\n */\nexport async function testDockerConnection(\n input: ConnectionTestInput,\n deps: DockerTestDeps = {},\n): Promise<DockerProbe> {\n let resolved: ResolvedConnection\n try {\n resolved = resolveConnection(input)\n } catch (error) {\n return { reachable: false, endpoint: '', error: error instanceof Error ? error.message : String(error) }\n }\n const { options, endpoint } = resolved\n const timeoutMs = deps.timeoutMs ?? 10_000\n const engine = deps.engine ?? (new Dockerode(options) as unknown as Pick<DockerEngineLike, 'version'>)\n try {\n const info = await withTimeout(engine.version(), timeoutMs)\n return {\n reachable: true,\n endpoint,\n ...(typeof info.Version === 'string' ? { version: info.Version } : {}),\n ...(typeof info.ApiVersion === 'string' ? { apiVersion: info.ApiVersion } : {}),\n ...(typeof info.Os === 'string' ? { os: info.Os } : {}),\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return { reachable: false, endpoint, error: message.startsWith('连接超时') ? message : `连接失败:${message}` }\n }\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`连接超时(${ms / 1000}s)`)), ms)\n promise.then(\n (value) => { clearTimeout(timer); resolve(value) },\n (error) => { clearTimeout(timer); reject(error) },\n )\n })\n}\n","/**\n * rpc.ts — Docker Engine 设置的 Typert RPC(宿主侧)。\n *\n * Settings UI 的 \"Docker Engine\" Tab 通过 `remote.pentesterDocker` 命名空间\n * 调用 `command(input)`;输入是类型化的 `{ kind: 'get' | 'set', ... }`,\n * 与旧 Config RPC 同构(单一 command 通道 + 双层信封解包)。\n * 不含任何自然语言命令;宿主侧校验后委托给 settings-store 与 DockerRuntime。\n */\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport { z } from 'zod'\nimport { dockerRpcInputSchema, PENTESTER_DOCKER_INVOCATION } from './invocations.js'\nimport { testDockerConnection, type AdvancedConnection, type ConnectionTestInput } from './docker/connection.js'\nimport type { DockerHost, DockerHostSource, DockerProbe } from './docker/host.js'\nimport { formatDockerHost, isRemoteHost, parseDockerHost, probeDockerHost, resolveDockerHostWithSource, type ResolvedDockerHost } from './docker/host.js'\nimport { toolboxFor, TOOLBOX_ALLOWLIST } from './docker/images.js'\nimport type { PentesterSettings } from './settings-store.js'\n\n/** 传输层输入 schema(宽松外壳 + 严格分发校验)。 */\nconst dockerRpcSchema = dockerRpcInputSchema\n\n/** 高级连接参数校验(Settings \"Docker Host\" 卡片的 advanced 面板)。 */\nconst connectionAuthSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('none') }),\n z.object({\n type: z.literal('tls'),\n ca: z.string().optional(),\n cert: z.string().optional(),\n key: z.string().optional(),\n }),\n z.object({\n type: z.literal('ssh'),\n username: z.string().optional(),\n password: z.string().optional(),\n privateKey: z.string().optional(),\n }),\n])\n\nconst advancedConnectionSchema = z.object({\n protocol: z.enum(['tcp', 'http', 'unix']),\n host: z.string(),\n port: z.number().int().min(1).max(65535).optional(),\n auth: connectionAuthSchema.optional(),\n})\n\n/** Docker RPC 的合法输入。 */\nexport type DockerRpcInput =\n | { readonly kind: 'get' }\n | { readonly kind: 'set'; readonly dockerHost: string }\n /**\n * 测试一个候选连接(不保存);dockerHost 缺省 = 测试当前生效值。\n * advanced = 高级设置面板(TLS/SSH);connectionString 优先于 advanced。\n */\n | { readonly kind: 'test'; readonly dockerHost?: string; readonly advanced?: AdvancedConnection }\n /** 查询 toolbox 镜像状态(是否 ready)。 */\n | { readonly kind: 'image.status' }\n /** 保存 toolbox 镜像覆盖(空 = 恢复默认镜像名)。 */\n | { readonly kind: 'image.set'; readonly image: string }\n\n/** 镜像状态(Toolbox Image 配置区)。 */\nexport interface ImageStatus {\n readonly image: string\n readonly ready: boolean\n /** 默认镜像名(输入框 placeholder)。 */\n readonly defaultImage: string\n}\n\n/** get/set 返回的状态快照(UI 显示与实际选择一一对应,不留白)。 */\nexport interface DockerHostState {\n /** 用户显式配置的 host;空字符串 = 未指定(走自动解析链)。 */\n readonly dockerHost: string\n /** 当前实际生效的 endpoint(如 unix:///var/run/docker.sock)。 */\n readonly effective: string\n readonly remote: boolean\n /** 生效来源:settings / config / local / env / default。 */\n readonly source: DockerHostSource\n}\n\nexport type DockerRpcResult =\n | { readonly ok: true; readonly value: DockerHostState | DockerProbe | ImageStatus }\n | { readonly ok: false; readonly error: string; readonly code?: string }\n\n/** 校验一条输入(严格模式:未知 kind / 非法 host 直接拒绝)。 */\nexport function parseDockerRpcInput(input: unknown): { ok: true; value: DockerRpcInput } | { ok: false; reason: string } {\n let parsed: z.output<typeof dockerRpcSchema>\n try {\n parsed = dockerRpcSchema.parse(input)\n } catch {\n return { ok: false, reason: 'invalid_request' }\n }\n if (parsed.kind === 'get') return { ok: true, value: { kind: 'get' } }\n if (parsed.kind === 'test') {\n const raw = (parsed as { dockerHost?: unknown }).dockerHost\n const advancedRaw = (parsed as { advanced?: unknown }).advanced\n let advanced: AdvancedConnection | undefined\n if (advancedRaw !== undefined) {\n const check = advancedConnectionSchema.safeParse(advancedRaw)\n if (!check.success) return { ok: false, reason: 'invalid_advanced' }\n advanced = check.data as AdvancedConnection\n }\n if (raw === undefined) {\n return { ok: true, value: { kind: 'test', ...(advanced !== undefined ? { advanced } : {}) } }\n }\n if (typeof raw !== 'string') return { ok: false, reason: 'invalid_docker_host' }\n if (raw.trim() !== '') {\n try {\n parseDockerHost(raw)\n } catch (error) {\n return { ok: false, reason: error instanceof Error ? error.message : 'invalid_docker_host' }\n }\n }\n return {\n ok: true,\n value: {\n kind: 'test',\n ...(raw.trim() !== '' ? { dockerHost: raw.trim() } : {}),\n ...(advanced !== undefined ? { advanced } : {}),\n },\n }\n }\n if (parsed.kind === 'image.status') {\n return { ok: true, value: { kind: 'image.status' } }\n }\n if (parsed.kind === 'image.set') {\n const imageValue = (parsed as { image?: unknown }).image\n const image = typeof imageValue === 'string' ? imageValue.trim() : undefined\n if (image === undefined) return { ok: false, reason: 'image_required' }\n return { ok: true, value: { kind: 'image.set', image } }\n }\n if (parsed.kind === 'set') {\n const hostValue = (parsed as { dockerHost?: unknown }).dockerHost\n const host = typeof hostValue === 'string' ? hostValue : undefined\n if (host === undefined) return { ok: false, reason: 'dockerHost_required' }\n // 空串合法(= 清除显式配置,回到本地优先);非空必须能被解析。\n if (host.trim() !== '') {\n try {\n parseDockerHost(host)\n } catch (error) {\n return { ok: false, reason: error instanceof Error ? error.message : 'invalid_docker_host' }\n }\n }\n return { ok: true, value: { kind: 'set', dockerHost: host.trim() } }\n }\n return { ok: false, reason: 'unsupported_kind' }\n}\n\n/** 宿主侧依赖(由 index.ts 注入,便于测试)。 */\nexport interface DockerRpcDeps {\n /** 读取当前全局设置。 */\n readonly getSettings: () => Promise<PentesterSettings>\n /** 插件配置里的 dockerHost(第二优先级)。 */\n readonly getConfigHost: () => string\n /** 持久化新的 dockerHost(已校验),返回保存后的设置。 */\n readonly saveDockerHost: (dockerHost: string) => Promise<PentesterSettings>\n /** 持久化整个设置对象(image 等)。 */\n readonly saveSettings: (settings: PentesterSettings) => Promise<void>\n /** 切换 DockerRuntime 连接(热生效)。 */\n readonly applyHost: (host: DockerHost) => void\n /** 解析(可注入 socketExists 测试)。 */\n readonly resolve?: (settingsHost: string, configHost: string) => ResolvedDockerHost\n /** 连接探测(可注入假引擎测试)。 */\n readonly probe?: (host: DockerHost) => Promise<DockerProbe>\n /** 高级连接测试(connectionString / advanced,可注入假引擎测试)。 */\n readonly testConnection?: (input: ConnectionTestInput) => Promise<DockerProbe>\n /** Docker 引擎操作面(镜像 inspect + 镜像覆盖热更新)。 */\n readonly docker: {\n imageReady(image: string): Promise<boolean>\n updateToolboxImage(toolbox: string, image: string | undefined): void\n }\n}\n\n/** 计算某个显式配置下的状态快照。 */\nexport function dockerHostState(settings: PentesterSettings, resolved: ResolvedDockerHost): DockerHostState {\n return {\n dockerHost: settings.dockerHost,\n effective: formatDockerHost(resolved.host),\n remote: isRemoteHost(resolved.host),\n source: resolved.source,\n }\n}\n\n/** 分发一条已校验的输入。 */\nexport async function dispatchDockerRpc(deps: DockerRpcDeps, input: DockerRpcInput): Promise<DockerRpcResult> {\n const resolve = deps.resolve ?? ((settingsHost: string, configHost: string) =>\n resolveDockerHostWithSource(settingsHost, configHost))\n const probe = deps.probe ?? ((host: DockerHost) => probeDockerHost(host))\n try {\n if (input.kind === 'get') {\n const settings = await deps.getSettings()\n return { ok: true, value: dockerHostState(settings, resolve(settings.dockerHost, deps.getConfigHost())) }\n }\n if (input.kind === 'test') {\n const testConnection = deps.testConnection ?? testDockerConnection\n // connectionString(主输入框)优先,为空才用 advanced(高级面板);\n // 两者都空 = 测试当前生效连接。\n if (input.dockerHost !== undefined && input.dockerHost !== '') {\n return { ok: true, value: await testConnection({ connectionString: input.dockerHost }) }\n }\n if (input.advanced !== undefined) {\n return { ok: true, value: await testConnection({ advanced: input.advanced }) }\n }\n const host = resolve((await deps.getSettings()).dockerHost, deps.getConfigHost()).host\n return { ok: true, value: await probe(host) }\n }\n if (input.kind === 'image.status') {\n const settings = await deps.getSettings()\n const image = toolboxFor('kali', settings.toolboxImages).image\n return {\n ok: true,\n value: {\n image,\n ready: await deps.docker.imageReady(image),\n defaultImage: TOOLBOX_ALLOWLIST[0].image,\n },\n }\n }\n if (input.kind === 'image.set') {\n const settings = await deps.getSettings()\n const next = { ...settings, toolboxImages: { ...settings.toolboxImages } }\n if (input.image === '') delete next.toolboxImages.kali\n else next.toolboxImages.kali = input.image\n await deps.saveSettings(next)\n deps.docker.updateToolboxImage('kali', input.image === '' ? undefined : input.image)\n const image = toolboxFor('kali', next.toolboxImages).image\n return {\n ok: true,\n value: {\n image,\n ready: await deps.docker.imageReady(image),\n defaultImage: TOOLBOX_ALLOWLIST[0].image,\n },\n }\n }\n const settings = await deps.saveDockerHost(input.dockerHost)\n const resolved = resolve(settings.dockerHost, deps.getConfigHost())\n deps.applyHost(resolved.host)\n return { ok: true, value: dockerHostState(settings, resolved) }\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : 'docker_rpc_failed', code: 'docker_rpc_failed' }\n }\n}\n\n/**\n * 宿主 Typert 服务:绑定到 `pentesterDocker` 命名空间。\n * Settings 页面是根级贡献,无 Agent 查找 —— 单参数 command。\n */\nexport class PentesterDockerTypertService extends TypertRemoteService {\n private readonly deps: DockerRpcDeps\n\n constructor(ctx: unknown, deps: DockerRpcDeps) {\n super(ctx as never, 'pentesterDocker')\n this.deps = deps\n }\n\n command(input: unknown): Promise<DockerRpcResult> {\n const parsed = parseDockerRpcInput(input)\n if (!parsed.ok) {\n return Promise.resolve({ ok: false, error: parsed.reason, code: 'invalid_request' })\n }\n return dispatchDockerRpc(this.deps, parsed.value)\n }\n}\n\n/** 插件的 Typert manifest(仅 Docker Engine 设置面)。 */\nexport const TYPERT_MANIFEST = {\n package: 'dsh-pentester',\n face: 'host' as const,\n schemas: [],\n model: {\n services: [\n {\n key: 'pentesterDocker',\n exportName: 'PentesterDockerTypertService',\n description: 'Pentester Docker Engine 设置(Settings UI Docker Engine Tab)。',\n tags: [],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: object): Promise<{ok:boolean; value?: {dockerHost:string; effective:string; remote:boolean}; error?: string; code?: string}>',\n },\n ],\n types: [],\n },\n ],\n events: [],\n objects: [],\n },\n invocations: [PENTESTER_DOCKER_INVOCATION],\n}\n","/**\n * git.ts — GitCheckpointService:workspace 的 git 仓库管理(宿主侧)。\n *\n * 仓库根 = <project>/workspace(= 容器 /workspace 的宿主镜像;.git 不随\n * volume 同步,Worker 物理上无法改 Git 状态)。约定式提交:\n * - 初始:`workspace: initialize <target>`\n * - 阶段完成:`ptes(<NN>-<stage>): complete` + tag `ptes/<NN>-<stage>`\n *\n * git 命令经注入的 runner 执行(生产 = child_process.execFile,测试 = fake)。\n */\nimport { execFile } from 'node:child_process'\nimport { mkdir } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { stageDir, type StageId } from './model.js'\nimport { workspaceDir } from './store.js'\n\nexport class GitCheckpointError extends Error {}\n\n/** git 命令执行器(返回 stdout;非零退出抛错)。 */\nexport type GitRunner = (args: readonly string[], cwd: string) => Promise<string>\n\nexport function realGitRunner(): GitRunner {\n return (args, cwd) =>\n new Promise((resolve, reject) => {\n execFile('git', [...args], { cwd, maxBuffer: 10 * 1024 * 1024 }, (error, stdout) => {\n if (error !== null && error !== undefined) {\n reject(new GitCheckpointError(`git ${args[0] ?? ''} failed: ${error.message}`))\n return\n }\n resolve(stdout)\n })\n })\n}\n\nexport interface GitCheckpointDeps {\n readonly runner?: GitRunner\n readonly userName?: string\n readonly userEmail?: string\n /** 测试注入:覆盖文件系统 .git 探测(fake runner 不落盘)。 */\n readonly isRepo?: (projectDir: string) => Promise<boolean>\n}\n\n/** workspace git 仓库管理(幂等 init;阶段完成 checkpoint)。 */\nexport class GitCheckpointService {\n private readonly runner: GitRunner\n private readonly userName: string\n private readonly userEmail: string\n private readonly isRepoOverride?: (projectDir: string) => Promise<boolean>\n\n constructor(deps: GitCheckpointDeps = {}) {\n this.runner = deps.runner ?? realGitRunner()\n this.userName = deps.userName ?? 'dsh-pentester'\n this.userEmail = deps.userEmail ?? 'dsh-pentester@local'\n this.isRepoOverride = deps.isRepo\n }\n\n /** 仓库根目录(<project>/workspace)。 */\n repoDir(projectDir: string): string {\n return workspaceDir(projectDir)\n }\n\n /** 是否已是 git 仓库(存在 .git)。 */\n async isRepo(projectDir: string): Promise<boolean> {\n if (this.isRepoOverride !== undefined) return this.isRepoOverride(projectDir)\n return existsSync(join(this.repoDir(projectDir), '.git'))\n }\n\n /**\n * 初始化仓库:`git init -b main` + 本地身份 + 初始提交。\n * 幂等:已是仓库则直接返回。\n */\n async init(projectDir: string, target?: string): Promise<void> {\n const cwd = this.repoDir(projectDir)\n await mkdir(cwd, { recursive: true })\n if (await this.isRepo(projectDir)) return\n await this.runner(['init', '-b', 'main'], cwd).catch(async () => {\n // 旧版 git 无 -b:init 后手动建 main 分支。\n await this.runner(['init'], cwd)\n await this.runner(['checkout', '-b', 'main'], cwd).catch(() => undefined)\n })\n await this.runner(['config', 'user.name', this.userName], cwd)\n await this.runner(['config', 'user.email', this.userEmail], cwd)\n await this.runner(['add', '-A'], cwd)\n await this.commit(cwd, `workspace: initialize ${target ?? 'pentest'}`)\n }\n\n /** 阶段完成 checkpoint:`git add -A` → commit → tag。返回 tag 名。 */\n async checkpointStage(projectDir: string, stage: StageId): Promise<string> {\n if (!(await this.isRepo(projectDir))) {\n throw new GitCheckpointError('workspace is not a git repository; run initWorkspace first')\n }\n const cwd = this.repoDir(projectDir)\n const dir = stageDir(stage)\n await this.runner(['add', '-A'], cwd)\n await this.commit(cwd, `ptes(${dir}): complete`)\n const tag = `ptes/${dir}`\n // tag 冲突处理(T25):main 与 rework 都可能完成同一 stage —— tag 已存在\n // 时不报错(tag 只是人类可读 checkpoint ref,正确性依赖 commit subject)。\n const exists = await this.runner(['tag', '-l', tag], cwd).then(out => out.trim().length > 0, () => false)\n if (!exists) {\n await this.runner(['tag', tag], cwd)\n }\n return tag\n }\n\n /** 当前 git 分支名(rollback / Root state 用)。 */\n async currentBranch(projectDir: string): Promise<string> {\n const cwd = this.repoDir(projectDir)\n const out = await this.runner(['branch', '--show-current'], cwd).catch(() => '')\n return out.trim() || 'main'\n }\n\n /** working tree 是否有未提交变更(rollback 前决定是否建 backup branch)。 */\n async hasChanges(projectDir: string): Promise<boolean> {\n const cwd = this.repoDir(projectDir)\n const out = await this.runner(['status', '--porcelain'], cwd).catch(() => '')\n return out.trim() !== ''\n }\n\n /**\n * 在 HEAD 的 first-parent reachable 历史中找目标 stage 的 completion commit\n * (subject `ptes(<NN>-<stage>): complete`)。不假设 tag 属于当前 branch\n * namespace(§31);tag 只是人类可读 ref。找不到返回 undefined。\n */\n async findStageCheckpoint(projectDir: string, stage: StageId): Promise<string | undefined> {\n const cwd = this.repoDir(projectDir)\n const dir = stageDir(stage)\n const out = await this.runner(\n ['log', '--first-parent', '--format=%H%x00%s', 'HEAD'],\n cwd,\n ).catch(() => '')\n for (const line of out.split('\\n')) {\n if (line.trim() === '') continue\n const [hash, ...subjectParts] = line.split('\\u0000')\n const subject = subjectParts.join('\\u0000')\n if (hash !== undefined && subject === `ptes(${dir}): complete`) return hash\n }\n return undefined\n }\n\n /** 建 backup branch:`backup/rollback-<ts>` + WIP commit(只在有变更时调用)。 */\n async createBackupBranch(projectDir: string, stage: string): Promise<string> {\n const cwd = this.repoDir(projectDir)\n const branch = `backup/rollback-${Date.now()}`\n await this.runner(['checkout', '-b', branch], cwd)\n await this.runner(['add', '-A'], cwd)\n await this.commit(cwd, `wip: before rollback to ${stage}`)\n return branch\n }\n\n /**\n * 从 checkpoint commit 建 rework branch:`rework/<next-stage-slug>-<n>`。\n * n 自动找下一个可用值(已有分支 +1)。\n */\n async createReworkBranch(projectDir: string, checkpoint: string, nextStageSlug: string): Promise<string> {\n const cwd = this.repoDir(projectDir)\n const existing = await this.runner(['branch', '--format=%(refname:short)'], cwd).catch(() => '')\n const prefix = `rework/${nextStageSlug}-`\n let n = 1\n for (const line of existing.split('\\n')) {\n const match = /^rework\\/[^/]+-(\\d+)$/.exec(line.trim())\n if (match !== null) n = Math.max(n, Number(match[1]) + 1)\n }\n const branch = `${prefix}${n}`\n await this.runner(['checkout', '-b', branch, checkpoint], cwd)\n return branch\n }\n\n /** checkout 到已有分支 / commit(rollback 收尾)。 */\n async checkout(projectDir: string, ref: string): Promise<void> {\n const cwd = this.repoDir(projectDir)\n await this.runner(['checkout', ref], cwd)\n }\n\n private async commit(cwd: string, message: string): Promise<void> {\n // 无改动时 git commit 报 nothing to commit —— 视为已是最新,直接成功。\n await this.runner(['commit', '-m', message], cwd).catch(error => {\n const text = error instanceof Error ? error.message : String(error)\n if (text.includes('nothing to commit') || text.includes('nothing added')) return\n throw error\n })\n }\n}\n","/**\n * index.ts — cordis plugin entry (contract per docs/architecture.md):\n * publish the pentester preset, then wire the Root tools over the\n * DSH agents seam。Workers 的工具面 restrict 到 pentester_container_exec。\n */\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport Schema from '@deepseek-ai/schemastery'\nimport { cp, mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { DshClient, type NativeHarnessContext } from './dsh.js'\nimport { DelegationService } from './delegations.js'\nimport { registerRootTools, type PentesterService } from './tools.js'\nimport { loadAgentProfiles } from './profiles.js'\nimport { STAGE_DEFINITIONS } from './stages.js'\nimport type { AgentProfile } from './model.js'\nimport { DockerRuntime } from './docker/runtime.js'\nimport { registerContainerExecTool } from './worker-tools.js'\nimport { resolveDockerHost } from './docker/host.js'\nimport { ensureSettings, saveSettings } from './settings-store.js'\nimport { PentesterDockerTypertService, TYPERT_MANIFEST } from './rpc.js'\nimport { GitCheckpointService } from './git.js'\n\nexport const name = 'dsh-pentester'\n\nexport const inject = ['tools', 'subagents']\n\nexport interface Config {\n verbose: boolean\n /**\n * Global docker host (unix:///path or http://host:port). Fallback chain:\n * this config > DOCKER_HOST > /var/run/docker.sock.\n */\n dockerHost?: string\n /** Optional image tag overrides keyed by toolbox name (default: kali). */\n toolboxImages?: Record<string, string>\n}\n\nexport const Config: Schema<Config> = Schema.object({\n verbose: Schema.boolean().default(false),\n dockerHost: Schema.string().default(''),\n toolboxImages: Schema.object({}).default({}),\n})\n\nexport async function apply(ctx: Context, config: Config): Promise<void> {\n const profiles = loadAgentProfiles(agentsRoot())\n const presetDir = await publishPentesterPreset()\n if (presetDir !== undefined) {\n // Root compact state 需要 current stage 的合法 AgentProfile 列表 ——\n // 由 STAGE_DEFINITIONS + AgentProfile registry 生成并随 preset 发布。\n await writeStageProfilesManifest(presetDir, profiles)\n }\n // Docker host 优先级:settings.json(Settings UI 可编辑)> 插件配置 > 本地优先回退链。\n const settings = await ensureSettings()\n const explicit = settings.dockerHost !== '' ? settings.dockerHost : config.dockerHost\n const docker = new DockerRuntime({\n host: resolveDockerHost(explicit === '' ? undefined : explicit),\n ...(config.toolboxImages === undefined || Object.keys(config.toolboxImages).length === 0\n ? {}\n : { imageOverrides: config.toolboxImages }),\n })\n const dsh = new DshClient(ctx as unknown as NativeHarnessContext)\n const delegations = new DelegationService(dsh, docker)\n const git = new GitCheckpointService()\n // Root/Worker 工具注册位置 = pentester preset scope(run-state.mjs 调用本\n // service)。宿主只发布实现,不把工具注册进 global registry —— standard\n // Session 因此完全看不到 pentester_*(docs/plan.md §7)。\n ctx.provide('pentester', {\n registerRootTools: (tools) => registerRootTools(tools, {\n delegations,\n profiles,\n git,\n pushWorkspace: async (projectDir, run) => { await docker.pushWorkspace(run.id, projectDir) },\n syncWorkspace: async (projectDir, run) => { await docker.syncWorkspace(run.id, projectDir) },\n }),\n registerContainerExecTool: (tools) => registerContainerExecTool(tools, docker),\n } satisfies PentesterService)\n // Settings UI 的 Docker Engine Tab:typed RPC(get/set dockerHost,保存后热切换)。\n ;(ctx as { inject: (deps: string[], fn: (inner: unknown) => void) => void }).inject(['typert'], (inner) => {\n new PentesterDockerTypertService(inner, {\n getSettings: () => ensureSettings(),\n getConfigHost: () => config.dockerHost ?? '',\n saveDockerHost: async (dockerHost: string) => {\n const current = await ensureSettings()\n const next = { ...current, dockerHost }\n await saveSettings(next)\n return next\n },\n saveSettings: async (next) => { await saveSettings(next) },\n docker,\n applyHost: (host) => docker.updateHost(host),\n })\n const typert = (inner as { typert: { register: (manifest: unknown) => () => void } }).typert\n typert.register(TYPERT_MANIFEST)\n })\n if (config.verbose) {\n console.log(`[dsh-pentester] loaded with ${profiles.size} agent profiles`)\n }\n}\n\nfunction agentsRoot(): string {\n // Shipped builtin profiles live in <package>/agents next to the built lib.\n const here = dirname(fileURLToPath(import.meta.url))\n for (const candidate of [\n join(here, '..', 'agents'),\n join(process.cwd(), 'agents'),\n ]) {\n if (existsSync(candidate)) return candidate\n }\n return join(process.cwd(), 'agents')\n}\n\n/** run-state.mjs 读取的 stage → AgentProfile 清单文件名(与 preset 同目录发布)。 */\nexport const STAGE_PROFILES_FILE = 'stage-profiles.json'\n\n/**\n * 生成并发布 stage → [{id, name}] 清单(docs/plan.md §7:Root compact state\n * 的 Available AgentProfiles 从 STAGE_DEFINITIONS + AgentProfile registry 生成,\n * 不硬编码第二套映射)。随 preset 目录发布,run-state.mjs 同目录读取。\n */\nexport async function writeStageProfilesManifest(\n presetDir: string,\n profiles: ReadonlyMap<string, AgentProfile>,\n): Promise<void> {\n const manifest = Object.fromEntries(\n STAGE_DEFINITIONS.map(definition => [\n definition.id,\n definition.agentIds\n .map(id => profiles.get(id))\n .filter((profile): profile is AgentProfile => profile !== undefined)\n .map(profile => ({ id: profile.id, name: profile.name })),\n ]),\n )\n await writeFile(join(presetDir, STAGE_PROFILES_FILE), `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n}\n\n// ── preset 发布(原 src/presets.ts)───────────────────────────────────────\n\n/** 把随包发布的 pentester preset 拷贝到 DSH 用户 preset 根目录。 */\nexport async function publishPentesterPreset(home?: string): Promise<string | undefined> {\n const source = shippedPresetDir()\n if (source === undefined) return undefined\n const dest = join(home ?? process.env.DSH_HOME ?? join(homedir(), '.dsh'), '.agent-presets', 'pentester')\n await mkdir(dirname(dest), { recursive: true })\n await cp(source, dest, { recursive: true })\n await readFile(join(dest, 'agent.cordis.yml'), 'utf8')\n return dest\n}\n\nfunction shippedPresetDir(): string | undefined {\n const here = dirname(fileURLToPath(import.meta.url))\n const candidates = [\n join(here, '..', 'presets', 'pentester'),\n join(here, 'presets', 'pentester'),\n join(process.cwd(), 'presets', 'pentester'),\n ]\n return candidates.find((path) => existsSync(join(path, 'agent.cordis.yml')))\n}\n"],"x_google_ignoreList":[15],"mappings":"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"}
|