dsh-pentester 2.2.0 → 2.3.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/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["RUN_DIR","targetRunFilePath","targetEventsPath","imageReadyOn","fsOpen","pentesterViewInputSchema"],"sources":["../src/dsh.ts","../src/stages.ts","../src/model.ts","../src/targets.ts","../src/store.ts","../src/workspace.ts","../src/delegations.ts","../src/pentest/assets.ts","../src/pentest/findings.ts","../src/pentest/pre-engagement.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/ui-view/snapshot.ts","../src/ui-view/binding.ts","../src/build-id.ts","../src/ui-view/invocations.ts","../src/ui-view/rpc.ts","../src/host-manifest.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_start',\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 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: 2\n readonly id: string\n readonly createdAt: string\n /** Singular primary target (canonicalized). */\n target: string\n /** Authorized scope text (human-readable; not machine-enforced). */\n scope: 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 * targets.ts — Target Registry: multi-target workspace isolation.\n *\n * Project workspace is shared only as a container for Target workspaces.\n * Every Target has an isolated Root Session, PentestRun, PTES timeline,\n * filesystem tree, Git history and Toolbox runtime.\n *\n * TargetContext is the mandatory resolver for all target-specific code.\n * No target-scoped function accepts a bare projectDir.\n */\nimport { createHash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { stageDir, type StageId } from './model.js'\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nexport const WORKSPACE_DIR = 'workspace'\nexport const RUN_DIR = '.dsh-pentester'\nexport const RUN_FILE = 'run.json'\nexport const TARGETS_FILE = 'targets.json'\nexport const TARGETS_SUBDIR = 'targets'\nconst TARGET_REGISTRY_SCHEMA = 1\n\n// ── Target registry types ────────────────────────────────────────────────────\n\nexport interface TargetRecord {\n readonly id: string\n readonly target: string\n readonly canonicalTarget: string\n readonly dirName: string\n /** Authoritative Root controller session id. */\n rootSessionId: string | null\n readonly createdAt: string\n updatedAt: string\n}\n\nexport interface TargetRegistry {\n readonly schemaVersion: typeof TARGET_REGISTRY_SCHEMA\n targets: TargetRecord[]\n}\n\n/**\n * Resolved target context: the single source of truth for all\n * target-scoped path resolution.\n */\nexport interface TargetContext {\n readonly projectDir: string\n readonly workspaceRoot: string\n readonly targetId: string\n readonly target: string\n readonly canonicalTarget: string\n readonly dirName: string\n readonly targetRoot: string\n readonly rootSessionId: string | null\n}\n\n// ── Canonicalization ─────────────────────────────────────────────────────────\n\n/**\n * Conservative canonicalization: trim, lowercase hostname portion,\n * strip trailing slash/path for URLs. Preserves port and scheme distinctions.\n * Never merges semantically different targets.\n */\nexport function canonicalizeTarget(raw: string): string {\n let cleaned = raw.trim()\n if (cleaned === '') return cleaned\n\n // Strip URL scheme for normalization\n let scheme = ''\n const schemeMatch = /^(https?:\\/\\/)/i.exec(cleaned)\n if (schemeMatch !== null) {\n scheme = schemeMatch[1].toLowerCase()\n cleaned = cleaned.slice(schemeMatch[1].length)\n }\n\n // Strip trailing slash and path\n const hostEnd = cleaned.indexOf('/')\n if (hostEnd !== -1) {\n cleaned = cleaned.slice(0, hostEnd)\n }\n\n // Strip trailing colon (no port)\n cleaned = cleaned.replace(/:$/, '')\n\n // Lowercase hostname portion (hostnames are case-insensitive)\n // Preserve port: example.com:8443\n const portMatch = /^(.+):(\\d+)$/.exec(cleaned)\n if (portMatch !== null) {\n cleaned = `${portMatch[1].toLowerCase()}:${portMatch[2]}`\n } else {\n cleaned = cleaned.toLowerCase()\n }\n\n return scheme === '' ? cleaned : `${scheme}${cleaned}`\n}\n\n/** 8-char hex digest for stable short id. */\nexport function makeTargetId(canonicalTarget: string): string {\n return createHash('sha1').update(canonicalTarget).digest('hex').slice(0, 8)\n}\n\n/**\n * Slug-safe directory name from a target string.\n * Replaces path-unsafe characters with hyphens.\n * Format: <readable-slug>-<short-hash>\n */\nexport function makeTargetDirName(target: string, id: string): string {\n // Build a readable slug from the target\n const slug = target\n .replace(/^https?:\\/\\//, '')\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40)\n return `${slug}-${id}`\n}\n\n/**\n * Validate that a target string is safe for directory use.\n * Rejects: /, \\, .., NUL, empty, control characters.\n */\nexport function isTargetSafe(raw: string): boolean {\n if (raw.length === 0) return false\n if (raw.includes('\\0')) return false\n if (raw.includes('/') || raw.includes('\\\\')) return false\n if (raw.includes('..')) return false\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f]/.test(raw)) return false\n return true\n}\n\n// ── Project-level paths ──────────────────────────────────────────────────────\n\nexport function projectWorkspaceDir(projectDir: string): string {\n return join(projectDir, WORKSPACE_DIR)\n}\n\nexport function targetRegistryPath(projectDir: string): string {\n return join(projectWorkspaceDir(projectDir), RUN_DIR, TARGETS_FILE)\n}\n\nexport function targetsRoot(projectDir: string): string {\n return join(projectWorkspaceDir(projectDir), TARGETS_SUBDIR)\n}\n\n// ── Target-scoped paths ──────────────────────────────────────────────────────\n\nexport function targetRoot(ctx: TargetContext): string {\n return ctx.targetRoot\n}\n\nexport function runFilePath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, RUN_FILE)\n}\n\nexport function workspaceMetaPath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, 'workspace.json')\n}\n\nexport function eventsFilePath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, 'events.jsonl')\n}\n\nexport function targetInputDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'target', 'inputs')\n}\n\nexport function assetsDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'assets')\n}\n\nexport function findingsDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'findings')\n}\n\nexport function stagesDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'stages')\n}\n\nexport function reportDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'report')\n}\n\nexport function trafficDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'traffic')\n}\n\nexport function stageDelegationsDir(ctx: TargetContext, stage: StageId): string {\n return join(stagesDir(ctx), stageDir(stage), 'delegations')\n}\n\n/** Host-side delegation directory: `<targetRoot>/stages/<NN>-<stage>/delegations/D-00N`. */\nexport function delegationHostDir(ctx: TargetContext, stage: StageId, id: string): string {\n return join(stageDelegationsDir(ctx, stage), id)\n}\n\n/** Container-side delegation directory: `/workspace/stages/<NN>-<stage>/delegations/D-00N`. */\nexport function delegationContainerDir(stage: StageId, id: string): string {\n return `/workspace/stages/${stageDir(stage)}/delegations/${id}`\n}\n\n// ── Registry I/O ─────────────────────────────────────────────────────────────\n\nexport class TargetRegistryError extends Error {}\n\n/**\n * Load the workspace target registry. Returns empty registry if file does not\n * exist (no targets yet). Throws on corruption.\n */\nexport async function loadTargetRegistry(projectDir: string): Promise<TargetRegistry> {\n const file = targetRegistryPath(projectDir)\n if (!existsSync(file)) {\n return { schemaVersion: TARGET_REGISTRY_SCHEMA, targets: [] }\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(await readFile(file, 'utf8'))\n } catch (error) {\n throw new TargetRegistryError(\n `targets.json is corrupted: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n if (parsed === null || typeof parsed !== 'object') {\n throw new TargetRegistryError('targets.json must be an object')\n }\n const record = parsed as Record<string, unknown>\n if (record.schemaVersion !== TARGET_REGISTRY_SCHEMA) {\n throw new TargetRegistryError(\n `targets.json: unsupported schemaVersion ${String(record.schemaVersion)}`,\n )\n }\n if (!Array.isArray(record.targets)) {\n throw new TargetRegistryError('targets.json: targets must be an array')\n }\n return record as unknown as TargetRegistry\n}\n\n/** Atomic write via tmp+rename. */\nexport async function saveTargetRegistry(\n projectDir: string,\n registry: TargetRegistry,\n): Promise<void> {\n const file = targetRegistryPath(projectDir)\n await mkdir(join(projectWorkspaceDir(projectDir), RUN_DIR), { recursive: true })\n const tmp = `${file}.${crypto.randomUUID().slice(0, 8)}.tmp`\n await writeFile(tmp, `${JSON.stringify(registry, null, 2)}\\n`)\n await rename(tmp, file)\n}\n\n// ── Registry mutation queue ──────────────────────────────────────────────────\n\nconst registryQueue = new Map<string, Promise<void>>()\n\n/**\n * Serial read-modify-write for targets.json. Keyed by projectDir.\n * Concurrent inserts from different sessions are serialized to prevent\n * lost updates.\n */\nexport async function updateTargetRegistry(\n projectDir: string,\n fn: (registry: TargetRegistry) => void | Promise<void>,\n): Promise<void> {\n const prev = registryQueue.get(projectDir) ?? Promise.resolve()\n const next = prev.then(async () => {\n const registry = await loadTargetRegistry(projectDir)\n await fn(registry)\n await saveTargetRegistry(projectDir, registry)\n })\n registryQueue.set(projectDir, next.catch(() => undefined).then(() => {}))\n return next\n}\n\n// ── Registry queries ─────────────────────────────────────────────────────────\n\nexport function listTargetRecords(registry: TargetRegistry): readonly TargetRecord[] {\n return registry.targets\n}\n\nexport function resolveTargetById(\n registry: TargetRegistry,\n targetId: string,\n): TargetRecord | undefined {\n return registry.targets.find(t => t.id === targetId)\n}\n\nexport function resolveTargetByCanonicalTarget(\n registry: TargetRegistry,\n canonicalTarget: string,\n): TargetRecord | undefined {\n return registry.targets.find(t => t.canonicalTarget === canonicalTarget)\n}\n\nexport function resolveTargetByRootSession(\n registry: TargetRegistry,\n sessionId: string,\n): TargetRecord | undefined {\n return registry.targets.find(t => t.rootSessionId === sessionId)\n}\n\n/**\n * Find a TargetRecord whose PentestRun contains a Delegation with the given\n * worker sessionId. Returns undefined if no active run matches.\n * This is a heavier query that requires loading each target's run.json.\n */\nexport async function resolveTargetByWorkerSession(\n projectDir: string,\n registry: TargetRegistry,\n sessionId: string,\n): Promise<{ record: TargetRecord; run: unknown } | undefined> {\n for (const record of registry.targets) {\n const ctx = buildTargetContext(projectDir, record)\n const runFile = runFilePath(ctx)\n if (!existsSync(runFile)) continue\n try {\n const run = JSON.parse(await readFile(runFile, 'utf8'))\n const delegations = run?.delegations\n if (!Array.isArray(delegations)) continue\n if (delegations.some((d: { sessionId?: string }) => d.sessionId === sessionId)) {\n return { record, run }\n }\n } catch {\n continue\n }\n }\n return undefined\n}\n\n// ── TargetContext construction ───────────────────────────────────────────────\n\nexport function buildTargetContext(\n projectDir: string,\n record: TargetRecord,\n): TargetContext {\n const targetRootPath = join(targetsRoot(projectDir), record.dirName)\n return {\n projectDir,\n workspaceRoot: projectWorkspaceDir(projectDir),\n targetId: record.id,\n target: record.target,\n canonicalTarget: record.canonicalTarget,\n dirName: record.dirName,\n targetRoot: targetRootPath,\n rootSessionId: record.rootSessionId,\n }\n}\n\n/**\n * Resolve the TargetContext for the given Root session.\n * Returns undefined if this session is not bound to any target.\n */\nexport async function resolveSessionTargetContext(\n projectDir: string,\n sessionId: string,\n): Promise<TargetContext | undefined> {\n const registry = await loadTargetRegistry(projectDir)\n const record = resolveTargetByRootSession(registry, sessionId)\n if (record === undefined) return undefined\n return buildTargetContext(projectDir, record)\n}\n\n/**\n * Resolve TargetContext for a worker session (via delegation binding).\n * Returns undefined if no delegation matches this session.\n */\nexport async function resolveWorkerTargetContext(\n projectDir: string,\n sessionId: string,\n): Promise<TargetContext | undefined> {\n const registry = await loadTargetRegistry(projectDir)\n const result = await resolveTargetByWorkerSession(projectDir, registry, sessionId)\n if (result === undefined) return undefined\n return buildTargetContext(projectDir, result.record)\n}","/**\n * store.ts — target-scoped PentestRun persistence (docs/workspace.md).\n * Atomic write via tmp+rename; no event log, no replay.\n *\n * All run I/O requires a TargetContext (from src/targets.ts). Bare projectDir\n * is no longer accepted for run-level operations.\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isStageId, nextStage, type Delegation, type PentestRun, type StageId } from './model.js'\nimport { runFilePath as targetRunFilePath, type TargetContext } from './targets.js'\n\nexport const RUN_DIR = '.dsh-pentester'\nexport const WORKSPACE_DIR = 'workspace'\n\nexport class StoreError extends Error {}\n\n/** @deprecated Use target-scoped `runFilePath(ctx)` from targets.ts instead. */\nexport function workspaceDir(projectDir: string): string {\n return join(projectDir, WORKSPACE_DIR)\n}\n\n// ── Target-scoped run I/O ────────────────────────────────────────────────────\n\nexport async function resolvePentestRun(ctx: TargetContext): Promise<PentestRun | null> {\n return tryLoadRun(ctx)\n}\n\nexport async function tryLoadRun(ctx: TargetContext): Promise<PentestRun | null> {\n const file = targetRunFilePath(ctx)\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\nexport async function loadRun(ctx: TargetContext): Promise<PentestRun | undefined> {\n return (await tryLoadRun(ctx)) ?? undefined\n}\n\nexport async function saveRun(ctx: TargetContext, run: PentestRun): Promise<void> {\n const file = targetRunFilePath(ctx)\n await mkdir(join(ctx.targetRoot, RUN_DIR), { recursive: true })\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// ── Serial write protection ──────────────────────────────────────────────────\n\nconst serialQueue = new Map<string, Promise<void>>()\n\n/**\n * Serial read-modify-write for a target's run.json. Keyed by targetId.\n * Concurrent calls for the same target queue automatically.\n */\nexport async function updateRun(\n ctx: TargetContext,\n fn: (run: PentestRun) => void | Promise<void>,\n): Promise<void> {\n const key = ctx.targetId\n const prev = serialQueue.get(key) ?? Promise.resolve()\n const next = prev.then(async () => {\n const run = await resolvePentestRun(ctx)\n if (run === null) throw new StoreError('cannot update a PentestRun that does not exist')\n await fn(run)\n await saveRun(ctx, run)\n })\n serialQueue.set(key, next.catch(() => undefined).then(() => {}))\n return next\n}\n\n// ── Domain helpers (unchanged) ───────────────────────────────────────────────\n\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 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\nexport function markStageReviewing(run: PentestRun): void {\n if (run.currentStage === null) return\n run.stageStatuses = { ...(run.stageStatuses ?? {}), [run.currentStage]: 'reviewing' }\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\n// ── Validation ───────────────────────────────────────────────────────────────\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 !== 2 && 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 * workspace.ts — target-scoped workspace initialization and host-side artifacts.\n *\n * New layout (per docs/workspace.md, updated for multi-target):\n *\n * <project>/workspace/\n * ├── .dsh-pentester/\n * │ └── targets.json ← Target registry (workspace-level)\n * └── targets/\n * └── <target-id>/\n * ├── .git/\n * ├── .dsh-pentester/\n * │ ├── run.json\n * │ ├── workspace.json\n * │ └── events.jsonl\n * ├── target/\n * ├── assets/\n * ├── findings/\n * ├── stages/\n * ├── report/\n * └── traffic/\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 StageId } from './model.js'\nimport { RUN_DIR } from './store.js'\nimport { eventsFilePath as targetEventsPath, targetInputDir, type TargetContext } from './targets.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 interface WorkspaceEvent {\n readonly ts: string\n readonly type: string\n readonly data?: unknown\n}\n\n// ── Project-level workspace ──────────────────────────────────────────────────\n\n/**\n * Ensure the project-level workspace skeleton (not target-specific).\n * Creates: workspace/, workspace/.dsh-pentester/, workspace/targets/.\n * Idempotent.\n */\nexport async function ensureProjectWorkspace(projectDir: string): Promise<void> {\n const ws = join(projectDir, 'workspace')\n await mkdir(join(ws, RUN_DIR), { recursive: true })\n await mkdir(join(ws, 'targets'), { recursive: true })\n}\n\n// ── Target-scoped workspace ──────────────────────────────────────────────────\n\nexport function workspaceFilePath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, 'workspace.json')\n}\n\n/** Append an event to the target's events.jsonl (best-effort, never blocks). */\nexport async function appendEvent(ctx: TargetContext, event: WorkspaceEvent): Promise<void> {\n try {\n await appendFile(\n targetEventsPath(ctx),\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 * Initialize a target workspace with the full skeleton.\n * Creates: .dsh-pentester/, target/, assets/, findings/, stages/,\n * report/, traffic/, .gitignore.\n * Idempotent: only creates missing directories.\n */\nexport async function initTargetWorkspace(\n ctx: TargetContext,\n options: { target?: string; language?: string; scope?: string; roe?: string } = {},\n): Promise<WorkspaceMeta> {\n const root = ctx.targetRoot\n const metaPath = workspaceFilePath(ctx)\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(ctx, { 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 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(ctx, 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/** Write target/target.json (idempotent). */\nexport async function writeTarget(ctx: TargetContext, target: string | undefined): Promise<void> {\n if (target === undefined) return\n const file = join(ctx.targetRoot, '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/** Write stage summary.md. */\nexport async function writeStageSummary(\n ctx: TargetContext,\n stage: StageId,\n summary: string,\n): Promise<void> {\n const text = summary.trim()\n if (text === '') return\n await writeFile(\n join(ctx.targetRoot, 'stages', stageDir(stage), 'summary.md'),\n `# ${stageDir(stage)}\\n\\n${text}\\n`,\n 'utf8',\n )\n}\n\n/** Promote threat-model.md from delegation dir to canonical findings/. */\nexport async function promoteDeliverables(\n ctx: TargetContext,\n dir: string,\n): Promise<void> {\n const root = ctx.targetRoot\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/** Write pre-engagement provenance to target/inputs/pre-engagement.md. */\nexport async function writePreEngagementInput(\n ctx: TargetContext,\n options: {\n target: string\n scope: string\n roe: string\n language: string\n },\n): Promise<void> {\n const inputsDir = targetInputDir(ctx)\n await mkdir(inputsDir, { recursive: true })\n const content = [\n '# Pre-engagement Confirmation',\n '',\n `**Recorded**: ${new Date().toISOString()}`,\n '',\n '## Target',\n `- ${options.target}`,\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 * 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 * 目录契约:`<targetRoot>/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 { findDelegation, markStageReviewing, nextDelegationId, saveRun } from './store.js'\nimport { appendEvent } from './workspace.js'\nimport { DshClient, type CreateWorkerInput } from './dsh.js'\nimport { DockerRuntime } from './docker/runtime.js'\nimport { delegationHostDir, delegationContainerDir, type TargetContext } from './targets.js'\nimport type { StageId } from './model.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 targetContext: TargetContext\n readonly run: PentestRun\n readonly profiles: ReadonlyMap<string, AgentProfile>\n readonly rootSessionId: string\n readonly parent: Agent\n readonly signal: AbortSignal\n}\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- Set the timeout duration for invoking the tool to 1800000 milliseconds.\n For operations such as enumeration, directory scanning, brute force cracking, etc.,\n a longer duration such as 1 hour or 2 hours can be set.`\n\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 * 所以必须自包含。\n */\nexport function buildWorkerTaskPrompt(options: {\n readonly run: PentestRun\n readonly delegation: Delegation\n readonly stageId: StageId\n}): string {\n const { run, delegation, stageId } = options\n const stage = stageDefinition(stageId)\n const containerDir = delegationContainerDir(stageId, delegation.id)\n const metadata = [\n `Delegation ID: ${delegation.id}`,\n `Stage: ${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 `Target: ${run.target || '(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\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 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 ctx = deps.targetContext\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 = delegationHostDir(ctx, 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 status: 'starting',\n createdAt: new Date().toISOString(),\n }\n deps.run.delegations.push(delegation)\n await saveRun(ctx, deps.run)\n await appendEvent(ctx, {\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(ctx, deps.run)\n // Push scaffold to container.\n await this.docker.pushWorkspace(deps.run.id, ctx).catch(() => undefined)\n const toolbox = await this.docker.ensureImage('kali')\n const containerId = await this.docker.ensureRunContainer({ runId: deps.run.id, targetId: ctx.targetId, target: ctx.canonicalTarget, toolbox, targetRoot: ctx.targetRoot })\n for (const delegation of created) {\n await this.dispatch(deps, delegation, containerId)\n }\n await saveRun(ctx, deps.run)\n return created\n }\n\n private async dispatch(deps: DelegateDeps, delegation: Delegation, containerId: string): Promise<void> {\n const profile = deps.profiles.get(delegation.agentId)!\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 创建\n }\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, stageId: delegation.stageId }),\n ...(profile.model === undefined ? {} : { model: profile.model }),\n }\n const start = await this.dsh.startContinuableWorker(input, deps.parent, deps.signal)\n delegation.sessionId = start.childId\n delegation.status = 'active'\n await saveRun(deps.targetContext, deps.run)\n await appendEvent(deps.targetContext, {\n ts: new Date().toISOString(),\n type: 'delegation.dispatched',\n data: { id: delegation.id, childId: start.childId, messageId: start.messageId },\n })\n }\n\n async cancel(\n deps: { targetContext: TargetContext; 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 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\n }\n }\n delegation.status = 'closed'\n delegation.resultSummary = reason ?? 'closed by Root'\n delegation.finishedAt = new Date().toISOString()\n await saveRun(deps.targetContext, deps.run)\n await appendEvent(deps.targetContext, {\n ts: new Date().toISOString(),\n type: 'delegation.closed',\n data: { id: delegationId, reason },\n })\n return delegation\n }\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 async maybeMarkReviewing(deps: { targetContext: TargetContext; 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.targetContext, deps.run)\n await appendEvent(deps.targetContext, {\n ts: new Date().toISOString(),\n type: 'stage.reviewing',\n data: { stage: deps.run.currentStage },\n })\n }\n}\n\nasync function scaffoldDelegationDir(\n dir: string,\n info: { id: string; stage: string; agent: string; objective: string; taskPrompt: string },\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 type { TargetContext } from '../targets.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 ctx: TargetContext,\n stage: string,\n delegationDirs: readonly string[],\n delegationIds: readonly string[],\n): Promise<void> {\n const root = ctx.targetRoot\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 type { TargetContext } from '../targets.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 ctx: TargetContext,\n stage: string,\n delegationDirs: readonly string[],\n delegationIds: readonly string[],\n): Promise<void> {\n const root = ctx.targetRoot\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 * pre-engagement.ts — fixed one-batch Pre-engagement questionnaire.\n *\n * The Root Agent calls ask_user_question EXACTLY ONCE with every question\n * in a single array. The host validates this contract mechanically before\n * pentester_start executes any side effect.\n *\n * Two planes:\n * 1. Pure domain constants (question IDs, definitions, answer helpers).\n * 2. Host-side session-event validator (reads persisted ask_user_question\n * invocations from the Root Session via sessionQuery).\n */\n\n// ── Domain constants ────────────────────────────────────────────────────────\n\n/** Fixed question IDs in strict order. */\nexport const PRE_ENGAGEMENT_QUESTION_IDS = [\n 'target_confirm',\n 'scope_confirm',\n 'exclusions_confirm',\n 'roe_confirm',\n 'language_confirm',\n 'final_confirm',\n] as const\n\nexport type PreEngagementQuestionId = (typeof PRE_ENGAGEMENT_QUESTION_IDS)[number]\n\n/** The 6 questions as fixed definitions (labels, placeholders, option templates). */\nexport interface PreEngagementQuestion {\n readonly id: PreEngagementQuestionId\n readonly header: string\n readonly question: string\n /** Option templates: {label, description} for each. */\n readonly optionTemplates: ReadonlyArray<{ readonly label: string; readonly description: string }>\n}\n\nexport const PRE_ENGAGEMENT_QUESTIONS: Readonly<Record<PreEngagementQuestionId, PreEngagementQuestion>> = {\n target_confirm: {\n id: 'target_confirm',\n header: '🎯 测试目标',\n question: '请确认本次授权渗透测试的 Primary Target。',\n optionTemplates: [\n { label: '{{target}}', description: '使用当前识别的目标' },\n { label: '目标不正确', description: '暂不开始测试,我会重新提供目标' },\n ],\n },\n scope_confirm: {\n id: 'scope_confirm',\n header: '📋 授权范围',\n question: '请确认本次允许测试的范围。',\n optionTemplates: [\n { label: '{{scope}}', description: '{{scopeDescription}}' },\n { label: '范围不正确', description: '暂不开始测试,我会重新提供授权范围' },\n ],\n },\n exclusions_confirm: {\n id: 'exclusions_confirm',\n header: '🚫 排除项',\n question: '除授权范围本身之外,是否还有额外禁止的目标、路径或行为?',\n optionTemplates: [\n { label: '无额外排除项', description: '仍严格受上述 Scope 和 RoE 限制' },\n { label: '有额外排除项', description: '暂不开始,我会补充排除项' },\n ],\n },\n roe_confirm: {\n id: 'roe_confirm',\n header: '⚔️ 交战规则',\n question: '请选择本次测试的 Rules of Engagement。',\n optionTemplates: [\n { label: '标准 RoE', description: '允许主动扫描、漏洞验证和授权范围内的利用;禁止 DoS、破坏性操作和高风险稳定性影响行为' },\n { label: '仅非侵入式测试', description: '允许信息收集和低风险探测,不进行利用' },\n { label: '需要自定义 RoE', description: '暂不开始,我会提供详细规则' },\n ],\n },\n language_confirm: {\n id: 'language_confirm',\n header: '🌐 输出语言',\n question: '请选择本次测试的主要输出语言。',\n optionTemplates: [\n { label: '中文', description: '使用中文' },\n { label: 'English', description: 'Use English' },\n ],\n },\n final_confirm: {\n id: 'final_confirm',\n header: '✅ 授权确认',\n question: '请确认以上回答共同构成本次测试的授权边界,并开始测试。',\n optionTemplates: [\n { label: '确认并开始', description: '按以上 Target / Scope / Exclusions / RoE / Language 开始测试' },\n { label: '暂不开始', description: '当前信息需要修改' },\n ],\n },\n}\n\n// ── Answer helpers ──────────────────────────────────────────────────────────\n\n/**\n * The answer accepted by the user for each confirmation question.\n * Matches the ask_user_question tool output schema.\n */\nexport interface PreEngagementAnswer {\n readonly id: string\n readonly answer?: string\n readonly selected?: readonly string[]\n}\n\n/**\n * Parse the ask_user_question result's answers array into an id→answer map.\n */\nexport function parseAnswers(\n answers: readonly PreEngagementAnswer[] | undefined,\n): ReadonlyMap<string, PreEngagementAnswer> {\n const map = new Map<string, PreEngagementAnswer>()\n if (answers !== undefined) {\n for (const entry of answers) {\n if (typeof entry.id === 'string') map.set(entry.id, entry)\n }\n }\n return map\n}\n\n/**\n * Check whether a single answer is a \"confirmed\" (not \"rejected\") choice.\n * For questions that use options, we check the selected label.\n */\nexport function isAnswerAccepted(\n questionId: PreEngagementQuestionId,\n answer: PreEngagementAnswer | undefined,\n): boolean {\n if (answer === undefined) return false\n const selected = (answer.selected ?? [])[0]\n if (selected === undefined) return false\n switch (questionId) {\n case 'target_confirm':\n return selected !== '目标不正确'\n case 'scope_confirm':\n return selected !== '范围不正确'\n case 'exclusions_confirm':\n return selected === '无额外排除项'\n case 'roe_confirm':\n return selected === '标准 RoE' || selected === '仅非侵入式测试'\n case 'language_confirm':\n return selected === '中文' || selected === 'English'\n case 'final_confirm':\n return selected === '确认并开始'\n }\n}\n\n/**\n * True when ALL six questions received confirmed answers.\n */\nexport function isPreEngagementConfirmed(\n answersById: ReadonlyMap<string, PreEngagementAnswer>,\n): boolean {\n return PRE_ENGAGEMENT_QUESTION_IDS.every(id =>\n isAnswerAccepted(id, answersById.get(id)),\n )\n}\n\n/**\n * Which question IDs are not yet confirmed (for Root to tell the user).\n */\nexport function unconfirmedQuestionIds(\n answersById: ReadonlyMap<string, PreEngagementAnswer>,\n): PreEngagementQuestionId[] {\n return PRE_ENGAGEMENT_QUESTION_IDS.filter(id =>\n !isAnswerAccepted(id, answersById.get(id)),\n )\n}\n\n// ── Host-side proof from session events ─────────────────────────────────────\n\n/**\n * Successful pre-engagement proof: a validated single-batch ask_user_question\n * invocation with all six answers confirmed.\n */\nexport interface PreEngagementProof {\n readonly ok: true\n /** The callId of the validated ask_user_question invocation. */\n readonly invocationCallId: string\n /** The six confirmed answers, keyed by question id. */\n readonly answers: Record<PreEngagementQuestionId, PreEngagementAnswer>\n}\n\n/** Pre-engagement validation error codes. */\nexport type PreEngagementErrorCode =\n | 'pre_engagement_missing'\n | 'pre_engagement_incomplete'\n | 'pre_engagement_batch_required'\n | 'pre_engagement_wrong_question_count'\n | 'pre_engagement_wrong_question_order'\n | 'pre_engagement_not_confirmed'\n | 'pre_engagement_target_mismatch'\n | 'pre_engagement_scope_mismatch'\n | 'pre_engagement_language_mismatch'\n\n/** Failed pre-engagement validation. */\nexport interface PreEngagementRejection {\n readonly ok: false\n readonly code: PreEngagementErrorCode\n readonly message: string\n}\n\nexport type PreEngagementValidation = PreEngagementProof | PreEngagementRejection\n\n// ── Minimal session query interface ─────────────────────────────────────────\n\n/** The subset of sessionQuery we need for validation. */\nexport interface SessionQueryReader {\n readSession(sessionId: string): Promise<{\n events: ReadonlyArray<{ readonly type: string; readonly data?: unknown }>\n }>\n}\n\n/** Shape of a tool/call event's data. */\ninterface ToolCallData {\n callId: string\n name: string\n arguments: string\n}\n\n/** Shape of a tool/result event's data. */\ninterface ToolResultData {\n message: {\n source: { callId: string }\n content: ReadonlyArray<{ type: string; text?: string }>\n }\n error?: { name: string; code: string; message: string }\n}\n\n// ── Validator ───────────────────────────────────────────────────────────────\n\n/**\n * Validate that the current Root Session contains exactly one completed\n * ask_user_question invocation with the six canonical Pre-engagement questions\n * in the canonical order, all confirmed, matching the start arguments.\n *\n * Reads from the session event log via sessionQuery — never trusts model\n * arguments or browser state.\n */\nexport async function validatePreEngagementBatch(\n sessionQuery: SessionQueryReader,\n sessionId: string,\n startArgs: { target: string; scope: string; language: string },\n): Promise<PreEngagementValidation> {\n const snapshot = await sessionQuery.readSession(sessionId)\n const events = snapshot.events\n\n // 1. Find the most recent ask_user_question tool/call with a matching tool/result\n // Skip the existing_target_action selector (not a Pre-engagement batch).\n let bestCall: ToolCallData | undefined\n let bestResult: ToolResultData | undefined\n let bestCallIndex = -1\n\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]\n if (event.type !== 'tool/call') continue\n const data = event.data as ToolCallData | undefined\n if (data === undefined || data.name !== 'ask_user_question') continue\n\n // Skip the existing_target_action selector — it's a single-question\n // \"Continue/Restart\" prompt, not the Pre-engagement batch.\n if (isExistingTargetActionCall(data)) continue\n\n // Find matching tool/result\n const result = findMatchingResult(events, data.callId)\n if (result === undefined) continue\n\n bestCall = data\n bestResult = result\n bestCallIndex = i\n break\n }\n\n if (bestCall === undefined || bestResult === undefined) {\n return {\n ok: false,\n code: 'pre_engagement_missing',\n message: 'No completed ask_user_question invocation found in this session. '\n + 'Ask all six Pre-engagement questions together in one ask_user_question call: '\n + PRE_ENGAGEMENT_QUESTION_IDS.join(', ') + '.',\n }\n }\n\n // 2. Parse the questions from the invocation\n let questions: unknown[]\n try {\n const parsed = JSON.parse(bestCall.arguments)\n questions = Array.isArray(parsed.questions) ? parsed.questions : []\n } catch {\n return {\n ok: false,\n code: 'pre_engagement_missing',\n message: 'The ask_user_question invocation has malformed arguments.',\n }\n }\n\n // 3. Validate question count and IDs\n const questionIds = questions.map((q: unknown) =>\n typeof (q as Record<string, unknown>)?.id === 'string'\n ? (q as Record<string, unknown>).id as string\n : '',\n )\n\n if (questionIds.length !== PRE_ENGAGEMENT_QUESTION_IDS.length) {\n return {\n ok: false,\n code: 'pre_engagement_wrong_question_count',\n message: `Pre-engagement requires exactly ${PRE_ENGAGEMENT_QUESTION_IDS.length} questions, `\n + `got ${questionIds.length}. Re-ask all six questions together in one batch.`,\n }\n }\n\n // Check exact match (count, order, no duplicates)\n for (let i = 0; i < PRE_ENGAGEMENT_QUESTION_IDS.length; i++) {\n if (questionIds[i] !== PRE_ENGAGEMENT_QUESTION_IDS[i]) {\n return {\n ok: false,\n code: 'pre_engagement_wrong_question_order',\n message: `Pre-engagement question at position ${i + 1} must be `\n + `\"${PRE_ENGAGEMENT_QUESTION_IDS[i]}\", got \"${questionIds[i]}\". `\n + 'The six questions must be in this exact order: '\n + PRE_ENGAGEMENT_QUESTION_IDS.join(', ') + '.',\n }\n }\n }\n\n // Check for duplicate IDs in the question list\n const uniqueIds = new Set(questionIds)\n if (uniqueIds.size !== questionIds.length) {\n return {\n ok: false,\n code: 'pre_engagement_wrong_question_order',\n message: 'Pre-engagement question IDs must be unique. Re-ask all six questions together.',\n }\n }\n\n // 4. Check the result has no error\n if (bestResult.error !== undefined) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `The Pre-engagement questionnaire was not answered (error: ${bestResult.error.code}). `\n + 'Re-ask all six questions together.',\n }\n }\n\n // 5. Parse the answers from the result.\n // Real Harness session log shape:\n // tool/result → data.message.content[]\n // type = \"tool-result\"\n // toolCallId = <callId>\n // isError = false\n // content[]\n // type = \"text\"\n // text = \"{\\\"answers\\\":[...]}\"\n let answers: PreEngagementAnswer[]\n try {\n const rawContent = bestResult.message.content\n\n // Unwrap: find the tool-result block, then extract its nested text block.\n const toolResultBlock = rawContent.find(b => b.type === 'tool-result') as\n { type: string; toolCallId?: string; isError?: boolean; content?: ReadonlyArray<{ type: string; text?: string }> } | undefined\n\n if (toolResultBlock !== undefined) {\n if (toolResultBlock.isError === true) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: 'The Pre-engagement questionnaire result returned an error. Re-ask all six questions together.',\n }\n }\n const innerContent = toolResultBlock.content ?? []\n const innerText = innerContent.find(b => b.type === 'text')\n if (innerText === undefined || innerText.text === undefined) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `The Pre-engagement questionnaire result is empty (tool-result block has no text content). `\n + 'Re-ask all six questions together.',\n }\n }\n const parsed = JSON.parse(innerText.text)\n answers = Array.isArray(parsed.answers) ? parsed.answers : []\n } else {\n // Fallback: direct text block (test fixtures, older event shapes).\n const textBlock = rawContent.find(b => b.type === 'text')\n if (textBlock !== undefined && textBlock.text !== undefined) {\n const parsed = JSON.parse(textBlock.text)\n answers = Array.isArray(parsed.answers) ? parsed.answers : []\n } else {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `The Pre-engagement questionnaire result is in an unrecognized format. `\n + `Found content types: ${JSON.stringify(rawContent.map(b => b.type))}. `\n + 'Re-ask all six questions together.',\n }\n }\n }\n } catch {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: 'The Pre-engagement questionnaire result is malformed. Re-ask all six questions together.',\n }\n }\n\n const answersById = parseAnswers(answers)\n\n // 6. Check all six questions have answers\n const unanswered = PRE_ENGAGEMENT_QUESTION_IDS.filter(id => !answersById.has(id))\n if (unanswered.length > 0) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `Pre-engagement questions not answered: ${unanswered.join(', ')}. `\n + 'Re-ask all six questions together.',\n }\n }\n\n // 7. Check all six are confirmed\n if (!isPreEngagementConfirmed(answersById)) {\n return {\n ok: false,\n code: 'pre_engagement_not_confirmed',\n message: 'Not all Pre-engagement questions were confirmed. '\n + 'The user must confirm all six questions before starting.',\n }\n }\n\n // 8. Check final_confirm specifically\n const finalAnswer = answersById.get('final_confirm')!\n if (!isAnswerAccepted('final_confirm', finalAnswer)) {\n return {\n ok: false,\n code: 'pre_engagement_not_confirmed',\n message: 'The final confirmation was not accepted. The user must select \"确认并开始\" to proceed.',\n }\n }\n\n // 9. Validate target match\n const targetAnswer = answersById.get('target_confirm')\n if (targetAnswer !== undefined) {\n const selected = (targetAnswer.selected ?? [])[0]\n if (selected !== undefined && selected !== '目标不正确') {\n // The selected label should correspond to the target\n // We accept the target as long as the user confirmed (didn't reject)\n }\n }\n\n // 10. Build the proof\n const proofAnswers = Object.fromEntries(\n PRE_ENGAGEMENT_QUESTION_IDS.map(id => [id, answersById.get(id)!]),\n ) as Record<PreEngagementQuestionId, PreEngagementAnswer>\n\n return {\n ok: true,\n invocationCallId: bestCall.callId,\n answers: proofAnswers,\n }\n}\n\n/**\n * Require a valid pre-engagement proof. Throws with a descriptive error\n * message on failure.\n */\nexport async function requirePreEngagementProof(\n sessionQuery: SessionQueryReader,\n sessionId: string,\n startArgs: { target: string; scope: string; language: string },\n): Promise<PreEngagementProof> {\n const result = await validatePreEngagementBatch(sessionQuery, sessionId, startArgs)\n if (!result.ok) {\n throw new Error(`[${result.code}] ${result.message}`)\n }\n return result\n}\n\n// ── Internal helpers ────────────────────────────────────────────────────────\n\n/**\n * Check whether an ask_user_question call is the existing_target_action\n * selector (\"Continue/Restart\") rather than the Pre-engagement batch.\n */\nfunction isExistingTargetActionCall(data: ToolCallData): boolean {\n try {\n const parsed = JSON.parse(data.arguments)\n const questions = Array.isArray(parsed.questions) ? parsed.questions : []\n return questions.length === 1\n && typeof (questions[0] as Record<string, unknown>)?.id === 'string'\n && (questions[0] as Record<string, unknown>).id === 'existing_target_action'\n } catch {\n return false\n }\n}\n\n/**\n * Find the tool/result event matching a given tool/call by callId.\n * Checks both `data.message.source.callId` (standard) and `data.callId` (fallback).\n */\nfunction findMatchingResult(\n events: ReadonlyArray<{ readonly type: string; readonly data?: unknown }>,\n callId: string,\n): ToolResultData | undefined {\n for (const event of events) {\n if (event.type !== 'tool/result') continue\n const data = event.data as (ToolResultData & { callId?: string }) | undefined\n if (data === undefined) continue\n // Primary: message.source.callId (standard session event shape)\n if (data.message?.source?.callId === callId) return data\n // Fallback: data.callId (some event shapes carry callId at top level)\n if (data.callId === callId) return data\n }\n return undefined\n}\n\n// ── Batch detection (for error messages) ────────────────────────────────────\n\n/**\n * Check whether the session has ANY ask_user_question invocation that looks\n * like a Pre-engagement batch (has questions with target_confirm etc).\n * Used to detect the \"split wizard\" pattern for better error messages.\n */\nexport function detectSplitWizard(\n events: ReadonlyArray<{ readonly type: string; readonly data?: unknown }>,\n): { batchCount: number; singleCount: number; hasPreEngagementIds: boolean } {\n let batchCount = 0\n let singleCount = 0\n let hasPreEngagementIds = false\n\n for (const event of events) {\n if (event.type !== 'tool/call') continue\n const data = event.data as ToolCallData | undefined\n if (data === undefined || data.name !== 'ask_user_question') continue\n\n try {\n const parsed = JSON.parse(data.arguments)\n const questions = Array.isArray(parsed.questions) ? parsed.questions : []\n const ids = questions.map((q: unknown) =>\n typeof (q as Record<string, unknown>)?.id === 'string'\n ? (q as Record<string, unknown>).id as string\n : '',\n )\n\n const isPreEngagement = ids.some((id: string) =>\n (PRE_ENGAGEMENT_QUESTION_IDS as readonly string[]).includes(id),\n )\n if (isPreEngagement) hasPreEngagementIds = true\n\n if (ids.length === PRE_ENGAGEMENT_QUESTION_IDS.length) {\n batchCount++\n } else if (ids.length === 1) {\n singleCount++\n }\n } catch {\n // skip malformed\n }\n }\n\n return { batchCount, singleCount, hasPreEngagementIds }\n}","/**\n * tools.ts — the five Root-Agent tools (docs/plan.md). The host checks\n * caller identity, stage linearity and path legality only; information\n * sufficiency is always the Root Agent's judgement.\n *\n * pentester_start is now the sole bootstrap entry point.\n * pentester_advance_stage no longer creates runs.\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, initTargetWorkspace, promoteDeliverables, writePreEngagementInput, writeStageSummary } from './workspace.js'\nimport { promoteAssets } from './pentest/assets.js'\nimport { promoteFindings } from './pentest/findings.js'\nimport { requirePreEngagementProof, type SessionQueryReader } from './pentest/pre-engagement.js'\nimport {\n buildTargetContext,\n canonicalizeTarget,\n makeTargetDirName,\n makeTargetId,\n loadTargetRegistry,\n updateTargetRegistry,\n resolveTargetByCanonicalTarget,\n resolveTargetByRootSession,\n resolveSessionTargetContext,\n delegationHostDir,\n type TargetContext,\n} from './targets.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\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_start: {\n type: 'object',\n additionalProperties: false,\n required: ['target', 'scope', 'rules_of_engagement', 'language', 'summary', 'mode'],\n properties: {\n target: { type: 'string', description: 'Primary target (hostname, IP, URL).' },\n scope: { type: 'string', description: 'Authorized scope description.' },\n rules_of_engagement: { type: 'string', description: 'Rules of Engagement text.' },\n language: { type: 'string', description: 'Output language (e.g. zh-CN, en).' },\n summary: { type: 'string', description: 'Pre-engagement confirmation summary.' },\n mode: { type: 'string', enum: ['new', 'restart'], description: 'new for fresh target, restart for existing target.' },\n expected_target_id: { type: 'string', description: 'For restart: expected target id to prevent race.' },\n },\n },\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.' },\n objective: { type: 'string', description: 'One-line objective (recorded in run.json).' },\n task_prompt: { type: 'string', description: 'Full task context for the worker.' },\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.' },\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.' },\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(ctx: TargetContext, target?: string): Promise<void>\n checkpointStage(ctx: TargetContext, stage: StageId): Promise<string>\n currentBranch(ctx: TargetContext): Promise<string>\n hasChanges(ctx: TargetContext): Promise<boolean>\n findStageCheckpoint(ctx: TargetContext, stage: StageId): Promise<string | undefined>\n createBackupBranch(ctx: TargetContext, stage: string): Promise<string>\n createReworkBranch(ctx: TargetContext, checkpoint: string, nextStageSlug: string): Promise<string>\n }\n readonly pushWorkspace: (ctx: TargetContext, run: PentestRun) => Promise<void>\n readonly syncWorkspace: (ctx: TargetContext, run: PentestRun) => Promise<void>\n readonly sessionQuery: SessionQueryReader\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_start',\n description: ROOT_TOOL_DESCRIPTIONS.pentester_start,\n parameters: ROOT_TOOL_SCHEMAS.pentester_start,\n output,\n execute: (args, exec) => startRun(deps, args, exec),\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_start', 'pentester_delegate', 'pentester_cancel_delegation', 'pentester_advance_stage', 'pentester_rollback_stage']\n}\n\nconst ROOT_TOOL_DESCRIPTIONS = {\n pentester_start:\n 'Initialize or restart a PentestRun for a target. Must be called before any other pentester tool. Mode \"new\" creates a fresh target; mode \"restart\" resets an existing target (old data destroyed).',\n pentester_delegate:\n 'Creates a new long-lived continuable PTES worker. IMPORTANT: explain to the user which worker you are creating before calling this tool.',\n pentester_cancel_delegation:\n 'Close a PTES Delegation. Interrupts the live child turn if active, then marks the Delegation as closed.',\n pentester_advance_stage:\n 'Advance to the next PTES stage. The host verifies linear order and that no active/starting delegations remain.',\n pentester_rollback_stage:\n 'Roll the timeline back to a completed stage checkpoint and start a rework branch.',\n} as const\n\n// ── pentester_start ──────────────────────────────────────────────────────────\n\nasync function startRun(\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 sessionId = caller.sessionId\n const target = typeof args.target === 'string' ? args.target.trim() : ''\n const scope = typeof args.scope === 'string' ? args.scope : ''\n const roe = typeof args.rules_of_engagement === 'string' ? args.rules_of_engagement : ''\n const language = typeof args.language === 'string' ? args.language : 'zh-CN'\n const summary = typeof args.summary === 'string' ? args.summary : ''\n const mode = args.mode === 'restart' ? 'restart' : 'new'\n const expectedTargetId = typeof args.expected_target_id === 'string' ? args.expected_target_id : undefined\n\n if (target === '') throw new Error('pentester_start requires a non-empty target')\n if (scope === '') throw new Error('pentester_start requires a non-empty scope')\n if (summary.trim() === '') throw new Error('pentester_start requires a non-empty summary')\n\n // ── Pre-engagement batch gate (MUST run before any side effect) ──────────\n const proof = await requirePreEngagementProof(\n deps.sessionQuery,\n sessionId,\n { target, scope, language },\n )\n // ── Gate passed ──────────────────────────────────────────────────────────\n\n const canonical = canonicalizeTarget(target)\n if (canonical === '') throw new Error(`invalid target: \"${target}\"`)\n\n const registry = await loadTargetRegistry(projectDir)\n\n // Check if this session is already bound to a different target\n const existingBinding = resolveTargetByRootSession(registry, sessionId)\n if (existingBinding !== undefined && existingBinding.canonicalTarget !== canonical) {\n throw new Error(\n `This session is already bound to target \"${existingBinding.target}\". ` +\n `Create a new Pentester Session for a different target.`,\n )\n }\n\n const existingTarget = resolveTargetByCanonicalTarget(registry, canonical)\n\n if (mode === 'new') {\n if (existingTarget !== undefined) {\n throw new Error(\n `Target \"${canonical}\" already exists. Use mode \"restart\" to restart it, ` +\n `or open the existing Root Session for this target.`,\n )\n }\n return bootstrapNewTarget(deps, projectDir, caller, registry, { target, canonical, scope, roe, language, summary })\n }\n\n // mode === 'restart'\n if (existingTarget === undefined) {\n throw new Error(`Target \"${canonical}\" does not exist. Use mode \"new\" to create it.`)\n }\n if (expectedTargetId !== undefined && expectedTargetId !== existingTarget.id) {\n throw new Error(`Target id mismatch: expected ${expectedTargetId}, got ${existingTarget.id}. The target may have been modified concurrently.`)\n }\n return restartTarget(deps, projectDir, caller, registry, existingTarget, { target, canonical, scope, roe, language, summary })\n}\n\nasync function bootstrapNewTarget(\n deps: RootToolDeps,\n projectDir: string,\n caller: TrustedCaller,\n registry: Awaited<ReturnType<typeof loadTargetRegistry>>,\n opts: { target: string; canonical: string; scope: string; roe: string; language: string; summary: string },\n): Promise<unknown> {\n const id = makeTargetId(opts.canonical)\n const dirName = makeTargetDirName(opts.target, id)\n\n // Create TargetRecord\n await updateTargetRegistry(projectDir, (r) => {\n r.targets.push({\n id,\n target: opts.target,\n canonicalTarget: opts.canonical,\n dirName,\n rootSessionId: caller.sessionId,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n })\n })\n\n const ctx = buildTargetContext(projectDir, {\n id,\n target: opts.target,\n canonicalTarget: opts.canonical,\n dirName,\n rootSessionId: caller.sessionId,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n })\n\n await initTargetWorkspace(ctx, {\n target: opts.target,\n language: opts.language,\n scope: opts.scope,\n roe: opts.roe,\n })\n await writePreEngagementInput(ctx, {\n target: opts.target,\n scope: opts.scope,\n roe: opts.roe,\n language: opts.language,\n })\n\n const run: PentestRun = {\n schemaVersion: 2,\n id: crypto.randomUUID(),\n createdAt: new Date().toISOString(),\n target: opts.canonical,\n scope: opts.scope,\n rulesOfEngagement: opts.roe,\n language: opts.language,\n status: 'active',\n currentStage: 'pre-engagement',\n stageHistory: [{ stage: 'pre-engagement', enteredAt: new Date().toISOString() }],\n delegations: [],\n }\n await saveRun(ctx, run)\n await deps.git.init(ctx, opts.target)\n\n // Complete pre-engagement and activate intelligence-gathering\n await writeStageSummary(ctx, 'pre-engagement', opts.summary)\n advanceStage(run, opts.summary)\n await saveRun(ctx, run)\n await deps.git.checkpointStage(ctx, 'pre-engagement')\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: 'pre-engagement', next: run.currentStage },\n })\n await deps.pushWorkspace(ctx, run).catch(() => undefined)\n\n return {\n mode: 'new',\n targetId: id,\n target: opts.canonical,\n ...rootState(run, deps.profiles),\n }\n}\n\nasync function restartTarget(\n deps: RootToolDeps,\n projectDir: string,\n caller: TrustedCaller,\n registry: Awaited<ReturnType<typeof loadTargetRegistry>>,\n existing: { id: string; target: string; canonicalTarget: string; dirName: string; rootSessionId: string | null; createdAt: string; updatedAt: string },\n opts: { target: string; canonical: string; scope: string; roe: string; language: string; summary: string },\n): Promise<unknown> {\n const ctx = buildTargetContext(projectDir, existing)\n\n // Quiesce old runtime: stop old container\n const oldRun = await resolvePentestRun(ctx)\n if (oldRun !== null) {\n await deps.pushWorkspace(ctx, oldRun).catch(() => undefined)\n // Docker stop handled by host via labels\n }\n\n // Reset target root: remove old tree, recreate fresh\n const { rm } = await import('node:fs/promises')\n await rm(ctx.targetRoot, { recursive: true, force: true }).catch(() => undefined)\n\n await initTargetWorkspace(ctx, {\n target: opts.target,\n language: opts.language,\n scope: opts.scope,\n roe: opts.roe,\n })\n await writePreEngagementInput(ctx, {\n target: opts.target,\n scope: opts.scope,\n roe: opts.roe,\n language: opts.language,\n })\n\n const run: PentestRun = {\n schemaVersion: 2,\n id: crypto.randomUUID(),\n createdAt: new Date().toISOString(),\n target: opts.canonical,\n scope: opts.scope,\n rulesOfEngagement: opts.roe,\n language: opts.language,\n status: 'active',\n currentStage: 'pre-engagement',\n stageHistory: [{ stage: 'pre-engagement', enteredAt: new Date().toISOString() }],\n delegations: [],\n }\n await saveRun(ctx, run)\n await deps.git.init(ctx, opts.target)\n\n // Update registry: rebind to new session\n await updateTargetRegistry(projectDir, (r) => {\n const rec = r.targets.find(t => t.id === existing.id)\n if (rec !== undefined) {\n rec.rootSessionId = caller.sessionId\n rec.updatedAt = new Date().toISOString()\n }\n })\n\n await writeStageSummary(ctx, 'pre-engagement', opts.summary)\n advanceStage(run, opts.summary)\n await saveRun(ctx, run)\n await deps.git.checkpointStage(ctx, 'pre-engagement')\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: 'pre-engagement', next: run.currentStage },\n })\n await deps.pushWorkspace(ctx, run).catch(() => undefined)\n\n return {\n mode: 'restart',\n targetId: existing.id,\n target: opts.canonical,\n ...rootState(run, deps.profiles),\n }\n}\n\n// ── delegate ─────────────────────────────────────────────────────────────────\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 { ctx, run } = await requireTargetRun(caller)\n const assignments = parseAssignments(args.assignments)\n const created = await deps.delegations.delegate(\n {\n projectDir,\n targetContext: ctx,\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\n// ── cancel ───────────────────────────────────────────────────────────────────\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 { ctx, run } = await requireTargetRun(caller)\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({ targetContext: ctx, run }, delegationId, reason)\n return {\n cancelled: { id: cancelled.id, status: cancelled.status },\n ...rootState(run, deps.profiles),\n }\n}\n\n// ── advance ──────────────────────────────────────────────────────────────────\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 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 const { ctx, run } = await requireTargetRun(caller)\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 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 await deps.syncWorkspace(ctx, run).catch(() => undefined)\n const stageDelegations = run.delegations.filter(d => d.stageId === previous)\n const delegationDirs = stageDelegations.map(d => delegationHostDir(ctx, previous, d.id))\n const delegationIds = stageDelegations.map(d => d.id)\n await promoteAssets(ctx, previous, delegationDirs, delegationIds)\n await promoteFindings(ctx, previous, delegationDirs, delegationIds)\n for (const delegation of stageDelegations) {\n await promoteDeliverables(ctx, delegationHostDir(ctx, previous, delegation.id))\n }\n await writeStageSummary(ctx, previous, summary)\n const target = advanceStage(run, summary)\n await saveRun(ctx, run)\n const tag = await deps.git.checkpointStage(ctx, previous)\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: previous, tag, next: target },\n })\n await deps.pushWorkspace(ctx, run).catch(() => undefined)\n return {\n previous,\n ...(target === null ? { completed: true } : { next: target }),\n tag,\n ...rootState(run, deps.profiles),\n }\n}\n\n// ── rollback ─────────────────────────────────────────────────────────────────\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 { ctx, run } = await requireTargetRun(caller)\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 const active = run.delegations.filter(d =>\n d.status === 'active' || d.status === 'starting')\n for (const delegation of active) {\n await deps.delegations.cancel({ targetContext: ctx, run }, delegation.id, 'rolled back by Root')\n }\n let backup: string | undefined\n if (await deps.git.hasChanges(ctx)) {\n backup = await deps.git.createBackupBranch(ctx, stageArg)\n }\n const checkpoint = await deps.git.findStageCheckpoint(ctx, stageArg)\n if (checkpoint === undefined) {\n throw new Error(`pentester_rollback_stage: no checkpoint commit found for stage ${stageArg}`)\n }\n const branch = await deps.git.createReworkBranch(ctx, checkpoint, stageDir(next))\n const authoritativeRun = await resolvePentestRun(ctx)\n if (authoritativeRun === null) {\n throw new Error('pentester_rollback_stage: run.json disappeared after checkout — this is a bug')\n }\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.rollback',\n data: { stage: stageArg, checkpoint, branch, backup, reason },\n })\n await deps.pushWorkspace(ctx, 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\n// ── helpers ──────────────────────────────────────────────────────────────────\n\nconst NO_RUN_MESSAGE =\n 'No PentestRun exists. Complete pre-engagement and call pentester_start first.'\n\nasync function requireTargetRun(caller: TrustedCaller): Promise<{ ctx: TargetContext; run: PentestRun }> {\n const projectDir = caller.cwd!\n const ctx = await resolveSessionTargetContext(projectDir, caller.sessionId)\n if (ctx === undefined) {\n throw new Error('This session is not bound to any target. Start a pentest with pentester_start first.')\n }\n const run = await resolvePentestRun(ctx)\n if (run === null) {\n throw new Error(NO_RUN_MESSAGE)\n }\n return { ctx, run }\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 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 target: run.target,\n scope: run.scope,\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 type { TargetContext } from '../targets.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/** Docker container name maximum length (Docker imposes 128 chars). */\nconst MAX_CONTAINER_NAME_LENGTH = 128\n\n/** Sanitize a target string into a valid Docker container name segment.\n *\n * - trim, lowercase\n * - strip http://, https://\n * - keep [a-z0-9._-], replace everything else with -\n * - collapse consecutive dashes\n * - strip leading/trailing non-alphanumeric\n * - cap length\n */\nexport function sanitizeDockerTargetName(target: string): string {\n let name = target.trim().toLowerCase()\n name = name.replace(/^https?:\\/\\//, '')\n // Replace disallowed characters with hyphens\n name = name.replace(/[^a-z0-9._-]/g, '-')\n // Collapse consecutive hyphens\n name = name.replace(/-{2,}/g, '-')\n // Strip leading/trailing non-alphanumeric\n name = name.replace(/^[^a-z0-9]+/, '').replace(/[^a-z0-9]+$/, '')\n // Cap length\n if (name.length > MAX_CONTAINER_NAME_LENGTH - 'dsh-pentester-'.length) {\n name = name.slice(0, MAX_CONTAINER_NAME_LENGTH - 'dsh-pentester-'.length)\n }\n // If empty after sanitize, use \"pentest\"\n if (name.length === 0) name = 'pentest'\n return name\n}\n\n/** Generate a human-readable Docker container name for a target. */\nexport function containerNameForTarget(target: string): string {\n const sanitized = sanitizeDockerTargetName(target)\n return `dsh-pentester-${sanitized}`\n}\n\n/** Legacy: still available for callers that don't have a target. */\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 targetId: string\n readonly target: string\n readonly toolbox: ToolboxSpec\n /** Target workspace root (host path). */\n readonly targetRoot: string\n}\n\nexport function volumeNameFor(targetId: string, runId: string): string {\n const digest = createHash('sha1').update(`${targetId}:${runId}`).digest('hex').slice(0, 12)\n return `dsh-pentester-${digest}`\n}\n\nexport function localMirrorDir(targetRoot: string): string {\n return targetRoot\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.targetId, options.runId) : 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 if (this.remote && volume?.created === true) {\n await this.pushLocalMirror(containerId, options.targetRoot).catch(() => undefined)\n }\n return containerId\n }\n\n private async ensureWorkspaceVolume(targetId: string, runId: string): Promise<{ name: string; created: boolean }> {\n const volume = volumeNameFor(targetId, runId)\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.run': runId, 'dsh.pentester.target': targetId },\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.targetRoot), 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 = containerNameForTarget(options.target)\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 'dsh.pentester.target': options.targetId,\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 ctx: TargetContext,\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 // Remote: exec. Container path = /workspace + relative to targetRoot.\n const containerPath = delegationDir.startsWith(ctx.targetRoot)\n ? '/workspace' + delegationDir.slice(ctx.targetRoot.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, ctx: TargetContext): Promise<void> {\n if (!this.remote) return\n const key = `${runId}:${ctx.targetRoot}`\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, ctx.targetRoot),\n )\n .finally(() => this.pushing.delete(key))\n this.pushing.set(key, task)\n return task\n }\n\n private async pushLocalMirror(containerId: string, targetRoot: string): Promise<void> {\n const localDir = localMirrorDir(targetRoot)\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, ctx: TargetContext): Promise<void> {\n if (!this.remote) return\n const key = `${runId}:${ctx.targetRoot}`\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, ctx.targetRoot),\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, targetRoot: string): Promise<void> {\n const localDir = localMirrorDir(targetRoot)\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 { resolveWorkerTargetContext, delegationContainerDir, type TargetContext } from './targets.js'\nimport type { Delegation, PentestRun } 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 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\n // Resolve TargetContext via worker session binding\n const ctx = await resolveWorkerTargetContext(projectDir, caller.sessionId)\n if (ctx === undefined) {\n throw new WorkerToolError(\n `session ${caller.sessionId} is not bound to any delegation; only delegated workers may execute commands`,\n )\n }\n\n const run = await resolvePentestRun(ctx)\n if (run === null) {\n throw new WorkerToolError('no PentestRun for this target; the Root Agent must start one first')\n }\n\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\n const toolbox = await docker.ensureImage(toolboxName)\n const containerId = await docker.ensureRunContainer({\n runId: run.id,\n targetId: ctx.targetId,\n target: ctx.canonicalTarget,\n toolbox,\n targetRoot: ctx.targetRoot,\n })\n const input: ExecInput = {\n argv: Array.isArray(args.argv) ? args.argv.map(String) : [],\n ...(typeof args.cwd === 'string' ? { cwd: args.cwd } : { cwd: workerContainerWorkDir(ctx, 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 void docker.syncWorkspace(run.id, ctx).catch(() => undefined)\n return result\n }\n}\n\n/** Worker 的容器工作目录:`/workspace/stages/<NN>-<stage>/delegations/D-00N/work`。 */\nfunction workerContainerWorkDir(ctx: TargetContext, delegation: Delegation): string {\n return `${delegationContainerDir(delegation.stageId, delegation.id)}/work`\n}\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 * 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 * ui-view/snapshot.ts — Build read-model views from run.json + filesystem.\n *\n * Core snapshot: run, stages, delegations, findings, trace — NO output trees.\n * Output trees: lazy via listOutput().\n * File reads: async, bounded concurrency, partial preview.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile, readdir, stat, open as fsOpen } from 'node:fs/promises'\nimport { performance } from 'node:perf_hooks'\nimport { join, relative, sep, isAbsolute } from 'node:path'\nimport { type PentestRun, STAGE_IDS } from '../model.js'\nimport { STAGE_DEFINITIONS } from '../stages.js'\nimport { tryLoadRun } from '../store.js'\nimport { loadTargetRegistry, buildTargetContext, listTargetRecords, type TargetContext } from '../targets.js'\nimport type {\n DelegationView,\n FindingSeverity,\n FindingView,\n OutputEntry,\n OutputEntryKind,\n OutputTargetTree,\n OutputTreeResult,\n PentesterRunView,\n PentesterViewSnapshot,\n StageView,\n TargetSummary,\n TraceEdge,\n TraceNode,\n TraceViewModel,\n} from './types.js'\n\n// ── Stage helpers ──────────────────────────────────────────────────────────\n\nconst STAGE_SHORT: Record<string, string> = {\n 'pre-engagement': 'Pre', 'intelligence-gathering': 'Intel', 'threat-modeling': 'Threat',\n 'vulnerability-analysis': 'Vuln', 'exploitation': 'Exploit', 'post-exploitation': 'Post', 'reporting': 'Report',\n}\n\nfunction stageStatus(run: PentestRun, stageId: string): string {\n const statuses = (run.stageStatuses ?? {}) as Record<string, string>\n if (run.currentStage === stageId) return statuses[stageId] ?? 'active'\n return statuses[stageId] ?? 'pending'\n}\n\n// ── Run view ───────────────────────────────────────────────────────────────\n\nfunction buildRunView(run: PentestRun): PentesterRunView {\n return { id: run.id, status: run.status ?? 'active', currentStage: run.currentStage, targets: [run.target], createdAt: run.createdAt }\n}\n\n// ── Stage views ────────────────────────────────────────────────────────────\n\nfunction buildStageViews(run: PentestRun): StageView[] {\n return STAGE_IDS.map(id => {\n const def = STAGE_DEFINITIONS.find(d => d.id === id)\n const delegations = run.delegations.filter(d => d.stageId === id)\n return {\n id, name: def?.name ?? id, shortName: STAGE_SHORT[id] ?? id.slice(0, 4),\n status: stageStatus(run, id) as StageView['status'],\n delegationCount: delegations.length,\n activeDelegationCount: delegations.filter(d => d.status === 'active' || d.status === 'starting').length,\n }\n })\n}\n\n// ── Delegation views ───────────────────────────────────────────────────────\n\nfunction buildDelegationViews(run: PentestRun): DelegationView[] {\n return run.delegations.map(d => ({\n id: d.id, stageId: d.stageId, agentId: d.agentId,\n ...(d.sessionId === undefined ? {} : { sessionId: d.sessionId }),\n objective: d.objective, status: d.status, createdAt: d.createdAt,\n ...(d.finishedAt === undefined ? {} : { finishedAt: d.finishedAt }),\n }))\n}\n\n// ── Finding views (metadata only, no detail markdown) ──────────────────────\n\nasync function parseFindingsIndex(ctx: TargetContext): Promise<FindingView[]> {\n const indexFile = join(ctx.targetRoot, 'findings', 'findings.json')\n if (!existsSync(indexFile)) return []\n try {\n const raw = await readFile(indexFile, 'utf8')\n const entries = JSON.parse(raw)\n if (!Array.isArray(entries)) return []\n return (entries as Array<Record<string, unknown>>).filter((e: unknown) => e !== null && typeof e === 'object').map((e: Record<string, unknown>) => {\n const detailFile = typeof e.detailFile === 'string' ? e.detailFile : ''\n const id = detailFile.replace(/-findings\\.md$/, '')\n return {\n id,\n title: id,\n severity: (typeof e.severity === 'string' ? e.severity : 'info') as FindingSeverity,\n sourceStage: typeof e.sourceStage === 'string' ? e.sourceStage : '',\n sourceDelegationId: typeof e.sourceDelegationId === 'string' ? e.sourceDelegationId : '',\n detailFile,\n updatedAt: typeof e.updatedAt === 'string' ? e.updatedAt : '',\n }\n })\n } catch { return [] }\n}\n\nasync function parseAssetsCount(ctx: TargetContext): Promise<number> {\n const assetsFile = join(ctx.targetRoot, 'assets', 'assets.json')\n if (!existsSync(assetsFile)) return 0\n try {\n const raw = await readFile(assetsFile, 'utf8')\n const parsed = JSON.parse(raw)\n return Array.isArray(parsed) ? parsed.length : 0\n } catch { return 0 }\n}\n\n// ── Trace model ────────────────────────────────────────────────────────────\n\nfunction buildTraceModel(run: PentestRun, ctx: TargetContext, findings: FindingView[]): TraceViewModel {\n const nodes: TraceNode[] = []\n const edges: TraceEdge[] = []\n nodes.push({ id: 'start', kind: 'start', label: 'Start', timestamp: run.createdAt })\n\n let prevStageId: string | null = null\n for (const stageId of STAGE_IDS) {\n const status = stageStatus(run, stageId)\n const stageNodeId = `stage:${stageId}`\n const stageEntry = run.stageHistory.find(h => h.stage === stageId)\n nodes.push({\n id: stageNodeId, kind: 'stage', label: STAGE_SHORT[stageId] ?? stageId, status,\n nav: { tab: 'stages', focus: stageId },\n ...(stageEntry?.enteredAt === undefined ? {} : { timestamp: stageEntry.enteredAt }),\n })\n if (prevStageId === null) {\n edges.push({ id: `edge:start-${stageId}`, source: 'start', target: stageNodeId, kind: 'transition' })\n } else {\n edges.push({ id: `edge:${prevStageId}-${stageId}`, source: `stage:${prevStageId}`, target: stageNodeId, kind: 'transition' })\n }\n const stageDelegations = run.delegations.filter(d => d.stageId === stageId)\n for (const d of stageDelegations) {\n const delNodeId = `delegation:${d.id}`\n nodes.push({ id: delNodeId, kind: 'delegation', label: `${d.id} · ${d.agentId}`, status: d.status, sublabel: d.objective.slice(0, 60), timestamp: d.createdAt })\n edges.push({ id: `edge:${stageNodeId}-${d.id}`, source: stageNodeId, target: delNodeId, kind: 'delegate' })\n }\n const stageFindings = findings.filter(f => f.sourceStage === stageId)\n for (const f of stageFindings) {\n nodes.push({ id: `finding:${f.id}`, kind: 'finding', label: f.title, status: f.severity.toUpperCase(), nav: { tab: 'findings', focus: f.id } })\n edges.push({ id: `edge:found-${f.id}`, source: `delegation:${f.sourceDelegationId}`, target: `finding:${f.id}`, kind: 'found' })\n }\n prevStageId = stageId\n }\n // Deduplicate edges\n const seen = new Set<string>()\n return { nodes, edges: edges.filter(e => { const k = `${e.source}->${e.target}`; if (seen.has(k)) return false; seen.add(k); return true }) }\n}\n\n// ── Core snapshot (no output trees) ────────────────────────────────────────\n\nconst snapshotPerf = typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1'\n\nexport async function buildSnapshot(ctx: TargetContext): Promise<PentesterViewSnapshot> {\n const t0 = performance.now()\n\n // Parallel: run, findings, assets, registry — all independent\n const [run, findings, assetCount, registry] = await Promise.all([\n tryLoadRun(ctx),\n parseFindingsIndex(ctx),\n parseAssetsCount(ctx),\n loadTargetRegistry(ctx.projectDir).catch(() => null),\n ])\n\n const tData = (performance.now() - t0).toFixed(1)\n if (snapshotPerf) {\n console.log(`[SESSION_SWITCH_PERF] snapshot data-load=${tData}ms (run+findings+assets+registry)`)\n }\n\n // Target summaries (pure memory from registry)\n const targets: TargetSummary[] = []\n if (registry !== null) {\n for (const record of listTargetRecords(registry)) {\n targets.push({\n id: record.id, target: record.target, canonicalTarget: record.canonicalTarget,\n rootSessionId: record.rootSessionId, status: 'unknown', currentStage: null, createdAt: record.createdAt,\n })\n }\n }\n\n if (run === null) {\n return {\n run: null,\n stats: { assets: 0, findings: 0, delegations: 0 },\n stages: STAGE_IDS.map(id => ({\n id, name: STAGE_DEFINITIONS.find(d => d.id === id)?.name ?? id,\n shortName: STAGE_SHORT[id] ?? id.slice(0, 4), status: 'pending', delegationCount: 0, activeDelegationCount: 0,\n })),\n delegations: [], findings,\n trace: { nodes: [{ id: 'start', kind: 'start', label: 'Start' }], edges: [] },\n targets,\n }\n }\n\n // Pure memory projection\n const result: PentesterViewSnapshot = {\n run: buildRunView(run),\n stats: { assets: assetCount, findings: findings.length, delegations: run.delegations.length },\n stages: buildStageViews(run),\n delegations: buildDelegationViews(run),\n findings,\n trace: buildTraceModel(run, ctx, findings),\n targets,\n }\n\n const totalMs = (performance.now() - t0).toFixed(1)\n if (snapshotPerf) {\n console.log(`[SESSION_SWITCH_PERF] snapshot projection=${(Number(totalMs) - Number(tData)).toFixed(1)}ms total=${totalMs}ms`)\n }\n\n return result\n}\n\n// ── Lazy output tree ──────────────────────────────────────────────────────\n\nconst outputCache = new Map<string, { tree: OutputEntry[]; builtAt: number }>()\nconst OUTPUT_CACHE_TTL = 10_000\n\n// In-flight dedup: only one build per target at a time\nconst outputInflight = new Map<string, Promise<OutputEntry[]>>()\n\n// Global FS semaphore: max concurrent readdir/stat operations\nconst FS_SEMAPHORE = 16\nlet fsInFlight = 0\nconst fsWaiters: Array<() => void> = []\n\nfunction fsAcquire(): Promise<void> {\n if (fsInFlight < FS_SEMAPHORE) {\n fsInFlight++\n return Promise.resolve()\n }\n return new Promise(resolve => { fsWaiters.push(resolve) })\n}\n\nfunction fsRelease(): void {\n fsInFlight--\n const next = fsWaiters.shift()\n if (next !== undefined) {\n fsInFlight++\n next()\n }\n}\n\nexport function invalidateOutputCache(targetId: string): void { outputCache.delete(targetId) }\n\nexport async function buildOutputTreeForTarget(ctx: TargetContext, targetId?: string, signal?: AbortSignal): Promise<OutputTreeResult> {\n // Resolve target context\n let targetCtx = ctx\n if (targetId !== undefined && targetId !== ctx.targetId) {\n const registry = await loadTargetRegistry(ctx.projectDir)\n const record = registry.targets.find(t => t.id === targetId)\n if (record === undefined) throw new Error('target not found')\n targetCtx = buildTargetContext(ctx.projectDir, record)\n }\n\n const cacheKey = targetCtx.targetId\n const cached = outputCache.get(cacheKey)\n if (cached !== undefined && (Date.now() - cached.builtAt) < OUTPUT_CACHE_TTL) {\n console.log(`[OUTPUT_SCAN] cache=hit targetId=${cacheKey}`)\n return { targetId: cacheKey, target: targetCtx.target, current: cacheKey === ctx.targetId, children: cached.tree }\n }\n\n // In-flight dedup: reuse existing build promise for same target\n const inflight = outputInflight.get(cacheKey)\n if (inflight !== undefined) {\n console.log(`[OUTPUT_SCAN] inflight=dedup targetId=${cacheKey}`)\n const tree = await inflight\n return { targetId: cacheKey, target: targetCtx.target, current: cacheKey === ctx.targetId, children: tree }\n }\n\n console.log(`[OUTPUT_SCAN] cache=miss targetId=${cacheKey}`)\n const promise = buildOutputTree(targetCtx, signal)\n outputInflight.set(cacheKey, promise)\n\n try {\n const tree = await promise\n outputCache.set(cacheKey, { tree, builtAt: Date.now() })\n return { targetId: cacheKey, target: targetCtx.target, current: cacheKey === ctx.targetId, children: tree }\n } finally {\n outputInflight.delete(cacheKey)\n }\n}\n\n// ── Output tree builder ────────────────────────────────────────────────────\n\ninterface ScanStats {\n dirs: number\n files: number\n statCalls: number\n readdirCalls: number\n maxDepth: number\n maxDirEntries: number\n}\n\nasync function buildOutputTree(ctx: TargetContext, signal?: AbortSignal): Promise<OutputEntry[]> {\n const root = ctx.targetRoot\n if (!existsSync(root)) return []\n const entries: OutputEntry[] = []\n\n const stats: ScanStats = { dirs: 0, files: 0, statCalls: 0, readdirCalls: 0, maxDepth: 0, maxDirEntries: 0 }\n const categoryTimings: Record<string, number> = {}\n const categoryCounts: Record<string, number> = {}\n\n const categories = [\n { dir: 'report', label: 'Reports', category: 'report' as const },\n { dir: 'findings', label: 'Findings', category: 'finding' as const },\n { dir: 'assets', label: 'Artifacts', category: 'artifact' as const },\n { dir: 'evidence', label: 'Evidence', category: 'evidence' as const },\n ]\n\n for (const cat of categories) {\n signal?.throwIfAborted()\n const catDir = join(root, cat.dir)\n if (!existsSync(catDir)) continue\n const tCat = performance.now()\n const children = await scanDir(catDir, root, cat.category, 0, stats, signal)\n const catMs = (performance.now() - tCat)\n categoryTimings[cat.dir] = catMs\n categoryCounts[cat.dir] = children.length\n if (children.length > 0) {\n entries.push({ path: cat.dir, name: cat.label, kind: 'directory', category: cat.category, children: flattenSingleChildDirs(children) })\n }\n }\n\n // Stage summaries\n const stagesDir = join(root, 'stages')\n if (existsSync(stagesDir)) {\n const tStages = performance.now()\n let stageEntryCount = 0\n for (let i = 0; i < STAGE_IDS.length; i++) {\n signal?.throwIfAborted()\n const stageId = STAGE_IDS[i]\n const stageSubDir = join(stagesDir, `${String(i + 1).padStart(2, '0')}-${stageId}`)\n if (!existsSync(stageSubDir)) continue\n const children: OutputEntry[] = []\n const summaryFile = join(stageSubDir, 'summary.md')\n if (existsSync(summaryFile)) {\n stats.statCalls++\n const st = await stat(summaryFile)\n children.push({ path: relative(root, summaryFile), name: 'summary.md', kind: 'file', size: st.size, mtime: st.mtime.toISOString(), category: 'stage', sourceStage: stageId })\n }\n const delegationsDir = join(stageSubDir, 'delegations')\n if (existsSync(delegationsDir)) {\n stats.readdirCalls++\n const delDirs = await readdir(delegationsDir, { withFileTypes: true })\n for (const delDir of delDirs) {\n if (!delDir.isDirectory()) continue\n const delId = delDir.name\n const resultFile = join(delegationsDir, delId, 'result.md')\n if (existsSync(resultFile)) {\n stats.statCalls++\n const st = await stat(resultFile)\n children.push({ path: relative(root, resultFile), name: `${delId}/result.md`, kind: 'file', size: st.size, mtime: st.mtime.toISOString(), category: 'stage', sourceStage: stageId, sourceDelegationId: delId })\n }\n const evidenceDir = join(delegationsDir, delId, 'evidence')\n if (existsSync(evidenceDir)) children.push(...flattenSingleChildDirs(await scanDir(evidenceDir, root, 'evidence', 0, stats, signal, stageId, delId)))\n const artifactsDir = join(delegationsDir, delId, 'artifacts')\n if (existsSync(artifactsDir)) children.push(...flattenSingleChildDirs(await scanDir(artifactsDir, root, 'artifact', 0, stats, signal, stageId, delId)))\n }\n }\n if (children.length > 0) {\n stageEntryCount += children.length\n entries.push({ path: relative(root, stageSubDir), name: STAGE_SHORT[stageId] ?? stageId, kind: 'directory', category: 'stage', children: flattenSingleChildDirs(children) })\n }\n }\n categoryTimings['stages'] = (performance.now() - tStages)\n categoryCounts['stages'] = stageEntryCount\n }\n\n // Print scan report\n const totalMs = Object.values(categoryTimings).reduce((a, b) => a + b, 0)\n const catReport = Object.entries(categoryTimings)\n .map(([cat, ms]) => `${cat}=${ms.toFixed(0)}ms entries=${categoryCounts[cat] ?? 0}`)\n .join('\\n')\n const totalEntries = Object.values(categoryCounts).reduce((a, b) => a + b, 0)\n console.log(`[OUTPUT_SCAN]\\n${catReport}\\nstages=${categoryTimings['stages']?.toFixed(0) ?? '0'}ms entries=${categoryCounts['stages'] ?? 0}\\ntotal=${totalMs.toFixed(0)}ms entries=${totalEntries}\\ndirs=${stats.dirs} files=${stats.files} stat=${stats.statCalls} readdir=${stats.readdirCalls} maxDepth=${stats.maxDepth} maxDirEntries=${stats.maxDirEntries}`)\n\n return entries\n}\n\n// ── Bounded-concurrency scanDir ────────────────────────────────────────────\n\nconst SCAN_CONCURRENCY = 16\n\nasync function scanDir(\n dir: string, root: string, parentCategory: OutputEntry['category'],\n depth: number = 0, stats?: ScanStats, signal?: AbortSignal,\n sourceStage?: string, sourceDelegationId?: string,\n): Promise<OutputEntry[]> {\n if (depth > 3) return []\n signal?.throwIfAborted()\n try {\n if (stats) {\n stats.dirs++\n if (depth > stats.maxDepth) stats.maxDepth = depth\n }\n await fsAcquire()\n if (stats) stats.readdirCalls++\n const items = await readdir(dir, { withFileTypes: true })\n fsRelease()\n if (stats && items.length > stats.maxDirEntries) stats.maxDirEntries = items.length\n const filtered = items.filter(i => !i.name.startsWith('.') && i.name !== 'tmp' && i.name !== 'cache' && i.name !== '.dsh-pentester' && i.name !== '.git')\n\n // Process in bounded batches\n const entries: OutputEntry[] = []\n for (let batch = 0; batch < filtered.length; batch += SCAN_CONCURRENCY) {\n const batchItems = filtered.slice(batch, batch + SCAN_CONCURRENCY)\n const results = await Promise.all(batchItems.map(async (item) => {\n signal?.throwIfAborted()\n const fullPath = join(dir, item.name)\n const relPath = relative(root, fullPath)\n if (item.isDirectory()) {\n const children = await scanDir(fullPath, root, parentCategory, depth + 1, stats, signal, sourceStage, sourceDelegationId)\n if (children.length === 0) return null\n return { path: relPath, name: item.name, kind: 'directory' as const, category: parentCategory, ...(sourceStage !== undefined ? { sourceStage } : {}), ...(sourceDelegationId !== undefined ? { sourceDelegationId } : {}), children }\n }\n try {\n if (stats) { stats.files++; stats.statCalls++ }\n await fsAcquire()\n const st = await stat(fullPath)\n fsRelease()\n return { path: relPath, name: item.name, kind: 'file' as const, size: st.size, mtime: st.mtime.toISOString(), category: parentCategory, ...(sourceStage !== undefined ? { sourceStage } : {}), ...(sourceDelegationId !== undefined ? { sourceDelegationId } : {}) }\n } catch { return null }\n }))\n for (const r of results) { if (r !== null) entries.push(r) }\n }\n return entries.sort((a, b) => a.kind !== b.kind ? (a.kind === 'directory' ? -1 : 1) : a.name.localeCompare(b.name))\n } catch { return [] }\n}\n\n// ── Flatten single-child dirs ──────────────────────────────────────────────\n\nfunction flattenSingleChildDirs(entries: readonly OutputEntry[]): OutputEntry[] {\n const result: OutputEntry[] = []\n for (const entry of entries) {\n if (entry.kind !== 'directory' || entry.children === undefined || entry.children.length !== 1 || entry.children[0].kind !== 'directory') {\n result.push(entry); continue\n }\n const child = entry.children[0]\n result.push({ path: child.path, name: `${entry.name}/${child.name}`, kind: 'directory', category: entry.category, ...(entry.sourceStage !== undefined ? { sourceStage: entry.sourceStage } : {}), ...(entry.sourceDelegationId !== undefined ? { sourceDelegationId: entry.sourceDelegationId } : {}), children: child.children !== undefined ? flattenSingleChildDirs(child.children) : undefined })\n }\n return result\n}\n\n// ── readOutputFile (partial read, no full 10MB load) ──────────────────────\n\nconst MAX_PREVIEW = 1 * 1024 * 1024 // 1MB\n\nexport async function readOutputFile(\n ctx: TargetContext, relativePath: string,\n): Promise<{ ok: true; content: string; mime: string; size: number; mtime: string; name: string } | { ok: false; error: string }> {\n if (relativePath.includes('..') || relativePath.startsWith('/') || isAbsolute(relativePath) || relativePath.includes('\\0')) {\n return { ok: false, error: 'path denied' }\n }\n const root = ctx.targetRoot\n const fullPath = join(root, relativePath)\n\n const { realpathSync } = await import('node:fs')\n let realRoot: string, realFile: string\n try {\n realRoot = realpathSync(root); realFile = realpathSync(fullPath)\n } catch { return { ok: false, error: 'file not found' } }\n if (!realFile.startsWith(realRoot + sep) && realFile !== realRoot) return { ok: false, error: 'path escape denied' }\n\n try {\n const st = await stat(fullPath)\n if (st.isDirectory()) return { ok: false, error: 'is a directory' }\n\n const ext = relativePath.split('.').pop()?.toLowerCase() ?? ''\n const binaryExts = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'ico', 'pdf', 'zip', 'gz', 'tar', 'pcap', 'mitm', 'bin', 'exe', 'dll', 'so'])\n if (binaryExts.has(ext)) {\n return { ok: true, content: `[Binary file: ${ext.toUpperCase()} — ${(st.size / 1024).toFixed(1)} KB]`, mime: 'binary', size: st.size, mtime: st.mtime.toISOString(), name: relativePath.split('/').pop() ?? relativePath }\n }\n\n // Partial read: only first MAX_PREVIEW bytes\n const fh = await fsOpen(fullPath, 'r')\n const buf = Buffer.alloc(Math.min(st.size, MAX_PREVIEW))\n await fh.read(buf, 0, buf.length, 0)\n await fh.close()\n\n let content = buf.toString('utf8')\n if (st.size > MAX_PREVIEW) content += `\\n\\n... [truncated: ${(st.size / 1024).toFixed(1)} KB total]`\n\n let mime: string = 'text'\n if (ext === 'md') mime = 'markdown'\n else if (ext === 'json') mime = 'json'\n\n return { ok: true, content, mime, size: st.size, mtime: st.mtime.toISOString(), name: relativePath.split('/').pop() ?? relativePath }\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : 'read error' }\n }\n}","/**\n * ui-view/binding.ts — Lightweight session → target resolver.\n *\n * Resolution order:\n * 1. Cache (only bound resolutions, no negative caching)\n * 2. Live: deps.getLiveSessionCwd(sessionId) → ctx.get('sessions') per call\n * 3. Cold: deps.getWorkspaceForSession(sessionId) → ctx.get('workspaceRegistry') per call\n * 4. resolveSessionTargetContext → TargetContext\n *\n * NEVER calls:\n * - sessionPersistence.list()\n * - sessionPersistence.inspect()\n * - sessionQuery.readSession()\n *\n * IMPORTANT: deps are dynamic resolver functions, not static service instances.\n * They call ctx.get() on each invocation so the resolver always reads the\n * current active service. sessions/workspaceRegistry lifecycle changes do\n * not invalidate the RPC endpoint.\n */\nimport { isAbsolute } from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport { resolveSessionTargetContext, type TargetContext } from '../targets.js'\n\n// ── Dynamic dependency contract ────────────────────────────────────────────\n\nexport interface PentesterViewHostDeps {\n /** Resolve the live session cwd from the current active sessions service. */\n readonly getLiveSessionCwd: (sessionId: string) => string | undefined\n /** Resolve workspace path from the current active workspaceRegistry. */\n readonly getWorkspaceForSession: (sessionId: string) => string | undefined\n readonly verbose?: boolean\n}\n\n// ── Resolution types ───────────────────────────────────────────────────────\n\nexport interface BindingResolution {\n kind: 'bound'\n projectDir: string\n targetContext: TargetContext\n}\n\ninterface UnboundResolution {\n kind: 'unbound'\n projectDir: string\n}\n\nexport type ViewResolution = BindingResolution | UnboundResolution\n\n// ── Cache (only bound, no negative) ────────────────────────────────────────\n\nconst cache = new Map<string, BindingResolution>()\n\nexport function invalidateBinding(sessionId: string): void {\n cache.delete(sessionId)\n}\n\n// ── Main resolver ──────────────────────────────────────────────────────────\n\nexport async function resolveBinding(\n deps: PentesterViewHostDeps,\n sessionId: string,\n): Promise<ViewResolution> {\n const t0 = performance.now()\n const perf = deps.verbose || (typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1')\n\n // 1. Cache (only bound)\n const cached = cache.get(sessionId)\n if (cached !== undefined) {\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=cache total=${(performance.now() - t0).toFixed(1)}ms`)\n }\n return cached\n }\n\n // 2. Live session header (O(1) — calls ctx.get('sessions') per invocation)\n const tLive = performance.now()\n const projectDir = deps.getLiveSessionCwd(sessionId)\n const liveMs = (performance.now() - tLive).toFixed(1)\n let source = 'live'\n\n // 3. Cold: workspaceRegistry (sync, in-memory, no persistence)\n let resolvedDir = projectDir\n if (resolvedDir === undefined) {\n const tWs = performance.now()\n resolvedDir = deps.getWorkspaceForSession(sessionId)\n const wsMs = (performance.now() - tWs).toFixed(1)\n source = 'workspace-index'\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} workspaceLookup=${wsMs}ms`)\n }\n }\n\n // 4. Unbound: no projectDir found\n if (resolvedDir === undefined || resolvedDir === '') {\n const totalMs = (performance.now() - t0).toFixed(1)\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=${source} result=unbound total=${totalMs}ms`)\n }\n return { kind: 'unbound', projectDir: '' }\n }\n\n // 5. Resolve target context\n const tTarget = performance.now()\n const targetCtx = await resolveSessionTargetContext(resolvedDir, sessionId)\n const targetMs = (performance.now() - tTarget).toFixed(1)\n\n if (targetCtx !== undefined) {\n const result: BindingResolution = { kind: 'bound', projectDir: resolvedDir, targetContext: targetCtx }\n cache.set(sessionId, result) // Only cache bound\n const totalMs = (performance.now() - t0).toFixed(1)\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=${source} cwd=${resolvedDir} liveLookup=${liveMs}ms targetLookup=${targetMs}ms total=${totalMs}ms`)\n }\n if (Number(totalMs) > 100) {\n console.warn(`[SESSION_SWITCH_PERF] slow binding ${totalMs}ms source=${source}`)\n }\n return result\n }\n\n const totalMs = (performance.now() - t0).toFixed(1)\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=${source} result=target-unresolved total=${totalMs}ms`)\n }\n return { kind: 'unbound', projectDir: resolvedDir }\n}","/**\n * build-id.ts — Build identity injected at build time.\n *\n * Generated by scripts/build-id.mjs before each build.\n * Both host (tsdown) and client (esbuild) import this module.\n *\n * Format: version+shortSha (e.g. \"1.1.0+391bfd6\")\n */\nexport const BUILD_ID = \"2.2.0+478786d\"\n","/**\n * ui-view/invocations.ts — Pentester View 的 Typert 调用描述符与 schemas。\n *\n * 仅包含纯数据常量:客户端和宿主两侧均可安全导入,无 Node.js 依赖。\n */\nimport { z } from 'zod'\n\nconst pentesterViewInputSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('health') }),\n z.object({ kind: z.literal('snapshot'), sessionId: z.string() }),\n z.object({ kind: z.literal('listOutput'), sessionId: z.string(), targetId: z.string().optional() }),\n z.object({ kind: z.literal('readOutput'), sessionId: z.string(), targetId: z.string().optional(), path: z.string() }),\n z.object({ kind: z.literal('readFinding'), sessionId: z.string(), detailFile: z.string() }),\n])\n\nconst snapshotResultSchema = z.object({\n run: z.union([z.object({\n id: z.string(),\n status: z.enum(['active', 'completed']),\n currentStage: z.string().nullable(),\n targets: z.array(z.string()),\n createdAt: z.string(),\n }), z.null()]),\n stats: z.object({\n assets: z.number(),\n findings: z.number(),\n delegations: z.number(),\n }),\n stages: z.array(z.object({\n id: z.string(),\n name: z.string(),\n shortName: z.string(),\n status: z.string(),\n delegationCount: z.number(),\n activeDelegationCount: z.number(),\n })),\n delegations: z.array(z.object({\n id: z.string(),\n stageId: z.string(),\n agentId: z.string(),\n sessionId: z.string().optional(),\n objective: z.string(),\n status: z.string(),\n createdAt: z.string(),\n finishedAt: z.string().optional(),\n })),\n findings: z.array(z.object({\n id: z.string(),\n title: z.string(),\n severity: z.string(),\n status: z.string().optional(),\n sourceStage: z.string(),\n sourceDelegationId: z.string(),\n detailFile: z.string(),\n affectedAsset: z.string().optional(),\n description: z.string().optional(),\n updatedAt: z.string(),\n })),\n trace: z.object({\n nodes: z.array(z.object({\n id: z.string(),\n kind: z.string(),\n label: z.string(),\n status: z.string().optional(),\n sublabel: z.string().optional(),\n timestamp: z.string().optional(),\n })),\n edges: z.array(z.object({\n id: z.string(),\n source: z.string(),\n target: z.string(),\n kind: z.string(),\n label: z.string().optional(),\n })),\n }),\n targets: z.array(z.object({\n id: z.string(),\n target: z.string(),\n canonicalTarget: z.string(),\n rootSessionId: z.string().nullable(),\n status: z.string(),\n currentStage: z.string().nullable(),\n createdAt: z.string(),\n })),\n})\n\nconst unboundResultSchema = z.object({\n kind: z.literal('unbound'),\n targets: z.array(z.object({\n id: z.string(),\n target: z.string(),\n canonicalTarget: z.string(),\n rootSessionId: z.string().nullable(),\n status: z.string(),\n currentStage: z.string().nullable(),\n createdAt: z.string(),\n })),\n})\n\nconst outputFileResultSchema = z.object({\n path: z.string(),\n name: z.string(),\n size: z.number(),\n mtime: z.string(),\n mime: z.enum(['text', 'markdown', 'json', 'image', 'binary']),\n content: z.string().optional(),\n})\n\nconst outputTreeResultSchema = z.object({\n targetId: z.string(),\n target: z.string(),\n current: z.boolean(),\n children: z.array(z.unknown()),\n})\n\n/** 客户端 remote 贡献的 invocation 描述符 */\nexport const PENTESTER_VIEW_INVOCATION = {\n id: 'dsh-pentester#pentesterView/command',\n service: 'pentesterView',\n namespace: 'pentesterView',\n method: 'command',\n invocation: { kind: 'direct' as const },\n cancellation: {\n parameter: 'signal' as const,\n },\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#PentesterViewInput',\n schema: pentesterViewInputSchema,\n },\n },\n ],\n result: {\n mode: 'strict' as const,\n typeSymbol: 'dsh-pentester#PentesterViewResult',\n schema: z.object({\n ok: z.boolean(),\n value: z.union([snapshotResultSchema, outputTreeResultSchema, outputFileResultSchema, unboundResultSchema, z.object({ ready: z.literal(true), buildId: z.string() })]).optional(),\n error: z.string().optional(),\n code: z.string().optional(),\n }),\n },\n} as const\n\n/** 客户端 remote 网关的挂载贡献 */\nexport const PENTESTER_VIEW_REMOTE = {\n package: 'dsh-pentester',\n descriptors: [PENTESTER_VIEW_INVOCATION],\n} as const\n\n/** Typert manifest(供宿主注册)。 */\nexport const PENTESTER_VIEW_MANIFEST = {\n package: 'dsh-pentester',\n face: 'host' as const,\n schemas: [],\n model: {\n services: [\n {\n key: 'pentesterView',\n exportName: 'PentesterViewTypertService',\n description: 'Pentester View 数据服务(snapshot / readOutput)。',\n tags: [],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: {kind: string; ...}): Promise<{ok: boolean; value?: any; error?: string; code?: string}>',\n },\n ],\n types: [],\n },\n ],\n events: [],\n objects: [],\n },\n invocations: [PENTESTER_VIEW_INVOCATION],\n}","/**\n * ui-view/rpc.ts — Pentester View Typert Remote service.\n *\n * Explicit dependency injection: sessions + workspaceRegistry.\n * NEVER calls sessionPersistence, sessionQuery, or agents.\n *\n * Core snapshot: no output trees. Output is lazy via listOutput.\n */\nimport { isAbsolute } from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport { z } from 'zod'\nimport { buildSnapshot, buildOutputTreeForTarget, readOutputFile } from './snapshot.js'\nimport { resolveBinding, type PentesterViewHostDeps } from './binding.js'\nimport { loadTargetRegistry, buildTargetContext } from '../targets.js'\nimport { tryLoadRun } from '../store.js'\nimport type { PentesterViewSnapshot, OutputFileResult, OutputTreeResult, PentesterViewUnbound, TargetSummary } from './types.js'\nimport { BUILD_ID } from '../build-id.js'\nimport { PENTESTER_VIEW_INVOCATION, PENTESTER_VIEW_REMOTE, PENTESTER_VIEW_MANIFEST } from './invocations.js'\n\nexport interface PentesterHealthResult {\n readonly ready: true\n readonly buildId: string\n}\n\nexport { PENTESTER_VIEW_INVOCATION, PENTESTER_VIEW_REMOTE, PENTESTER_VIEW_MANIFEST }\n\nexport function validateCwd(raw: unknown): string | undefined {\n if (typeof raw !== 'string' || raw.length === 0) return undefined\n if (!isAbsolute(raw)) return undefined\n return raw\n}\n\n// ── Input schema (host-side, must match invocations.ts) ────────────────────\n\nconst pentesterViewInputSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('health') }),\n z.object({ kind: z.literal('snapshot'), sessionId: z.string() }),\n z.object({ kind: z.literal('listOutput'), sessionId: z.string(), targetId: z.string().optional() }),\n z.object({ kind: z.literal('readOutput'), sessionId: z.string(), targetId: z.string().optional(), path: z.string() }),\n z.object({ kind: z.literal('readFinding'), sessionId: z.string(), detailFile: z.string() }),\n])\n\n// ── Request ID counter ─────────────────────────────────────────────────────\n\nlet requestSeq = 0\n\n// ── Typert service ─────────────────────────────────────────────────────────\n\nconst HOST_PERF = typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1'\n\nexport class PentesterViewTypertService extends TypertRemoteService {\n private readonly deps: PentesterViewHostDeps\n\n constructor(ctx: unknown, deps: PentesterViewHostDeps) {\n super(ctx as never, 'pentesterView')\n this.deps = deps\n }\n\n async command(\n input: unknown,\n signal?: AbortSignal,\n ): Promise<{\n ok: boolean\n value?: PentesterViewSnapshot | OutputTreeResult | OutputFileResult | PentesterViewUnbound | PentesterHealthResult\n error?: string\n code?: string\n }> {\n const requestId = ++requestSeq\n const t0 = performance.now()\n\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} ENTER +0ms`)\n }\n\n const parsed = pentesterViewInputSchema.safeParse(input)\n if (!parsed.success) {\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} INVALID_REQUEST +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: false, error: 'invalid_request', code: 'invalid_request' }\n }\n\n const data = parsed.data\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} PARSED kind=${data.kind} +${(performance.now() - t0).toFixed(1)}ms`)\n }\n\n try {\n signal?.throwIfAborted()\n\n if (data.kind === 'health') {\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} HEALTH +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: true, value: { ready: true as const, buildId: BUILD_ID } }\n }\n\n if (data.kind === 'snapshot') {\n signal?.throwIfAborted()\n\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} BINDING_START +${(performance.now() - t0).toFixed(1)}ms`)\n }\n const tResolve = performance.now()\n const resolution = await resolveBinding(this.deps, data.sessionId)\n const resolveMs = (performance.now() - tResolve).toFixed(1)\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} BINDING_END kind=${resolution.kind} +${(performance.now() - t0).toFixed(1)}ms`)\n }\n\n if (resolution.kind === 'bound') {\n signal?.throwIfAborted()\n\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} SNAPSHOT_START +${(performance.now() - t0).toFixed(1)}ms`)\n }\n const tBuild = performance.now()\n const snapshot = await buildSnapshot(resolution.targetContext)\n const buildMs = (performance.now() - tBuild).toFixed(1)\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} SNAPSHOT_END +${(performance.now() - t0).toFixed(1)}ms`)\n }\n\n signal?.throwIfAborted()\n\n const totalMs = (performance.now() - t0).toFixed(1)\n if (HOST_PERF) {\n const payload = JSON.stringify(snapshot).length\n console.log(`[PENTESTER_RPC_HOST] #${requestId} RETURN binding=${resolveMs}ms build=${buildMs}ms total=${totalMs}ms payload=${(payload / 1024).toFixed(0)}KB`)\n }\n if (Number(totalMs) > 1000) {\n console.warn(`[PENTESTER_RPC_HOST] #${requestId} slow ${totalMs}ms`)\n }\n return { ok: true, value: snapshot }\n }\n\n if (resolution.projectDir !== '') {\n return buildUnboundSnapshot(resolution.projectDir)\n }\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} RETURN unbound +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: true, value: { kind: 'unbound', targets: [] } }\n }\n\n if (data.kind === 'listOutput') {\n signal?.throwIfAborted()\n\n const tResolve = performance.now()\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} ENTER`)\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} BINDING_START`)\n\n const resolution = await resolveBinding(this.deps, data.sessionId)\n if (resolution.kind !== 'bound') return { ok: false, error: 'not bound', code: 'no_binding' }\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} BINDING_END ${(performance.now() - tResolve).toFixed(1)}ms`)\n\n signal?.throwIfAborted()\n\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} TREE_START targetId=${data.targetId ?? 'default'}`)\n const tTree = performance.now()\n const tree = await buildOutputTreeForTarget(resolution.targetContext, data.targetId, signal)\n const treeMs = (performance.now() - tTree).toFixed(1)\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} TREE_END ${treeMs}ms`)\n\n signal?.throwIfAborted()\n\n const totalMs = (performance.now() - t0).toFixed(1)\n const payload = JSON.stringify(tree).length\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} RETURN total=${totalMs}ms entryCount=${tree.children.length} payload=${(payload / 1024).toFixed(0)}KB`)\n return { ok: true, value: tree }\n }\n\n if (data.kind === 'readOutput') {\n signal?.throwIfAborted()\n const resolution = await resolveBinding(this.deps, data.sessionId)\n if (resolution.kind !== 'bound') return { ok: false, error: 'not bound', code: 'no_binding' }\n const path = data.path\n if (path === '') return { ok: false, error: 'path required', code: 'invalid_request' }\n\n let targetCtx = resolution.targetContext\n if (data.targetId !== undefined && data.targetId !== resolution.targetContext.targetId) {\n const registry = await loadTargetRegistry(resolution.projectDir)\n const record = registry.targets.find(t => t.id === data.targetId)\n if (record === undefined) return { ok: false, error: 'target not found', code: 'invalid_target' }\n targetCtx = buildTargetContext(resolution.projectDir, record)\n }\n\n const result = await readOutputFile(targetCtx, path)\n if (!result.ok) return { ok: false, error: result.error, code: 'read_error' }\n return {\n ok: true,\n value: { path, name: result.name, size: result.size, mtime: result.mtime, mime: result.mime as OutputFileResult['mime'], content: result.content },\n }\n }\n\n if (data.kind === 'readFinding') {\n signal?.throwIfAborted()\n const resolution = await resolveBinding(this.deps, data.sessionId)\n if (resolution.kind !== 'bound') return { ok: false, error: 'not bound', code: 'no_binding' }\n const detailFile = data.detailFile\n if (detailFile === '') return { ok: false, error: 'detailFile required', code: 'invalid_request' }\n const result = await readOutputFile(resolution.targetContext, `findings/${detailFile}`)\n if (!result.ok) return { ok: false, error: result.error, code: 'read_error' }\n return { ok: true, value: { path: `findings/${detailFile}`, name: detailFile, size: result.size, mtime: result.mtime, mime: 'markdown', content: result.content } }\n }\n\n return { ok: false, error: 'unknown kind', code: 'invalid_request' }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} ABORTED +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: false, error: 'aborted', code: 'aborted' }\n }\n const totalMs = (performance.now() - t0).toFixed(1)\n if (HOST_PERF) console.error(`[PENTESTER_RPC_HOST] #${requestId} FAILED kind=${data.kind} +${totalMs}ms: ${error instanceof Error ? error.message : 'error'}`)\n return { ok: false, error: error instanceof Error ? error.message : 'failed', code: 'snapshot_error' }\n }\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────\n\nasync function buildUnboundSnapshot(projectDir: string): Promise<{ ok: true; value: PentesterViewUnbound }> {\n const registry = await loadTargetRegistry(projectDir)\n const targets: TargetSummary[] = []\n for (const record of registry.targets) {\n const ctx = buildTargetContext(projectDir, record)\n const run = await tryLoadRun(ctx)\n targets.push({\n id: record.id, target: record.target, canonicalTarget: record.canonicalTarget,\n rootSessionId: record.rootSessionId, status: run?.status ?? 'unknown',\n currentStage: run?.currentStage ?? null, createdAt: record.createdAt,\n })\n }\n return { ok: true, value: { kind: 'unbound', targets } }\n}","/**\n * host-manifest.ts — Single unified Typert host manifest for dsh-pentester.\n *\n * Combines pentesterDocker (Settings UI) and pentesterView (Pentester panel)\n * invocations into ONE manifest. Two separate register() calls with the same\n * package name cause the first to be withdrawn (SRC fallback denied).\n *\n * Client uses the same invocation constants via PENTESTER_REMOTE and\n * PENTESTER_VIEW_REMOTE — no duplication of endpoint definitions.\n */\nimport { PENTESTER_DOCKER_INVOCATION } from './invocations.js'\nimport { PENTESTER_VIEW_INVOCATION } from './ui-view/invocations.js'\n\nexport const PENTESTER_HOST_MANIFEST = {\n package: 'dsh-pentester',\n face: 'host' as const,\n schemas: [] as readonly never[],\n model: {\n services: [\n {\n key: 'pentesterDocker',\n exportName: 'PentesterDockerTypertService',\n description: 'Pentester Docker Engine 设置(Settings UI Docker Engine Tab)。',\n tags: [] as readonly never[],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: object): Promise<{ok:boolean; value?:any; error?:string; code?:string}>',\n },\n ],\n types: [] as readonly never[],\n },\n {\n key: 'pentesterView',\n exportName: 'PentesterViewTypertService',\n description: 'Pentester View 数据服务(snapshot / readOutput)。',\n tags: [] as readonly never[],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: {kind:string; ...}): Promise<{ok:boolean; value?:any; error?:string; code?:string}>',\n },\n ],\n types: [] as readonly never[],\n },\n ],\n events: [] as readonly never[],\n objects: [] as readonly never[],\n },\n invocations: [PENTESTER_DOCKER_INVOCATION, PENTESTER_VIEW_INVOCATION],\n} as const","/**\n * git.ts — GitCheckpointService:target-scoped git 仓库管理(宿主侧)。\n *\n * 仓库根 = targetRoot(每 Target 独立 .git)。\n * 约定式提交:\n * - 初始:`workspace: initialize <target>`\n * - 阶段完成:`ptes(<NN>-<stage>): complete` + tag `ptes/<NN>-<stage>`\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 type { TargetContext } from './targets.js'\n\nexport class GitCheckpointError extends Error {}\n\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 readonly isRepo?: (ctx: TargetContext) => Promise<boolean>\n}\n\nexport class GitCheckpointService {\n private readonly runner: GitRunner\n private readonly userName: string\n private readonly userEmail: string\n private readonly isRepoOverride?: (ctx: TargetContext) => 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 repoDir(ctx: TargetContext): string {\n return ctx.targetRoot\n }\n\n async isRepo(ctx: TargetContext): Promise<boolean> {\n if (this.isRepoOverride !== undefined) return this.isRepoOverride(ctx)\n return existsSync(join(this.repoDir(ctx), '.git'))\n }\n\n async init(ctx: TargetContext, target?: string): Promise<void> {\n const cwd = this.repoDir(ctx)\n await mkdir(cwd, { recursive: true })\n if (await this.isRepo(ctx)) return\n await this.runner(['init', '-b', 'main'], cwd).catch(async () => {\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 async checkpointStage(ctx: TargetContext, stage: StageId): Promise<string> {\n if (!(await this.isRepo(ctx))) {\n throw new GitCheckpointError('workspace is not a git repository; run initTargetWorkspace first')\n }\n const cwd = this.repoDir(ctx)\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 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 async currentBranch(ctx: TargetContext): Promise<string> {\n const cwd = this.repoDir(ctx)\n const out = await this.runner(['branch', '--show-current'], cwd).catch(() => '')\n return out.trim() || 'main'\n }\n\n async hasChanges(ctx: TargetContext): Promise<boolean> {\n const cwd = this.repoDir(ctx)\n const out = await this.runner(['status', '--porcelain'], cwd).catch(() => '')\n return out.trim() !== ''\n }\n\n async findStageCheckpoint(ctx: TargetContext, stage: StageId): Promise<string | undefined> {\n const cwd = this.repoDir(ctx)\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 async createBackupBranch(ctx: TargetContext, stage: string): Promise<string> {\n const cwd = this.repoDir(ctx)\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 async createReworkBranch(ctx: TargetContext, checkpoint: string, nextStageSlug: string): Promise<string> {\n const cwd = this.repoDir(ctx)\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 async checkout(ctx: TargetContext, ref: string): Promise<void> {\n const cwd = this.repoDir(ctx)\n await this.runner(['checkout', ref], cwd)\n }\n\n private async commit(cwd: string, message: string): Promise<void> {\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 * 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 *\n * RPC endpoints (pentesterDocker, pentesterView) are registered in the\n * main fiber — NOT a child plugin. Their lifetime equals the dsh-pentester\n * plugin lifetime. sessions/workspaceRegistry are resolved dynamically\n * via ctx.get() on each command invocation, so their lifecycle does not\n * affect RPC endpoint registration.\n */\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { performance } from 'node:perf_hooks'\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 } from './rpc.js'\nimport { PentesterViewTypertService } from './ui-view/rpc.js'\nimport { PENTESTER_HOST_MANIFEST } from './host-manifest.js'\nimport type { PentesterViewHostDeps } from './ui-view/binding.js'\nimport { GitCheckpointService } from './git.js'\nimport type { TargetContext } from './targets.js'\nimport { BUILD_ID } from './build-id.js'\n\nexport const name = 'dsh-pentester'\n\n// typert is a hard dependency: RPC endpoints must exist for the full\n// plugin lifetime. sessions/workspaceRegistry are NOT hard dependencies\n// — they are resolved dynamically per command invocation.\nexport const inject = ['tools', 'subagents', 'typert']\n\nexport interface Config {\n verbose: boolean\n dockerHost?: string\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 console.log(`[dsh-pentester] host build=${BUILD_ID}`)\n\n // ── Event loop stall detector (DSH_PENTESTER_PERF=1 only) ──────────────\n const perf = config.verbose || (typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1')\n if (perf) {\n const INTERVAL = 100\n let expected = performance.now() + INTERVAL\n const timer = setInterval(() => {\n const now = performance.now()\n const lag = now - expected\n if (lag > 250) {\n console.warn(`[HOST_EVENT_LOOP_LAG] ${lag.toFixed(0)}ms (expected interval=${INTERVAL}ms)`)\n }\n expected = now + INTERVAL\n }, INTERVAL)\n timer.unref()\n console.log('[dsh-pentester] event loop stall detector active (interval=100ms, warn>250ms)')\n }\n\n // ── Descriptor lifecycle monitor (verbose/perf only) ───────────────────\n if (perf) {\n try {\n const typertLocal = (ctx as any).typert?.local as {\n subscribe?: (listener: (event: { kind: string; key: string }) => void) => () => void\n }\n if (typertLocal?.subscribe !== undefined) {\n typertLocal.subscribe((event) => {\n if (event.key === 'pentesterView/command') {\n console.log(`[PENTESTER_RPC_LIFECYCLE] pentesterView/command ${event.kind}`)\n }\n })\n }\n } catch { /* best-effort */ }\n }\n\n const profiles = loadAgentProfiles(agentsRoot())\n const presetDir = await publishPentesterPreset()\n if (presetDir !== undefined) {\n await writeStageProfilesManifest(presetDir, profiles)\n }\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 ctx.provide('pentester', {\n registerRootTools: (tools) => registerRootTools(tools, {\n delegations,\n profiles,\n git,\n pushWorkspace: async (targetCtx: TargetContext, run) => { await docker.pushWorkspace(run.id, targetCtx) },\n syncWorkspace: async (targetCtx: TargetContext, run) => { await docker.syncWorkspace(run.id, targetCtx) },\n sessionQuery: {\n readSession: async (sessionId: string) => {\n const sq = (ctx as { get?: (name: string) => unknown }).get?.('sessionQuery') as\n { readSession(id: string): Promise<{ events: ReadonlyArray<{ type: string; data?: unknown }> }> } | undefined\n if (sq === undefined) throw new Error('sessionQuery service unavailable')\n return sq.readSession(sessionId)\n },\n },\n }),\n registerContainerExecTool: (tools) => registerContainerExecTool(tools, docker),\n } satisfies PentesterService)\n\n // ── RPC Services + Manifest — directly in main fiber ───────────────────\n // The endpoint lifetime MUST equal the dsh-pentester plugin lifetime.\n // sessions/workspaceRegistry are resolved dynamically per command.\n //\n // IMPORTANT: manifest MUST be registered before services so the Typert\n // gateway can route requests. Services created before the manifest are\n // invisible to remote clients.\n\n // Register manifest first — gateway routing depends on it.\n ;(ctx as any).typert.register(PENTESTER_HOST_MANIFEST)\n\n // Docker RPC service (settings UI)\n new PentesterDockerTypertService(ctx, {\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 applyHost: (host) => docker.updateHost(host),\n docker,\n })\n\n // Pentester View RPC service — dynamic resolvers, not static instances\n const viewDeps: PentesterViewHostDeps = {\n getLiveSessionCwd(sessionId: string): string | undefined {\n try {\n const sessions = (ctx as { get?: (name: string) => unknown }).get?.('sessions') as\n { get?: (id: string) => { header: { cwd?: string } } | undefined } | undefined\n const session = sessions?.get?.(sessionId)\n const cwd = session?.header?.cwd\n if (typeof cwd === 'string' && cwd.length > 0 && cwd.startsWith('/')) return cwd\n } catch {\n // ctx.get('sessions') may throw if service is not yet available\n }\n return undefined\n },\n\n getWorkspaceForSession(sessionId: string): string | undefined {\n try {\n const registry = (ctx as { get?: (name: string) => unknown }).get?.('workspaceRegistry') as\n { list?: () => readonly { path: string; sessionIds: readonly string[] }[] } | undefined\n if (registry?.list === undefined) return undefined\n for (const workspace of registry.list()) {\n if (workspace.sessionIds.includes(sessionId)) {\n return workspace.path\n }\n }\n } catch {\n // ctx.get('workspaceRegistry') may throw if service is not yet available\n }\n return undefined\n },\n\n verbose: config.verbose,\n }\n\n new PentesterViewTypertService(ctx, viewDeps)\n\n // ── Startup self-check ─────────────────────────────────────────────────\n const typertLocal = (ctx as any).typert.local as {\n get(endpoint: string): unknown\n }\n\n const dockerEndpoint = typertLocal.get('pentesterDocker/command')\n const viewEndpoint = typertLocal.get('pentesterView/command')\n\n if (dockerEndpoint === undefined || viewEndpoint === undefined) {\n throw new Error(\n 'dsh-pentester startup failed: RPC descriptors not registered. ' +\n `docker=${dockerEndpoint !== undefined ? 'ok' : 'MISSING'} ` +\n `view=${viewEndpoint !== undefined ? 'ok' : 'MISSING'}`,\n )\n }\n\n console.log(`[dsh-pentester] RPC ready build=${BUILD_ID}`)\n console.log(` pentesterDocker/command = registered`)\n console.log(` pentesterView/command = registered`)\n console.log(` host module = ${import.meta.url}`)\n\n if (config.verbose) {\n console.log(`[dsh-pentester] loaded with ${profiles.size} agent profiles`)\n }\n}\n\nfunction agentsRoot(): string {\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\nexport const STAGE_PROFILES_FILE = 'stage-profiles.json'\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\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}"],"x_google_ignoreList":[17],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["RUN_DIR","targetRunFilePath","targetEventsPath","readJsonArray","imageReadyOn","fsOpen","pentesterViewInputSchema"],"sources":["../src/dsh.ts","../src/stages.ts","../src/model.ts","../src/targets.ts","../src/store.ts","../src/workspace.ts","../src/delegations.ts","../src/pentest/assets.ts","../src/pentest/findings.ts","../src/pentest/pre-engagement.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/ui-view/snapshot.ts","../src/ui-view/binding.ts","../src/build-id.ts","../src/ui-view/invocations.ts","../src/ui-view/rpc.ts","../src/host-manifest.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_start',\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 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: 2\n readonly id: string\n readonly createdAt: string\n /** Singular primary target (canonicalized). */\n target: string\n /** Authorized scope text (human-readable; not machine-enforced). */\n scope: 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 * targets.ts — Target Registry: multi-target workspace isolation.\n *\n * Project workspace is shared only as a container for Target workspaces.\n * Every Target has an isolated Root Session, PentestRun, PTES timeline,\n * filesystem tree, Git history and Toolbox runtime.\n *\n * TargetContext is the mandatory resolver for all target-specific code.\n * No target-scoped function accepts a bare projectDir.\n */\nimport { createHash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { stageDir, type StageId } from './model.js'\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nexport const WORKSPACE_DIR = 'workspace'\nexport const RUN_DIR = '.dsh-pentester'\nexport const RUN_FILE = 'run.json'\nexport const TARGETS_FILE = 'targets.json'\nexport const TARGETS_SUBDIR = 'targets'\nconst TARGET_REGISTRY_SCHEMA = 1\n\n// ── Target registry types ────────────────────────────────────────────────────\n\nexport interface TargetRecord {\n readonly id: string\n readonly target: string\n readonly canonicalTarget: string\n readonly dirName: string\n /** Authoritative Root controller session id. */\n rootSessionId: string | null\n readonly createdAt: string\n updatedAt: string\n}\n\nexport interface TargetRegistry {\n readonly schemaVersion: typeof TARGET_REGISTRY_SCHEMA\n targets: TargetRecord[]\n}\n\n/**\n * Resolved target context: the single source of truth for all\n * target-scoped path resolution.\n */\nexport interface TargetContext {\n readonly projectDir: string\n readonly workspaceRoot: string\n readonly targetId: string\n readonly target: string\n readonly canonicalTarget: string\n readonly dirName: string\n readonly targetRoot: string\n readonly rootSessionId: string | null\n}\n\n// ── Canonicalization ─────────────────────────────────────────────────────────\n\n/**\n * Conservative canonicalization: trim, lowercase hostname portion,\n * strip trailing slash/path for URLs. Preserves port and scheme distinctions.\n * Never merges semantically different targets.\n */\nexport function canonicalizeTarget(raw: string): string {\n let cleaned = raw.trim()\n if (cleaned === '') return cleaned\n\n // Strip URL scheme for normalization\n let scheme = ''\n const schemeMatch = /^(https?:\\/\\/)/i.exec(cleaned)\n if (schemeMatch !== null) {\n scheme = schemeMatch[1].toLowerCase()\n cleaned = cleaned.slice(schemeMatch[1].length)\n }\n\n // Strip trailing slash and path\n const hostEnd = cleaned.indexOf('/')\n if (hostEnd !== -1) {\n cleaned = cleaned.slice(0, hostEnd)\n }\n\n // Strip trailing colon (no port)\n cleaned = cleaned.replace(/:$/, '')\n\n // Lowercase hostname portion (hostnames are case-insensitive)\n // Preserve port: example.com:8443\n const portMatch = /^(.+):(\\d+)$/.exec(cleaned)\n if (portMatch !== null) {\n cleaned = `${portMatch[1].toLowerCase()}:${portMatch[2]}`\n } else {\n cleaned = cleaned.toLowerCase()\n }\n\n return scheme === '' ? cleaned : `${scheme}${cleaned}`\n}\n\n/** 8-char hex digest for stable short id. */\nexport function makeTargetId(canonicalTarget: string): string {\n return createHash('sha1').update(canonicalTarget).digest('hex').slice(0, 8)\n}\n\n/**\n * Slug-safe directory name from a target string.\n * Replaces path-unsafe characters with hyphens.\n * Format: <readable-slug>-<short-hash>\n */\nexport function makeTargetDirName(target: string, id: string): string {\n // Build a readable slug from the target\n const slug = target\n .replace(/^https?:\\/\\//, '')\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40)\n return `${slug}-${id}`\n}\n\n/**\n * Validate that a target string is safe for directory use.\n * Rejects: /, \\, .., NUL, empty, control characters.\n */\nexport function isTargetSafe(raw: string): boolean {\n if (raw.length === 0) return false\n if (raw.includes('\\0')) return false\n if (raw.includes('/') || raw.includes('\\\\')) return false\n if (raw.includes('..')) return false\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f]/.test(raw)) return false\n return true\n}\n\n// ── Project-level paths ──────────────────────────────────────────────────────\n\nexport function projectWorkspaceDir(projectDir: string): string {\n return join(projectDir, WORKSPACE_DIR)\n}\n\nexport function targetRegistryPath(projectDir: string): string {\n return join(projectWorkspaceDir(projectDir), RUN_DIR, TARGETS_FILE)\n}\n\nexport function targetsRoot(projectDir: string): string {\n return join(projectWorkspaceDir(projectDir), TARGETS_SUBDIR)\n}\n\n// ── Target-scoped paths ──────────────────────────────────────────────────────\n\nexport function targetRoot(ctx: TargetContext): string {\n return ctx.targetRoot\n}\n\nexport function runFilePath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, RUN_FILE)\n}\n\nexport function workspaceMetaPath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, 'workspace.json')\n}\n\nexport function eventsFilePath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, 'events.jsonl')\n}\n\nexport function targetInputDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'target', 'inputs')\n}\n\nexport function assetsDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'assets')\n}\n\nexport function findingsDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'findings')\n}\n\nexport function stagesDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'stages')\n}\n\nexport function reportDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'report')\n}\n\nexport function trafficDir(ctx: TargetContext): string {\n return join(ctx.targetRoot, 'traffic')\n}\n\nexport function stageDelegationsDir(ctx: TargetContext, stage: StageId): string {\n return join(stagesDir(ctx), stageDir(stage), 'delegations')\n}\n\n/** Host-side delegation directory: `<targetRoot>/stages/<NN>-<stage>/delegations/D-00N`. */\nexport function delegationHostDir(ctx: TargetContext, stage: StageId, id: string): string {\n return join(stageDelegationsDir(ctx, stage), id)\n}\n\n/** Container-side delegation directory: `/workspace/stages/<NN>-<stage>/delegations/D-00N`. */\nexport function delegationContainerDir(stage: StageId, id: string): string {\n return `/workspace/stages/${stageDir(stage)}/delegations/${id}`\n}\n\n// ── Registry I/O ─────────────────────────────────────────────────────────────\n\nexport class TargetRegistryError extends Error {}\n\n/**\n * Load the workspace target registry. Returns empty registry if file does not\n * exist (no targets yet). Throws on corruption.\n */\nexport async function loadTargetRegistry(projectDir: string): Promise<TargetRegistry> {\n const file = targetRegistryPath(projectDir)\n if (!existsSync(file)) {\n return { schemaVersion: TARGET_REGISTRY_SCHEMA, targets: [] }\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(await readFile(file, 'utf8'))\n } catch (error) {\n throw new TargetRegistryError(\n `targets.json is corrupted: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n if (parsed === null || typeof parsed !== 'object') {\n throw new TargetRegistryError('targets.json must be an object')\n }\n const record = parsed as Record<string, unknown>\n if (record.schemaVersion !== TARGET_REGISTRY_SCHEMA) {\n throw new TargetRegistryError(\n `targets.json: unsupported schemaVersion ${String(record.schemaVersion)}`,\n )\n }\n if (!Array.isArray(record.targets)) {\n throw new TargetRegistryError('targets.json: targets must be an array')\n }\n return record as unknown as TargetRegistry\n}\n\n/** Atomic write via tmp+rename. */\nexport async function saveTargetRegistry(\n projectDir: string,\n registry: TargetRegistry,\n): Promise<void> {\n const file = targetRegistryPath(projectDir)\n await mkdir(join(projectWorkspaceDir(projectDir), RUN_DIR), { recursive: true })\n const tmp = `${file}.${crypto.randomUUID().slice(0, 8)}.tmp`\n await writeFile(tmp, `${JSON.stringify(registry, null, 2)}\\n`)\n await rename(tmp, file)\n}\n\n// ── Registry mutation queue ──────────────────────────────────────────────────\n\nconst registryQueue = new Map<string, Promise<void>>()\n\n/**\n * Serial read-modify-write for targets.json. Keyed by projectDir.\n * Concurrent inserts from different sessions are serialized to prevent\n * lost updates.\n */\nexport async function updateTargetRegistry(\n projectDir: string,\n fn: (registry: TargetRegistry) => void | Promise<void>,\n): Promise<void> {\n const prev = registryQueue.get(projectDir) ?? Promise.resolve()\n const next = prev.then(async () => {\n const registry = await loadTargetRegistry(projectDir)\n await fn(registry)\n await saveTargetRegistry(projectDir, registry)\n })\n registryQueue.set(projectDir, next.catch(() => undefined).then(() => {}))\n return next\n}\n\n// ── Registry queries ─────────────────────────────────────────────────────────\n\nexport function listTargetRecords(registry: TargetRegistry): readonly TargetRecord[] {\n return registry.targets\n}\n\nexport function resolveTargetById(\n registry: TargetRegistry,\n targetId: string,\n): TargetRecord | undefined {\n return registry.targets.find(t => t.id === targetId)\n}\n\nexport function resolveTargetByCanonicalTarget(\n registry: TargetRegistry,\n canonicalTarget: string,\n): TargetRecord | undefined {\n return registry.targets.find(t => t.canonicalTarget === canonicalTarget)\n}\n\nexport function resolveTargetByRootSession(\n registry: TargetRegistry,\n sessionId: string,\n): TargetRecord | undefined {\n return registry.targets.find(t => t.rootSessionId === sessionId)\n}\n\n/**\n * Find a TargetRecord whose PentestRun contains a Delegation with the given\n * worker sessionId. Returns undefined if no active run matches.\n * This is a heavier query that requires loading each target's run.json.\n */\nexport async function resolveTargetByWorkerSession(\n projectDir: string,\n registry: TargetRegistry,\n sessionId: string,\n): Promise<{ record: TargetRecord; run: unknown } | undefined> {\n for (const record of registry.targets) {\n const ctx = buildTargetContext(projectDir, record)\n const runFile = runFilePath(ctx)\n if (!existsSync(runFile)) continue\n try {\n const run = JSON.parse(await readFile(runFile, 'utf8'))\n const delegations = run?.delegations\n if (!Array.isArray(delegations)) continue\n if (delegations.some((d: { sessionId?: string }) => d.sessionId === sessionId)) {\n return { record, run }\n }\n } catch {\n continue\n }\n }\n return undefined\n}\n\n// ── TargetContext construction ───────────────────────────────────────────────\n\nexport function buildTargetContext(\n projectDir: string,\n record: TargetRecord,\n): TargetContext {\n const targetRootPath = join(targetsRoot(projectDir), record.dirName)\n return {\n projectDir,\n workspaceRoot: projectWorkspaceDir(projectDir),\n targetId: record.id,\n target: record.target,\n canonicalTarget: record.canonicalTarget,\n dirName: record.dirName,\n targetRoot: targetRootPath,\n rootSessionId: record.rootSessionId,\n }\n}\n\n/**\n * Resolve the TargetContext for the given Root session.\n * Returns undefined if this session is not bound to any target.\n */\nexport async function resolveSessionTargetContext(\n projectDir: string,\n sessionId: string,\n): Promise<TargetContext | undefined> {\n const registry = await loadTargetRegistry(projectDir)\n const record = resolveTargetByRootSession(registry, sessionId)\n if (record === undefined) return undefined\n return buildTargetContext(projectDir, record)\n}\n\n/**\n * Resolve TargetContext for a worker session (via delegation binding).\n * Returns undefined if no delegation matches this session.\n */\nexport async function resolveWorkerTargetContext(\n projectDir: string,\n sessionId: string,\n): Promise<TargetContext | undefined> {\n const registry = await loadTargetRegistry(projectDir)\n const result = await resolveTargetByWorkerSession(projectDir, registry, sessionId)\n if (result === undefined) return undefined\n return buildTargetContext(projectDir, result.record)\n}","/**\n * store.ts — target-scoped PentestRun persistence (docs/workspace.md).\n * Atomic write via tmp+rename; no event log, no replay.\n *\n * All run I/O requires a TargetContext (from src/targets.ts). Bare projectDir\n * is no longer accepted for run-level operations.\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isStageId, nextStage, type Delegation, type PentestRun, type StageId } from './model.js'\nimport { runFilePath as targetRunFilePath, type TargetContext } from './targets.js'\n\nexport const RUN_DIR = '.dsh-pentester'\nexport const WORKSPACE_DIR = 'workspace'\n\nexport class StoreError extends Error {}\n\n/** @deprecated Use target-scoped `runFilePath(ctx)` from targets.ts instead. */\nexport function workspaceDir(projectDir: string): string {\n return join(projectDir, WORKSPACE_DIR)\n}\n\n// ── Target-scoped run I/O ────────────────────────────────────────────────────\n\nexport async function resolvePentestRun(ctx: TargetContext): Promise<PentestRun | null> {\n return tryLoadRun(ctx)\n}\n\nexport async function tryLoadRun(ctx: TargetContext): Promise<PentestRun | null> {\n const file = targetRunFilePath(ctx)\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\nexport async function loadRun(ctx: TargetContext): Promise<PentestRun | undefined> {\n return (await tryLoadRun(ctx)) ?? undefined\n}\n\nexport async function saveRun(ctx: TargetContext, run: PentestRun): Promise<void> {\n const file = targetRunFilePath(ctx)\n await mkdir(join(ctx.targetRoot, RUN_DIR), { recursive: true })\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// ── Serial write protection ──────────────────────────────────────────────────\n\nconst serialQueue = new Map<string, Promise<void>>()\n\n/**\n * Serial read-modify-write for a target's run.json. Keyed by targetId.\n * Concurrent calls for the same target queue automatically.\n */\nexport async function updateRun(\n ctx: TargetContext,\n fn: (run: PentestRun) => void | Promise<void>,\n): Promise<void> {\n const key = ctx.targetId\n const prev = serialQueue.get(key) ?? Promise.resolve()\n const next = prev.then(async () => {\n const run = await resolvePentestRun(ctx)\n if (run === null) throw new StoreError('cannot update a PentestRun that does not exist')\n await fn(run)\n await saveRun(ctx, run)\n })\n serialQueue.set(key, next.catch(() => undefined).then(() => {}))\n return next\n}\n\n// ── Domain helpers (unchanged) ───────────────────────────────────────────────\n\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 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\nexport function markStageReviewing(run: PentestRun): void {\n if (run.currentStage === null) return\n run.stageStatuses = { ...(run.stageStatuses ?? {}), [run.currentStage]: 'reviewing' }\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\n// ── Validation ───────────────────────────────────────────────────────────────\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 !== 2 && 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 * workspace.ts — target-scoped workspace initialization and host-side artifacts.\n *\n * New layout (per docs/workspace.md, updated for multi-target):\n *\n * <project>/workspace/\n * ├── .dsh-pentester/\n * │ └── targets.json ← Target registry (workspace-level)\n * └── targets/\n * └── <target-id>/\n * ├── .git/\n * ├── .dsh-pentester/\n * │ ├── run.json\n * │ ├── workspace.json\n * │ └── events.jsonl\n * ├── target/\n * ├── assets/\n * ├── findings/\n * ├── stages/\n * ├── report/\n * └── traffic/\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 StageId } from './model.js'\nimport { RUN_DIR } from './store.js'\nimport { eventsFilePath as targetEventsPath, targetInputDir, type TargetContext } from './targets.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 interface WorkspaceEvent {\n readonly ts: string\n readonly type: string\n readonly data?: unknown\n}\n\n// ── Project-level workspace ──────────────────────────────────────────────────\n\n/**\n * Ensure the project-level workspace skeleton (not target-specific).\n * Creates: workspace/, workspace/.dsh-pentester/, workspace/targets/.\n * Idempotent.\n */\nexport async function ensureProjectWorkspace(projectDir: string): Promise<void> {\n const ws = join(projectDir, 'workspace')\n await mkdir(join(ws, RUN_DIR), { recursive: true })\n await mkdir(join(ws, 'targets'), { recursive: true })\n}\n\n// ── Target-scoped workspace ──────────────────────────────────────────────────\n\nexport function workspaceFilePath(ctx: TargetContext): string {\n return join(ctx.targetRoot, RUN_DIR, 'workspace.json')\n}\n\n/** Append an event to the target's events.jsonl (best-effort, never blocks). */\nexport async function appendEvent(ctx: TargetContext, event: WorkspaceEvent): Promise<void> {\n try {\n await appendFile(\n targetEventsPath(ctx),\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 * Initialize a target workspace with the full skeleton.\n * Creates: .dsh-pentester/, target/, assets/, findings/, stages/,\n * report/, traffic/, .gitignore.\n * Idempotent: only creates missing directories.\n */\nexport async function initTargetWorkspace(\n ctx: TargetContext,\n options: { target?: string; language?: string; scope?: string; roe?: string } = {},\n): Promise<WorkspaceMeta> {\n const root = ctx.targetRoot\n const metaPath = workspaceFilePath(ctx)\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(ctx, { 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 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(ctx, 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/** Write target/target.json (idempotent). */\nexport async function writeTarget(ctx: TargetContext, target: string | undefined): Promise<void> {\n if (target === undefined) return\n const file = join(ctx.targetRoot, '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/** Write stage summary.md. */\nexport async function writeStageSummary(\n ctx: TargetContext,\n stage: StageId,\n summary: string,\n): Promise<void> {\n const text = summary.trim()\n if (text === '') return\n await writeFile(\n join(ctx.targetRoot, 'stages', stageDir(stage), 'summary.md'),\n `# ${stageDir(stage)}\\n\\n${text}\\n`,\n 'utf8',\n )\n}\n\n/** Promote threat-model.md from delegation dir to canonical findings/. */\nexport async function promoteDeliverables(\n ctx: TargetContext,\n dir: string,\n): Promise<void> {\n const root = ctx.targetRoot\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/** Write pre-engagement provenance to target/inputs/pre-engagement.md. */\nexport async function writePreEngagementInput(\n ctx: TargetContext,\n options: {\n target: string\n scope: string\n roe: string\n language: string\n },\n): Promise<void> {\n const inputsDir = targetInputDir(ctx)\n await mkdir(inputsDir, { recursive: true })\n const content = [\n '# Pre-engagement Confirmation',\n '',\n `**Recorded**: ${new Date().toISOString()}`,\n '',\n '## Target',\n `- ${options.target}`,\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 * 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 * 目录契约:`<targetRoot>/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 { findDelegation, markStageReviewing, nextDelegationId, saveRun } from './store.js'\nimport { appendEvent } from './workspace.js'\nimport { DshClient, type CreateWorkerInput } from './dsh.js'\nimport { DockerRuntime } from './docker/runtime.js'\nimport { delegationHostDir, delegationContainerDir, type TargetContext } from './targets.js'\nimport type { StageId } from './model.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 targetContext: TargetContext\n readonly run: PentestRun\n readonly profiles: ReadonlyMap<string, AgentProfile>\n readonly rootSessionId: string\n readonly parent: Agent\n readonly signal: AbortSignal\n}\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- Set the timeout duration for invoking the tool to 1800000 milliseconds.\n For operations such as enumeration, directory scanning, brute force cracking, etc.,\n a longer duration such as 1 hour or 2 hours can be set.`\n\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 * 所以必须自包含。\n */\nexport function buildWorkerTaskPrompt(options: {\n readonly run: PentestRun\n readonly delegation: Delegation\n readonly stageId: StageId\n}): string {\n const { run, delegation, stageId } = options\n const stage = stageDefinition(stageId)\n const containerDir = delegationContainerDir(stageId, delegation.id)\n const metadata = [\n `Delegation ID: ${delegation.id}`,\n `Stage: ${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 `Target: ${run.target || '(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\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 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 ctx = deps.targetContext\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 = delegationHostDir(ctx, 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 status: 'starting',\n createdAt: new Date().toISOString(),\n }\n deps.run.delegations.push(delegation)\n await saveRun(ctx, deps.run)\n await appendEvent(ctx, {\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(ctx, deps.run)\n // Push scaffold to container.\n await this.docker.pushWorkspace(deps.run.id, ctx).catch(() => undefined)\n const toolbox = await this.docker.ensureImage('kali')\n const containerId = await this.docker.ensureRunContainer({ runId: deps.run.id, targetId: ctx.targetId, target: ctx.canonicalTarget, toolbox, targetRoot: ctx.targetRoot })\n for (const delegation of created) {\n await this.dispatch(deps, delegation, containerId)\n }\n await saveRun(ctx, deps.run)\n return created\n }\n\n private async dispatch(deps: DelegateDeps, delegation: Delegation, containerId: string): Promise<void> {\n const profile = deps.profiles.get(delegation.agentId)!\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 创建\n }\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, stageId: delegation.stageId }),\n ...(profile.model === undefined ? {} : { model: profile.model }),\n }\n const start = await this.dsh.startContinuableWorker(input, deps.parent, deps.signal)\n delegation.sessionId = start.childId\n delegation.status = 'active'\n await saveRun(deps.targetContext, deps.run)\n await appendEvent(deps.targetContext, {\n ts: new Date().toISOString(),\n type: 'delegation.dispatched',\n data: { id: delegation.id, childId: start.childId, messageId: start.messageId },\n })\n }\n\n async cancel(\n deps: { targetContext: TargetContext; 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 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\n }\n }\n delegation.status = 'closed'\n delegation.resultSummary = reason ?? 'closed by Root'\n delegation.finishedAt = new Date().toISOString()\n await saveRun(deps.targetContext, deps.run)\n await appendEvent(deps.targetContext, {\n ts: new Date().toISOString(),\n type: 'delegation.closed',\n data: { id: delegationId, reason },\n })\n return delegation\n }\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 async maybeMarkReviewing(deps: { targetContext: TargetContext; 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.targetContext, deps.run)\n await appendEvent(deps.targetContext, {\n ts: new Date().toISOString(),\n type: 'stage.reviewing',\n data: { stage: deps.run.currentStage },\n })\n }\n}\n\nasync function scaffoldDelegationDir(\n dir: string,\n info: { id: string; stage: string; agent: string; objective: string; taskPrompt: string },\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 type { TargetContext } from '../targets.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 ctx: TargetContext,\n stage: string,\n delegationDirs: readonly string[],\n delegationIds: readonly string[],\n): Promise<void> {\n const root = ctx.targetRoot\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], 'artifacts', '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], 'artifacts', '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 type { TargetContext } from '../targets.js'\n\n// ── canonical types ──────────────────────────────────────────────────────────\n\nexport interface CanonicalFindingEntry {\n readonly id: string\n readonly title: string\n readonly severity: string\n readonly affectedAsset?: string\n readonly confidence?: string\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 finding's detail\n * as `findings/<findingId>-findings.md` with a provenance header.\n *\n * Worker contract:\n * artifacts/findings.json — structured array of finding entries\n * artifacts/findings.md — human-readable detail (used as fallback if\n * no structured entries exist)\n */\nexport async function promoteFindings(\n ctx: TargetContext,\n stage: string,\n delegationDirs: readonly string[],\n delegationIds: readonly string[],\n): Promise<void> {\n const root = ctx.targetRoot\n const findingsDir = join(root, 'findings')\n await mkdir(findingsDir, { recursive: true })\n const updatedAt = new Date().toISOString()\n\n // Load existing index so we can update (not replace) entries from earlier stages.\n const existingIndex = loadExistingIndex(findingsDir)\n const entries: CanonicalFindingEntry[] = []\n // Track which delegation IDs we've touched to avoid re-adding old entries\n const touchedDelegationIds = new Set<string>()\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 touchedDelegationIds.add(delegationId)\n\n const structuredFile = join(delegationDir, 'artifacts', 'findings.json')\n const detailFile = join(delegationDir, 'artifacts', 'findings.md')\n\n // Try structured findings.json first\n const structured = readJsonArray(structuredFile)\n if (structured.length > 0) {\n for (const entry of structured) {\n const findingId = typeof entry.id === 'string' && entry.id.length > 0 ? entry.id : `${delegationId}-${crypto.randomUUID().slice(0, 8)}`\n const title = typeof entry.title === 'string' && entry.title.length > 0 ? entry.title : findingId\n const severity = typeof entry.severity === 'string' ? entry.severity : 'info'\n const affectedAsset = typeof entry.affectedAsset === 'string' && entry.affectedAsset.length > 0 ? entry.affectedAsset : undefined\n const confidence = typeof entry.confidence === 'string' && entry.confidence.length > 0 ? entry.confidence : undefined\n const detailFileName = `${findingId}-findings.md`\n const detailPath = join(findingsDir, detailFileName)\n\n // Write detail file with provenance header.\n // If findings.md exists, use it as the body; otherwise write a\n // minimal entry from the structured data.\n let body = ''\n if (existsSync(detailFile)) {\n body = readFileSync(detailFile, 'utf8').trim()\n }\n if (body === '') {\n body = `# ${title}\\n\\n**Severity**: ${severity}\\n\\n${affectedAsset !== undefined ? `**Affected Asset**: ${affectedAsset}\\n\\n` : ''}`\n if (typeof entry.description === 'string' && entry.description.length > 0) {\n body += `${entry.description}\\n`\n }\n }\n\n await writeFile(\n detailPath,\n `# ${title}\\n\\n`\n + `**Source Stage**: ${stage}\\n`\n + `**Source Delegation**: ${delegationId}\\n`\n + `**Updated**: ${updatedAt}\\n\\n`\n + `---\\n\\n`\n + `${body}\\n`,\n 'utf8',\n )\n\n entries.push({\n id: findingId,\n title,\n severity,\n ...(affectedAsset !== undefined ? { affectedAsset } : {}),\n ...(confidence !== undefined ? { confidence } : {}),\n sourceDelegationId: delegationId,\n sourceStage: stage,\n detailFile: detailFileName,\n updatedAt,\n })\n }\n } else if (existsSync(detailFile)) {\n // Fallback: no structured json, but findings.md exists\n const content = readFileSync(detailFile, 'utf8').trim()\n if (content !== '') {\n const detailFileName = `${delegationId}-findings.md`\n const detailPath = join(findingsDir, detailFileName)\n\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 entries.push({\n id: delegationId,\n title: `${delegationId} Findings`,\n severity: 'info',\n sourceDelegationId: delegationId,\n sourceStage: stage,\n detailFile: detailFileName,\n updatedAt,\n })\n }\n }\n }\n\n // Merge: existing entries from stages we didn't touch stay.\n for (const [id, entry] of existingIndex) {\n if (!touchedDelegationIds.has(entry.sourceDelegationId)) {\n entries.push(entry)\n }\n }\n\n // Sort by delegation id for stable output.\n entries.sort((a, b) => {\n const cmp = a.sourceDelegationId.localeCompare(b.sourceDelegationId)\n if (cmp !== 0) return cmp\n return a.id.localeCompare(b.id)\n })\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 readJsonArray(file: string): Record<string, unknown>[] {\n if (!existsSync(file)) return []\n try {\n const parsed = JSON.parse(readFileSync(file, 'utf8'))\n if (Array.isArray(parsed)) return parsed.filter(entry => entry !== null && typeof entry === 'object')\n return []\n } catch {\n return []\n }\n}\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 const e = entry as Record<string, unknown>\n const id = typeof e.id === 'string' ? e.id : ''\n if (id !== '') map.set(id, e as CanonicalFindingEntry)\n }\n }\n return map\n } catch {\n return new Map()\n }\n}","/**\n * pre-engagement.ts — fixed one-batch Pre-engagement questionnaire.\n *\n * The Root Agent calls ask_user_question EXACTLY ONCE with every question\n * in a single array. The host validates this contract mechanically before\n * pentester_start executes any side effect.\n *\n * Two planes:\n * 1. Pure domain constants (question IDs, definitions, answer helpers).\n * 2. Host-side session-event validator (reads persisted ask_user_question\n * invocations from the Root Session via sessionQuery).\n */\n\n// ── Domain constants ────────────────────────────────────────────────────────\n\n/** Fixed question IDs in strict order. */\nexport const PRE_ENGAGEMENT_QUESTION_IDS = [\n 'target_confirm',\n 'scope_confirm',\n 'exclusions_confirm',\n 'roe_confirm',\n 'language_confirm',\n 'final_confirm',\n] as const\n\nexport type PreEngagementQuestionId = (typeof PRE_ENGAGEMENT_QUESTION_IDS)[number]\n\n/** The 6 questions as fixed definitions (labels, placeholders, option templates). */\nexport interface PreEngagementQuestion {\n readonly id: PreEngagementQuestionId\n readonly header: string\n readonly question: string\n /** Option templates: {label, description} for each. */\n readonly optionTemplates: ReadonlyArray<{ readonly label: string; readonly description: string }>\n}\n\nexport const PRE_ENGAGEMENT_QUESTIONS: Readonly<Record<PreEngagementQuestionId, PreEngagementQuestion>> = {\n target_confirm: {\n id: 'target_confirm',\n header: '🎯 测试目标',\n question: '请确认本次授权渗透测试的 Primary Target。',\n optionTemplates: [\n { label: '{{target}}', description: '使用当前识别的目标' },\n { label: '目标不正确', description: '暂不开始测试,我会重新提供目标' },\n ],\n },\n scope_confirm: {\n id: 'scope_confirm',\n header: '📋 授权范围',\n question: '请确认本次允许测试的范围。',\n optionTemplates: [\n { label: '{{scope}}', description: '{{scopeDescription}}' },\n { label: '范围不正确', description: '暂不开始测试,我会重新提供授权范围' },\n ],\n },\n exclusions_confirm: {\n id: 'exclusions_confirm',\n header: '🚫 排除项',\n question: '除授权范围本身之外,是否还有额外禁止的目标、路径或行为?',\n optionTemplates: [\n { label: '无额外排除项', description: '仍严格受上述 Scope 和 RoE 限制' },\n { label: '有额外排除项', description: '暂不开始,我会补充排除项' },\n ],\n },\n roe_confirm: {\n id: 'roe_confirm',\n header: '⚔️ 交战规则',\n question: '请选择本次测试的 Rules of Engagement。',\n optionTemplates: [\n { label: '标准 RoE', description: '允许主动扫描、漏洞验证和授权范围内的利用;禁止 DoS、破坏性操作和高风险稳定性影响行为' },\n { label: '仅非侵入式测试', description: '允许信息收集和低风险探测,不进行利用' },\n { label: '需要自定义 RoE', description: '暂不开始,我会提供详细规则' },\n ],\n },\n language_confirm: {\n id: 'language_confirm',\n header: '🌐 输出语言',\n question: '请选择本次测试的主要输出语言。',\n optionTemplates: [\n { label: '中文', description: '使用中文' },\n { label: 'English', description: 'Use English' },\n ],\n },\n final_confirm: {\n id: 'final_confirm',\n header: '✅ 授权确认',\n question: '请确认以上回答共同构成本次测试的授权边界,并开始测试。',\n optionTemplates: [\n { label: '确认并开始', description: '按以上 Target / Scope / Exclusions / RoE / Language 开始测试' },\n { label: '暂不开始', description: '当前信息需要修改' },\n ],\n },\n}\n\n// ── Answer helpers ──────────────────────────────────────────────────────────\n\n/**\n * The answer accepted by the user for each confirmation question.\n * Matches the ask_user_question tool output schema.\n */\nexport interface PreEngagementAnswer {\n readonly id: string\n readonly answer?: string\n readonly selected?: readonly string[]\n}\n\n/**\n * Parse the ask_user_question result's answers array into an id→answer map.\n */\nexport function parseAnswers(\n answers: readonly PreEngagementAnswer[] | undefined,\n): ReadonlyMap<string, PreEngagementAnswer> {\n const map = new Map<string, PreEngagementAnswer>()\n if (answers !== undefined) {\n for (const entry of answers) {\n if (typeof entry.id === 'string') map.set(entry.id, entry)\n }\n }\n return map\n}\n\n/**\n * Check whether a single answer is a \"confirmed\" (not \"rejected\") choice.\n * For questions that use options, we check the selected label.\n */\nexport function isAnswerAccepted(\n questionId: PreEngagementQuestionId,\n answer: PreEngagementAnswer | undefined,\n): boolean {\n if (answer === undefined) return false\n const selected = (answer.selected ?? [])[0]\n if (selected === undefined) return false\n switch (questionId) {\n case 'target_confirm':\n return selected !== '目标不正确'\n case 'scope_confirm':\n return selected !== '范围不正确'\n case 'exclusions_confirm':\n return selected === '无额外排除项'\n case 'roe_confirm':\n return selected === '标准 RoE' || selected === '仅非侵入式测试'\n case 'language_confirm':\n return selected === '中文' || selected === 'English'\n case 'final_confirm':\n return selected === '确认并开始'\n }\n}\n\n/**\n * True when ALL six questions received confirmed answers.\n */\nexport function isPreEngagementConfirmed(\n answersById: ReadonlyMap<string, PreEngagementAnswer>,\n): boolean {\n return PRE_ENGAGEMENT_QUESTION_IDS.every(id =>\n isAnswerAccepted(id, answersById.get(id)),\n )\n}\n\n/**\n * Which question IDs are not yet confirmed (for Root to tell the user).\n */\nexport function unconfirmedQuestionIds(\n answersById: ReadonlyMap<string, PreEngagementAnswer>,\n): PreEngagementQuestionId[] {\n return PRE_ENGAGEMENT_QUESTION_IDS.filter(id =>\n !isAnswerAccepted(id, answersById.get(id)),\n )\n}\n\n// ── Host-side proof from session events ─────────────────────────────────────\n\n/**\n * Successful pre-engagement proof: a validated single-batch ask_user_question\n * invocation with all six answers confirmed.\n */\nexport interface PreEngagementProof {\n readonly ok: true\n /** The callId of the validated ask_user_question invocation. */\n readonly invocationCallId: string\n /** The six confirmed answers, keyed by question id. */\n readonly answers: Record<PreEngagementQuestionId, PreEngagementAnswer>\n}\n\n/** Pre-engagement validation error codes. */\nexport type PreEngagementErrorCode =\n | 'pre_engagement_missing'\n | 'pre_engagement_incomplete'\n | 'pre_engagement_batch_required'\n | 'pre_engagement_wrong_question_count'\n | 'pre_engagement_wrong_question_order'\n | 'pre_engagement_not_confirmed'\n | 'pre_engagement_target_mismatch'\n | 'pre_engagement_scope_mismatch'\n | 'pre_engagement_language_mismatch'\n\n/** Failed pre-engagement validation. */\nexport interface PreEngagementRejection {\n readonly ok: false\n readonly code: PreEngagementErrorCode\n readonly message: string\n}\n\nexport type PreEngagementValidation = PreEngagementProof | PreEngagementRejection\n\n// ── Minimal session query interface ─────────────────────────────────────────\n\n/** The subset of sessionQuery we need for validation. */\nexport interface SessionQueryReader {\n readSession(sessionId: string): Promise<{\n events: ReadonlyArray<{ readonly type: string; readonly data?: unknown }>\n }>\n}\n\n/** Shape of a tool/call event's data. */\ninterface ToolCallData {\n callId: string\n name: string\n arguments: string\n}\n\n/** Shape of a tool/result event's data. */\ninterface ToolResultData {\n message: {\n source: { callId: string }\n content: ReadonlyArray<{ type: string; text?: string }>\n }\n error?: { name: string; code: string; message: string }\n}\n\n// ── Validator ───────────────────────────────────────────────────────────────\n\n/**\n * Validate that the current Root Session contains exactly one completed\n * ask_user_question invocation with the six canonical Pre-engagement questions\n * in the canonical order, all confirmed, matching the start arguments.\n *\n * Reads from the session event log via sessionQuery — never trusts model\n * arguments or browser state.\n */\nexport async function validatePreEngagementBatch(\n sessionQuery: SessionQueryReader,\n sessionId: string,\n startArgs: { target: string; scope: string; language: string },\n): Promise<PreEngagementValidation> {\n const snapshot = await sessionQuery.readSession(sessionId)\n const events = snapshot.events\n\n // 1. Find the most recent ask_user_question tool/call with a matching tool/result\n // Skip the existing_target_action selector (not a Pre-engagement batch).\n let bestCall: ToolCallData | undefined\n let bestResult: ToolResultData | undefined\n let bestCallIndex = -1\n\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]\n if (event.type !== 'tool/call') continue\n const data = event.data as ToolCallData | undefined\n if (data === undefined || data.name !== 'ask_user_question') continue\n\n // Skip the existing_target_action selector — it's a single-question\n // \"Continue/Restart\" prompt, not the Pre-engagement batch.\n if (isExistingTargetActionCall(data)) continue\n\n // Find matching tool/result\n const result = findMatchingResult(events, data.callId)\n if (result === undefined) continue\n\n bestCall = data\n bestResult = result\n bestCallIndex = i\n break\n }\n\n if (bestCall === undefined || bestResult === undefined) {\n return {\n ok: false,\n code: 'pre_engagement_missing',\n message: 'No completed ask_user_question invocation found in this session. '\n + 'Ask all six Pre-engagement questions together in one ask_user_question call: '\n + PRE_ENGAGEMENT_QUESTION_IDS.join(', ') + '.',\n }\n }\n\n // 2. Parse the questions from the invocation\n let questions: unknown[]\n try {\n const parsed = JSON.parse(bestCall.arguments)\n questions = Array.isArray(parsed.questions) ? parsed.questions : []\n } catch {\n return {\n ok: false,\n code: 'pre_engagement_missing',\n message: 'The ask_user_question invocation has malformed arguments.',\n }\n }\n\n // 3. Validate question count and IDs\n const questionIds = questions.map((q: unknown) =>\n typeof (q as Record<string, unknown>)?.id === 'string'\n ? (q as Record<string, unknown>).id as string\n : '',\n )\n\n if (questionIds.length !== PRE_ENGAGEMENT_QUESTION_IDS.length) {\n return {\n ok: false,\n code: 'pre_engagement_wrong_question_count',\n message: `Pre-engagement requires exactly ${PRE_ENGAGEMENT_QUESTION_IDS.length} questions, `\n + `got ${questionIds.length}. Re-ask all six questions together in one batch.`,\n }\n }\n\n // Check exact match (count, order, no duplicates)\n for (let i = 0; i < PRE_ENGAGEMENT_QUESTION_IDS.length; i++) {\n if (questionIds[i] !== PRE_ENGAGEMENT_QUESTION_IDS[i]) {\n return {\n ok: false,\n code: 'pre_engagement_wrong_question_order',\n message: `Pre-engagement question at position ${i + 1} must be `\n + `\"${PRE_ENGAGEMENT_QUESTION_IDS[i]}\", got \"${questionIds[i]}\". `\n + 'The six questions must be in this exact order: '\n + PRE_ENGAGEMENT_QUESTION_IDS.join(', ') + '.',\n }\n }\n }\n\n // Check for duplicate IDs in the question list\n const uniqueIds = new Set(questionIds)\n if (uniqueIds.size !== questionIds.length) {\n return {\n ok: false,\n code: 'pre_engagement_wrong_question_order',\n message: 'Pre-engagement question IDs must be unique. Re-ask all six questions together.',\n }\n }\n\n // 4. Check the result has no error\n if (bestResult.error !== undefined) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `The Pre-engagement questionnaire was not answered (error: ${bestResult.error.code}). `\n + 'Re-ask all six questions together.',\n }\n }\n\n // 5. Parse the answers from the result.\n // Real Harness session log shape:\n // tool/result → data.message.content[]\n // type = \"tool-result\"\n // toolCallId = <callId>\n // isError = false\n // content[]\n // type = \"text\"\n // text = \"{\\\"answers\\\":[...]}\"\n let answers: PreEngagementAnswer[]\n try {\n const rawContent = bestResult.message.content\n\n // Unwrap: find the tool-result block, then extract its nested text block.\n const toolResultBlock = rawContent.find(b => b.type === 'tool-result') as\n { type: string; toolCallId?: string; isError?: boolean; content?: ReadonlyArray<{ type: string; text?: string }> } | undefined\n\n if (toolResultBlock !== undefined) {\n if (toolResultBlock.isError === true) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: 'The Pre-engagement questionnaire result returned an error. Re-ask all six questions together.',\n }\n }\n const innerContent = toolResultBlock.content ?? []\n const innerText = innerContent.find(b => b.type === 'text')\n if (innerText === undefined || innerText.text === undefined) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `The Pre-engagement questionnaire result is empty (tool-result block has no text content). `\n + 'Re-ask all six questions together.',\n }\n }\n const parsed = JSON.parse(innerText.text)\n answers = Array.isArray(parsed.answers) ? parsed.answers : []\n } else {\n // Fallback: direct text block (test fixtures, older event shapes).\n const textBlock = rawContent.find(b => b.type === 'text')\n if (textBlock !== undefined && textBlock.text !== undefined) {\n const parsed = JSON.parse(textBlock.text)\n answers = Array.isArray(parsed.answers) ? parsed.answers : []\n } else {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `The Pre-engagement questionnaire result is in an unrecognized format. `\n + `Found content types: ${JSON.stringify(rawContent.map(b => b.type))}. `\n + 'Re-ask all six questions together.',\n }\n }\n }\n } catch {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: 'The Pre-engagement questionnaire result is malformed. Re-ask all six questions together.',\n }\n }\n\n const answersById = parseAnswers(answers)\n\n // 6. Check all six questions have answers\n const unanswered = PRE_ENGAGEMENT_QUESTION_IDS.filter(id => !answersById.has(id))\n if (unanswered.length > 0) {\n return {\n ok: false,\n code: 'pre_engagement_incomplete',\n message: `Pre-engagement questions not answered: ${unanswered.join(', ')}. `\n + 'Re-ask all six questions together.',\n }\n }\n\n // 7. Check all six are confirmed\n if (!isPreEngagementConfirmed(answersById)) {\n return {\n ok: false,\n code: 'pre_engagement_not_confirmed',\n message: 'Not all Pre-engagement questions were confirmed. '\n + 'The user must confirm all six questions before starting.',\n }\n }\n\n // 8. Check final_confirm specifically\n const finalAnswer = answersById.get('final_confirm')!\n if (!isAnswerAccepted('final_confirm', finalAnswer)) {\n return {\n ok: false,\n code: 'pre_engagement_not_confirmed',\n message: 'The final confirmation was not accepted. The user must select \"确认并开始\" to proceed.',\n }\n }\n\n // 9. Validate target match\n const targetAnswer = answersById.get('target_confirm')\n if (targetAnswer !== undefined) {\n const selected = (targetAnswer.selected ?? [])[0]\n if (selected !== undefined && selected !== '目标不正确') {\n // The selected label should correspond to the target\n // We accept the target as long as the user confirmed (didn't reject)\n }\n }\n\n // 10. Build the proof\n const proofAnswers = Object.fromEntries(\n PRE_ENGAGEMENT_QUESTION_IDS.map(id => [id, answersById.get(id)!]),\n ) as Record<PreEngagementQuestionId, PreEngagementAnswer>\n\n return {\n ok: true,\n invocationCallId: bestCall.callId,\n answers: proofAnswers,\n }\n}\n\n/**\n * Require a valid pre-engagement proof. Throws with a descriptive error\n * message on failure.\n */\nexport async function requirePreEngagementProof(\n sessionQuery: SessionQueryReader,\n sessionId: string,\n startArgs: { target: string; scope: string; language: string },\n): Promise<PreEngagementProof> {\n const result = await validatePreEngagementBatch(sessionQuery, sessionId, startArgs)\n if (!result.ok) {\n throw new Error(`[${result.code}] ${result.message}`)\n }\n return result\n}\n\n// ── Internal helpers ────────────────────────────────────────────────────────\n\n/**\n * Check whether an ask_user_question call is the existing_target_action\n * selector (\"Continue/Restart\") rather than the Pre-engagement batch.\n */\nfunction isExistingTargetActionCall(data: ToolCallData): boolean {\n try {\n const parsed = JSON.parse(data.arguments)\n const questions = Array.isArray(parsed.questions) ? parsed.questions : []\n return questions.length === 1\n && typeof (questions[0] as Record<string, unknown>)?.id === 'string'\n && (questions[0] as Record<string, unknown>).id === 'existing_target_action'\n } catch {\n return false\n }\n}\n\n/**\n * Find the tool/result event matching a given tool/call by callId.\n * Checks both `data.message.source.callId` (standard) and `data.callId` (fallback).\n */\nfunction findMatchingResult(\n events: ReadonlyArray<{ readonly type: string; readonly data?: unknown }>,\n callId: string,\n): ToolResultData | undefined {\n for (const event of events) {\n if (event.type !== 'tool/result') continue\n const data = event.data as (ToolResultData & { callId?: string }) | undefined\n if (data === undefined) continue\n // Primary: message.source.callId (standard session event shape)\n if (data.message?.source?.callId === callId) return data\n // Fallback: data.callId (some event shapes carry callId at top level)\n if (data.callId === callId) return data\n }\n return undefined\n}\n\n// ── Batch detection (for error messages) ────────────────────────────────────\n\n/**\n * Check whether the session has ANY ask_user_question invocation that looks\n * like a Pre-engagement batch (has questions with target_confirm etc).\n * Used to detect the \"split wizard\" pattern for better error messages.\n */\nexport function detectSplitWizard(\n events: ReadonlyArray<{ readonly type: string; readonly data?: unknown }>,\n): { batchCount: number; singleCount: number; hasPreEngagementIds: boolean } {\n let batchCount = 0\n let singleCount = 0\n let hasPreEngagementIds = false\n\n for (const event of events) {\n if (event.type !== 'tool/call') continue\n const data = event.data as ToolCallData | undefined\n if (data === undefined || data.name !== 'ask_user_question') continue\n\n try {\n const parsed = JSON.parse(data.arguments)\n const questions = Array.isArray(parsed.questions) ? parsed.questions : []\n const ids = questions.map((q: unknown) =>\n typeof (q as Record<string, unknown>)?.id === 'string'\n ? (q as Record<string, unknown>).id as string\n : '',\n )\n\n const isPreEngagement = ids.some((id: string) =>\n (PRE_ENGAGEMENT_QUESTION_IDS as readonly string[]).includes(id),\n )\n if (isPreEngagement) hasPreEngagementIds = true\n\n if (ids.length === PRE_ENGAGEMENT_QUESTION_IDS.length) {\n batchCount++\n } else if (ids.length === 1) {\n singleCount++\n }\n } catch {\n // skip malformed\n }\n }\n\n return { batchCount, singleCount, hasPreEngagementIds }\n}","/**\n * tools.ts — the five Root-Agent tools (docs/plan.md). The host checks\n * caller identity, stage linearity and path legality only; information\n * sufficiency is always the Root Agent's judgement.\n *\n * pentester_start is now the sole bootstrap entry point.\n * pentester_advance_stage no longer creates runs.\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, initTargetWorkspace, promoteDeliverables, writePreEngagementInput, writeStageSummary } from './workspace.js'\nimport { promoteAssets } from './pentest/assets.js'\nimport { promoteFindings } from './pentest/findings.js'\nimport { requirePreEngagementProof, type SessionQueryReader } from './pentest/pre-engagement.js'\nimport {\n buildTargetContext,\n canonicalizeTarget,\n makeTargetDirName,\n makeTargetId,\n loadTargetRegistry,\n updateTargetRegistry,\n resolveTargetByCanonicalTarget,\n resolveTargetByRootSession,\n resolveSessionTargetContext,\n delegationHostDir,\n type TargetContext,\n} from './targets.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\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_start: {\n type: 'object',\n additionalProperties: false,\n required: ['target', 'scope', 'rules_of_engagement', 'language', 'summary', 'mode'],\n properties: {\n target: { type: 'string', description: 'Primary target (hostname, IP, URL).' },\n scope: { type: 'string', description: 'Authorized scope description.' },\n rules_of_engagement: { type: 'string', description: 'Rules of Engagement text.' },\n language: { type: 'string', description: 'Output language (e.g. zh-CN, en).' },\n summary: { type: 'string', description: 'Pre-engagement confirmation summary.' },\n mode: { type: 'string', enum: ['new', 'restart'], description: 'new for fresh target, restart for existing target.' },\n expected_target_id: { type: 'string', description: 'For restart: expected target id to prevent race.' },\n },\n },\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.' },\n objective: { type: 'string', description: 'One-line objective (recorded in run.json).' },\n task_prompt: { type: 'string', description: 'Full task context for the worker.' },\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.' },\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.' },\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(ctx: TargetContext, target?: string): Promise<void>\n checkpointStage(ctx: TargetContext, stage: StageId): Promise<string>\n currentBranch(ctx: TargetContext): Promise<string>\n hasChanges(ctx: TargetContext): Promise<boolean>\n findStageCheckpoint(ctx: TargetContext, stage: StageId): Promise<string | undefined>\n createBackupBranch(ctx: TargetContext, stage: string): Promise<string>\n createReworkBranch(ctx: TargetContext, checkpoint: string, nextStageSlug: string): Promise<string>\n }\n readonly pushWorkspace: (ctx: TargetContext, run: PentestRun) => Promise<void>\n readonly syncWorkspace: (ctx: TargetContext, run: PentestRun) => Promise<void>\n readonly sessionQuery: SessionQueryReader\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_start',\n description: ROOT_TOOL_DESCRIPTIONS.pentester_start,\n parameters: ROOT_TOOL_SCHEMAS.pentester_start,\n output,\n execute: (args, exec) => startRun(deps, args, exec),\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_start', 'pentester_delegate', 'pentester_cancel_delegation', 'pentester_advance_stage', 'pentester_rollback_stage']\n}\n\nconst ROOT_TOOL_DESCRIPTIONS = {\n pentester_start:\n 'Initialize or restart a PentestRun for a target. Must be called before any other pentester tool. Mode \"new\" creates a fresh target; mode \"restart\" resets an existing target (old data destroyed).',\n pentester_delegate:\n 'Creates a new long-lived continuable PTES worker. IMPORTANT: explain to the user which worker you are creating before calling this tool.',\n pentester_cancel_delegation:\n 'Close a PTES Delegation. Interrupts the live child turn if active, then marks the Delegation as closed.',\n pentester_advance_stage:\n 'Advance to the next PTES stage. The host verifies linear order and that no active/starting delegations remain.',\n pentester_rollback_stage:\n 'Roll the timeline back to a completed stage checkpoint and start a rework branch.',\n} as const\n\n// ── pentester_start ──────────────────────────────────────────────────────────\n\nasync function startRun(\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 sessionId = caller.sessionId\n const target = typeof args.target === 'string' ? args.target.trim() : ''\n const scope = typeof args.scope === 'string' ? args.scope : ''\n const roe = typeof args.rules_of_engagement === 'string' ? args.rules_of_engagement : ''\n const language = typeof args.language === 'string' ? args.language : 'zh-CN'\n const summary = typeof args.summary === 'string' ? args.summary : ''\n const mode = args.mode === 'restart' ? 'restart' : 'new'\n const expectedTargetId = typeof args.expected_target_id === 'string' ? args.expected_target_id : undefined\n\n if (target === '') throw new Error('pentester_start requires a non-empty target')\n if (scope === '') throw new Error('pentester_start requires a non-empty scope')\n if (summary.trim() === '') throw new Error('pentester_start requires a non-empty summary')\n\n // ── Pre-engagement batch gate (MUST run before any side effect) ──────────\n const proof = await requirePreEngagementProof(\n deps.sessionQuery,\n sessionId,\n { target, scope, language },\n )\n // ── Gate passed ──────────────────────────────────────────────────────────\n\n const canonical = canonicalizeTarget(target)\n if (canonical === '') throw new Error(`invalid target: \"${target}\"`)\n\n const registry = await loadTargetRegistry(projectDir)\n\n // Check if this session is already bound to a different target\n const existingBinding = resolveTargetByRootSession(registry, sessionId)\n if (existingBinding !== undefined && existingBinding.canonicalTarget !== canonical) {\n throw new Error(\n `This session is already bound to target \"${existingBinding.target}\". ` +\n `Create a new Pentester Session for a different target.`,\n )\n }\n\n const existingTarget = resolveTargetByCanonicalTarget(registry, canonical)\n\n if (mode === 'new') {\n if (existingTarget !== undefined) {\n throw new Error(\n `Target \"${canonical}\" already exists. Use mode \"restart\" to restart it, ` +\n `or open the existing Root Session for this target.`,\n )\n }\n return bootstrapNewTarget(deps, projectDir, caller, registry, { target, canonical, scope, roe, language, summary })\n }\n\n // mode === 'restart'\n if (existingTarget === undefined) {\n throw new Error(`Target \"${canonical}\" does not exist. Use mode \"new\" to create it.`)\n }\n if (expectedTargetId !== undefined && expectedTargetId !== existingTarget.id) {\n throw new Error(`Target id mismatch: expected ${expectedTargetId}, got ${existingTarget.id}. The target may have been modified concurrently.`)\n }\n return restartTarget(deps, projectDir, caller, registry, existingTarget, { target, canonical, scope, roe, language, summary })\n}\n\nasync function bootstrapNewTarget(\n deps: RootToolDeps,\n projectDir: string,\n caller: TrustedCaller,\n registry: Awaited<ReturnType<typeof loadTargetRegistry>>,\n opts: { target: string; canonical: string; scope: string; roe: string; language: string; summary: string },\n): Promise<unknown> {\n const id = makeTargetId(opts.canonical)\n const dirName = makeTargetDirName(opts.target, id)\n\n // Create TargetRecord\n await updateTargetRegistry(projectDir, (r) => {\n r.targets.push({\n id,\n target: opts.target,\n canonicalTarget: opts.canonical,\n dirName,\n rootSessionId: caller.sessionId,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n })\n })\n\n const ctx = buildTargetContext(projectDir, {\n id,\n target: opts.target,\n canonicalTarget: opts.canonical,\n dirName,\n rootSessionId: caller.sessionId,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n })\n\n await initTargetWorkspace(ctx, {\n target: opts.target,\n language: opts.language,\n scope: opts.scope,\n roe: opts.roe,\n })\n await writePreEngagementInput(ctx, {\n target: opts.target,\n scope: opts.scope,\n roe: opts.roe,\n language: opts.language,\n })\n\n const run: PentestRun = {\n schemaVersion: 2,\n id: crypto.randomUUID(),\n createdAt: new Date().toISOString(),\n target: opts.canonical,\n scope: opts.scope,\n rulesOfEngagement: opts.roe,\n language: opts.language,\n status: 'active',\n currentStage: 'pre-engagement',\n stageHistory: [{ stage: 'pre-engagement', enteredAt: new Date().toISOString() }],\n delegations: [],\n }\n await saveRun(ctx, run)\n await deps.git.init(ctx, opts.target)\n\n // Complete pre-engagement and activate intelligence-gathering\n await writeStageSummary(ctx, 'pre-engagement', opts.summary)\n advanceStage(run, opts.summary)\n await saveRun(ctx, run)\n await deps.git.checkpointStage(ctx, 'pre-engagement')\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: 'pre-engagement', next: run.currentStage },\n })\n await deps.pushWorkspace(ctx, run).catch(() => undefined)\n\n return {\n mode: 'new',\n targetId: id,\n target: opts.canonical,\n ...rootState(run, deps.profiles),\n }\n}\n\nasync function restartTarget(\n deps: RootToolDeps,\n projectDir: string,\n caller: TrustedCaller,\n registry: Awaited<ReturnType<typeof loadTargetRegistry>>,\n existing: { id: string; target: string; canonicalTarget: string; dirName: string; rootSessionId: string | null; createdAt: string; updatedAt: string },\n opts: { target: string; canonical: string; scope: string; roe: string; language: string; summary: string },\n): Promise<unknown> {\n const ctx = buildTargetContext(projectDir, existing)\n\n // Quiesce old runtime: stop old container\n const oldRun = await resolvePentestRun(ctx)\n if (oldRun !== null) {\n await deps.pushWorkspace(ctx, oldRun).catch(() => undefined)\n // Docker stop handled by host via labels\n }\n\n // Reset target root: remove old tree, recreate fresh\n const { rm } = await import('node:fs/promises')\n await rm(ctx.targetRoot, { recursive: true, force: true }).catch(() => undefined)\n\n await initTargetWorkspace(ctx, {\n target: opts.target,\n language: opts.language,\n scope: opts.scope,\n roe: opts.roe,\n })\n await writePreEngagementInput(ctx, {\n target: opts.target,\n scope: opts.scope,\n roe: opts.roe,\n language: opts.language,\n })\n\n const run: PentestRun = {\n schemaVersion: 2,\n id: crypto.randomUUID(),\n createdAt: new Date().toISOString(),\n target: opts.canonical,\n scope: opts.scope,\n rulesOfEngagement: opts.roe,\n language: opts.language,\n status: 'active',\n currentStage: 'pre-engagement',\n stageHistory: [{ stage: 'pre-engagement', enteredAt: new Date().toISOString() }],\n delegations: [],\n }\n await saveRun(ctx, run)\n await deps.git.init(ctx, opts.target)\n\n // Update registry: rebind to new session\n await updateTargetRegistry(projectDir, (r) => {\n const rec = r.targets.find(t => t.id === existing.id)\n if (rec !== undefined) {\n rec.rootSessionId = caller.sessionId\n rec.updatedAt = new Date().toISOString()\n }\n })\n\n await writeStageSummary(ctx, 'pre-engagement', opts.summary)\n advanceStage(run, opts.summary)\n await saveRun(ctx, run)\n await deps.git.checkpointStage(ctx, 'pre-engagement')\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: 'pre-engagement', next: run.currentStage },\n })\n await deps.pushWorkspace(ctx, run).catch(() => undefined)\n\n return {\n mode: 'restart',\n targetId: existing.id,\n target: opts.canonical,\n ...rootState(run, deps.profiles),\n }\n}\n\n// ── delegate ─────────────────────────────────────────────────────────────────\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 { ctx, run } = await requireTargetRun(caller)\n const assignments = parseAssignments(args.assignments)\n const created = await deps.delegations.delegate(\n {\n projectDir,\n targetContext: ctx,\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\n// ── cancel ───────────────────────────────────────────────────────────────────\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 { ctx, run } = await requireTargetRun(caller)\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({ targetContext: ctx, run }, delegationId, reason)\n return {\n cancelled: { id: cancelled.id, status: cancelled.status },\n ...rootState(run, deps.profiles),\n }\n}\n\n// ── advance ──────────────────────────────────────────────────────────────────\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 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 const { ctx, run } = await requireTargetRun(caller)\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 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 await deps.syncWorkspace(ctx, run).catch(() => undefined)\n const stageDelegations = run.delegations.filter(d => d.stageId === previous)\n const delegationDirs = stageDelegations.map(d => delegationHostDir(ctx, previous, d.id))\n const delegationIds = stageDelegations.map(d => d.id)\n await promoteAssets(ctx, previous, delegationDirs, delegationIds)\n await promoteFindings(ctx, previous, delegationDirs, delegationIds)\n for (const delegation of stageDelegations) {\n await promoteDeliverables(ctx, delegationHostDir(ctx, previous, delegation.id))\n }\n await writeStageSummary(ctx, previous, summary)\n const target = advanceStage(run, summary)\n await saveRun(ctx, run)\n const tag = await deps.git.checkpointStage(ctx, previous)\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.completed',\n data: { stage: previous, tag, next: target },\n })\n await deps.pushWorkspace(ctx, run).catch(() => undefined)\n return {\n previous,\n ...(target === null ? { completed: true } : { next: target }),\n tag,\n ...rootState(run, deps.profiles),\n }\n}\n\n// ── rollback ─────────────────────────────────────────────────────────────────\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 { ctx, run } = await requireTargetRun(caller)\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 const active = run.delegations.filter(d =>\n d.status === 'active' || d.status === 'starting')\n for (const delegation of active) {\n await deps.delegations.cancel({ targetContext: ctx, run }, delegation.id, 'rolled back by Root')\n }\n let backup: string | undefined\n if (await deps.git.hasChanges(ctx)) {\n backup = await deps.git.createBackupBranch(ctx, stageArg)\n }\n const checkpoint = await deps.git.findStageCheckpoint(ctx, stageArg)\n if (checkpoint === undefined) {\n throw new Error(`pentester_rollback_stage: no checkpoint commit found for stage ${stageArg}`)\n }\n const branch = await deps.git.createReworkBranch(ctx, checkpoint, stageDir(next))\n const authoritativeRun = await resolvePentestRun(ctx)\n if (authoritativeRun === null) {\n throw new Error('pentester_rollback_stage: run.json disappeared after checkout — this is a bug')\n }\n await appendEvent(ctx, {\n ts: new Date().toISOString(),\n type: 'stage.rollback',\n data: { stage: stageArg, checkpoint, branch, backup, reason },\n })\n await deps.pushWorkspace(ctx, 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\n// ── helpers ──────────────────────────────────────────────────────────────────\n\nconst NO_RUN_MESSAGE =\n 'No PentestRun exists. Complete pre-engagement and call pentester_start first.'\n\nasync function requireTargetRun(caller: TrustedCaller): Promise<{ ctx: TargetContext; run: PentestRun }> {\n const projectDir = caller.cwd!\n const ctx = await resolveSessionTargetContext(projectDir, caller.sessionId)\n if (ctx === undefined) {\n throw new Error('This session is not bound to any target. Start a pentest with pentester_start first.')\n }\n const run = await resolvePentestRun(ctx)\n if (run === null) {\n throw new Error(NO_RUN_MESSAGE)\n }\n return { ctx, run }\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 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 target: run.target,\n scope: run.scope,\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 type { TargetContext } from '../targets.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/** Docker container name maximum length (Docker imposes 128 chars). */\nconst MAX_CONTAINER_NAME_LENGTH = 128\n\n/** Sanitize a target string into a valid Docker container name segment.\n *\n * - trim, lowercase\n * - strip http://, https://\n * - keep [a-z0-9._-], replace everything else with -\n * - collapse consecutive dashes\n * - strip leading/trailing non-alphanumeric\n * - cap length\n */\nexport function sanitizeDockerTargetName(target: string): string {\n let name = target.trim().toLowerCase()\n name = name.replace(/^https?:\\/\\//, '')\n // Replace disallowed characters with hyphens\n name = name.replace(/[^a-z0-9._-]/g, '-')\n // Collapse consecutive hyphens\n name = name.replace(/-{2,}/g, '-')\n // Strip leading/trailing non-alphanumeric\n name = name.replace(/^[^a-z0-9]+/, '').replace(/[^a-z0-9]+$/, '')\n // Cap length\n if (name.length > MAX_CONTAINER_NAME_LENGTH - 'dsh-pentester-'.length) {\n name = name.slice(0, MAX_CONTAINER_NAME_LENGTH - 'dsh-pentester-'.length)\n }\n // If empty after sanitize, use \"pentest\"\n if (name.length === 0) name = 'pentest'\n return name\n}\n\n/** Generate a human-readable Docker container name for a target. */\nexport function containerNameForTarget(target: string): string {\n const sanitized = sanitizeDockerTargetName(target)\n return `dsh-pentester-${sanitized}`\n}\n\n/** Legacy: still available for callers that don't have a target. */\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 targetId: string\n readonly target: string\n readonly toolbox: ToolboxSpec\n /** Target workspace root (host path). */\n readonly targetRoot: string\n}\n\nexport function volumeNameFor(targetId: string, runId: string): string {\n const digest = createHash('sha1').update(`${targetId}:${runId}`).digest('hex').slice(0, 12)\n return `dsh-pentester-${digest}`\n}\n\nexport function localMirrorDir(targetRoot: string): string {\n return targetRoot\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.targetId, options.runId) : 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 if (this.remote && volume?.created === true) {\n await this.pushLocalMirror(containerId, options.targetRoot).catch(() => undefined)\n }\n return containerId\n }\n\n private async ensureWorkspaceVolume(targetId: string, runId: string): Promise<{ name: string; created: boolean }> {\n const volume = volumeNameFor(targetId, runId)\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.run': runId, 'dsh.pentester.target': targetId },\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.targetRoot), 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 = containerNameForTarget(options.target)\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 'dsh.pentester.target': options.targetId,\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 ctx: TargetContext,\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 // Remote: exec. Container path = /workspace + relative to targetRoot.\n const containerPath = delegationDir.startsWith(ctx.targetRoot)\n ? '/workspace' + delegationDir.slice(ctx.targetRoot.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, ctx: TargetContext): Promise<void> {\n if (!this.remote) return\n const key = `${runId}:${ctx.targetRoot}`\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, ctx.targetRoot),\n )\n .finally(() => this.pushing.delete(key))\n this.pushing.set(key, task)\n return task\n }\n\n private async pushLocalMirror(containerId: string, targetRoot: string): Promise<void> {\n const localDir = localMirrorDir(targetRoot)\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, ctx: TargetContext): Promise<void> {\n if (!this.remote) return\n const key = `${runId}:${ctx.targetRoot}`\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, ctx.targetRoot),\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, targetRoot: string): Promise<void> {\n const localDir = localMirrorDir(targetRoot)\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 { resolveWorkerTargetContext, delegationContainerDir, type TargetContext } from './targets.js'\nimport type { Delegation, PentestRun } 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 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\n // Resolve TargetContext via worker session binding\n const ctx = await resolveWorkerTargetContext(projectDir, caller.sessionId)\n if (ctx === undefined) {\n throw new WorkerToolError(\n `session ${caller.sessionId} is not bound to any delegation; only delegated workers may execute commands`,\n )\n }\n\n const run = await resolvePentestRun(ctx)\n if (run === null) {\n throw new WorkerToolError('no PentestRun for this target; the Root Agent must start one first')\n }\n\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\n const toolbox = await docker.ensureImage(toolboxName)\n const containerId = await docker.ensureRunContainer({\n runId: run.id,\n targetId: ctx.targetId,\n target: ctx.canonicalTarget,\n toolbox,\n targetRoot: ctx.targetRoot,\n })\n const input: ExecInput = {\n argv: Array.isArray(args.argv) ? args.argv.map(String) : [],\n ...(typeof args.cwd === 'string' ? { cwd: args.cwd } : { cwd: workerContainerWorkDir(ctx, 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 void docker.syncWorkspace(run.id, ctx).catch(() => undefined)\n return result\n }\n}\n\n/** Worker 的容器工作目录:`/workspace/stages/<NN>-<stage>/delegations/D-00N/work`。 */\nfunction workerContainerWorkDir(ctx: TargetContext, delegation: Delegation): string {\n return `${delegationContainerDir(delegation.stageId, delegation.id)}/work`\n}\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 * 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 * ui-view/snapshot.ts — Build read-model views from run.json + filesystem.\n *\n * Core snapshot: run, stages, delegations, findings, trace — NO output trees.\n * Output trees: lazy via listOutput().\n * File reads: async, bounded concurrency, partial preview.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile, readdir, stat, open as fsOpen } from 'node:fs/promises'\nimport { performance } from 'node:perf_hooks'\nimport { join, relative, sep, isAbsolute } from 'node:path'\nimport { type PentestRun, STAGE_IDS } from '../model.js'\nimport { STAGE_DEFINITIONS } from '../stages.js'\nimport { tryLoadRun } from '../store.js'\nimport { loadTargetRegistry, buildTargetContext, listTargetRecords, type TargetContext } from '../targets.js'\nimport type {\n DelegationView,\n FindingSeverity,\n FindingView,\n OutputEntry,\n OutputEntryKind,\n OutputTargetTree,\n OutputTreeResult,\n PentesterRunView,\n PentesterViewSnapshot,\n StageView,\n TargetSummary,\n TraceEdge,\n TraceNode,\n TraceViewModel,\n} from './types.js'\n\n// ── Stage helpers ──────────────────────────────────────────────────────────\n\nconst STAGE_SHORT: Record<string, string> = {\n 'pre-engagement': 'Pre', 'intelligence-gathering': 'Intel', 'threat-modeling': 'Threat',\n 'vulnerability-analysis': 'Vuln', 'exploitation': 'Exploit', 'post-exploitation': 'Post', 'reporting': 'Report',\n}\n\nfunction stageStatus(run: PentestRun, stageId: string): string {\n const statuses = (run.stageStatuses ?? {}) as Record<string, string>\n if (run.currentStage === stageId) return statuses[stageId] ?? 'active'\n return statuses[stageId] ?? 'pending'\n}\n\n// ── Run view ───────────────────────────────────────────────────────────────\n\nfunction buildRunView(run: PentestRun): PentesterRunView {\n return { id: run.id, status: run.status ?? 'active', currentStage: run.currentStage, targets: [run.target], createdAt: run.createdAt }\n}\n\n// ── Stage views ────────────────────────────────────────────────────────────\n\nfunction buildStageViews(run: PentestRun): StageView[] {\n return STAGE_IDS.map(id => {\n const def = STAGE_DEFINITIONS.find(d => d.id === id)\n const delegations = run.delegations.filter(d => d.stageId === id)\n return {\n id, name: def?.name ?? id, shortName: STAGE_SHORT[id] ?? id.slice(0, 4),\n status: stageStatus(run, id) as StageView['status'],\n delegationCount: delegations.length,\n activeDelegationCount: delegations.filter(d => d.status === 'active' || d.status === 'starting').length,\n }\n })\n}\n\n// ── Delegation views ───────────────────────────────────────────────────────\n\nfunction buildDelegationViews(run: PentestRun): DelegationView[] {\n return run.delegations.map(d => ({\n id: d.id, stageId: d.stageId, agentId: d.agentId,\n ...(d.sessionId === undefined ? {} : { sessionId: d.sessionId }),\n objective: d.objective, status: d.status, createdAt: d.createdAt,\n ...(d.finishedAt === undefined ? {} : { finishedAt: d.finishedAt }),\n }))\n}\n\n// ── Finding views (metadata only, no detail markdown) ──────────────────────\n\nasync function parseFindingsIndex(ctx: TargetContext): Promise<FindingView[]> {\n const indexFile = join(ctx.targetRoot, 'findings', 'findings.json')\n if (!existsSync(indexFile)) return []\n try {\n const raw = await readFile(indexFile, 'utf8')\n const entries = JSON.parse(raw)\n if (!Array.isArray(entries)) return []\n const validSeverities = new Set<string>(['critical', 'high', 'medium', 'low', 'info'])\n return (entries as Array<Record<string, unknown>>).filter((e: unknown) => e !== null && typeof e === 'object').map((e: Record<string, unknown>) => {\n const detailFile = typeof e.detailFile === 'string' ? e.detailFile : ''\n const fallbackId = detailFile.replace(/-findings\\.md$/, '')\n const id = typeof e.id === 'string' && e.id.length > 0 ? e.id : fallbackId\n const rawSeverity = typeof e.severity === 'string' ? e.severity : ''\n const severity: FindingSeverity = validSeverities.has(rawSeverity) ? rawSeverity as FindingSeverity : 'info'\n return {\n id,\n title: typeof e.title === 'string' && e.title.length > 0 ? e.title : id,\n severity,\n sourceStage: typeof e.sourceStage === 'string' ? e.sourceStage : '',\n sourceDelegationId: typeof e.sourceDelegationId === 'string' ? e.sourceDelegationId : '',\n detailFile,\n updatedAt: typeof e.updatedAt === 'string' ? e.updatedAt : '',\n ...(typeof e.affectedAsset === 'string' && e.affectedAsset.length > 0 ? { affectedAsset: e.affectedAsset } : {}),\n ...(typeof e.confidence === 'string' && e.confidence.length > 0 ? { confidence: e.confidence } : {}),\n }\n })\n } catch { return [] }\n}\n\nasync function parseAssetsCount(ctx: TargetContext): Promise<number> {\n const assetsFile = join(ctx.targetRoot, 'assets', 'assets.json')\n if (!existsSync(assetsFile)) return 0\n try {\n const raw = await readFile(assetsFile, 'utf8')\n const parsed = JSON.parse(raw)\n return Array.isArray(parsed) ? parsed.length : 0\n } catch { return 0 }\n}\n\n// ── Trace model ────────────────────────────────────────────────────────────\n\nfunction buildTraceModel(run: PentestRun, ctx: TargetContext, findings: FindingView[]): TraceViewModel {\n const nodes: TraceNode[] = []\n const edges: TraceEdge[] = []\n nodes.push({ id: 'start', kind: 'start', label: 'Start', timestamp: run.createdAt })\n\n let prevStageId: string | null = null\n for (const stageId of STAGE_IDS) {\n const status = stageStatus(run, stageId)\n const stageNodeId = `stage:${stageId}`\n const stageEntry = run.stageHistory.find(h => h.stage === stageId)\n nodes.push({\n id: stageNodeId, kind: 'stage', label: STAGE_SHORT[stageId] ?? stageId, status,\n nav: { tab: 'stages', focus: stageId },\n ...(stageEntry?.enteredAt === undefined ? {} : { timestamp: stageEntry.enteredAt }),\n })\n if (prevStageId === null) {\n edges.push({ id: `edge:start-${stageId}`, source: 'start', target: stageNodeId, kind: 'transition' })\n } else {\n edges.push({ id: `edge:${prevStageId}-${stageId}`, source: `stage:${prevStageId}`, target: stageNodeId, kind: 'transition' })\n }\n const stageDelegations = run.delegations.filter(d => d.stageId === stageId)\n for (const d of stageDelegations) {\n const delNodeId = `delegation:${d.id}`\n nodes.push({ id: delNodeId, kind: 'delegation', label: `${d.id} · ${d.agentId}`, status: d.status, sublabel: d.objective.slice(0, 60), timestamp: d.createdAt })\n edges.push({ id: `edge:${stageNodeId}-${d.id}`, source: stageNodeId, target: delNodeId, kind: 'delegate' })\n }\n const stageFindings = findings.filter(f => f.sourceStage === stageId)\n for (const f of stageFindings) {\n nodes.push({ id: `finding:${f.id}`, kind: 'finding', label: f.title, status: f.severity.toUpperCase(), nav: { tab: 'findings', focus: f.id } })\n edges.push({ id: `edge:found-${f.id}`, source: `delegation:${f.sourceDelegationId}`, target: `finding:${f.id}`, kind: 'found' })\n }\n prevStageId = stageId\n }\n // Deduplicate edges\n const seen = new Set<string>()\n return { nodes, edges: edges.filter(e => { const k = `${e.source}->${e.target}`; if (seen.has(k)) return false; seen.add(k); return true }) }\n}\n\n// ── Core snapshot (no output trees) ────────────────────────────────────────\n\nconst snapshotPerf = typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1'\n\nexport async function buildSnapshot(ctx: TargetContext): Promise<PentesterViewSnapshot> {\n const t0 = performance.now()\n\n // Parallel: run, findings, assets, registry — all independent\n const [run, findings, assetCount, registry] = await Promise.all([\n tryLoadRun(ctx),\n parseFindingsIndex(ctx),\n parseAssetsCount(ctx),\n loadTargetRegistry(ctx.projectDir).catch(() => null),\n ])\n\n const tData = (performance.now() - t0).toFixed(1)\n if (snapshotPerf) {\n console.log(`[SESSION_SWITCH_PERF] snapshot data-load=${tData}ms (run+findings+assets+registry)`)\n }\n\n // Target summaries (pure memory from registry)\n const targets: TargetSummary[] = []\n if (registry !== null) {\n for (const record of listTargetRecords(registry)) {\n targets.push({\n id: record.id, target: record.target, canonicalTarget: record.canonicalTarget,\n rootSessionId: record.rootSessionId, status: 'unknown', currentStage: null, createdAt: record.createdAt,\n })\n }\n }\n\n if (run === null) {\n return {\n run: null,\n stats: { assets: 0, findings: 0, delegations: 0 },\n stages: STAGE_IDS.map(id => ({\n id, name: STAGE_DEFINITIONS.find(d => d.id === id)?.name ?? id,\n shortName: STAGE_SHORT[id] ?? id.slice(0, 4), status: 'pending', delegationCount: 0, activeDelegationCount: 0,\n })),\n delegations: [], findings,\n trace: { nodes: [{ id: 'start', kind: 'start', label: 'Start' }], edges: [] },\n targets,\n }\n }\n\n // Pure memory projection\n const result: PentesterViewSnapshot = {\n run: buildRunView(run),\n stats: { assets: assetCount, findings: findings.length, delegations: run.delegations.length },\n stages: buildStageViews(run),\n delegations: buildDelegationViews(run),\n findings,\n trace: buildTraceModel(run, ctx, findings),\n targets,\n }\n\n const totalMs = (performance.now() - t0).toFixed(1)\n if (snapshotPerf) {\n console.log(`[SESSION_SWITCH_PERF] snapshot projection=${(Number(totalMs) - Number(tData)).toFixed(1)}ms total=${totalMs}ms`)\n }\n\n return result\n}\n\n// ── Lazy output tree ──────────────────────────────────────────────────────\n\nconst outputCache = new Map<string, { tree: OutputEntry[]; builtAt: number }>()\nconst OUTPUT_CACHE_TTL = 10_000\n\n// In-flight dedup: only one build per target at a time\nconst outputInflight = new Map<string, Promise<OutputEntry[]>>()\n\n// Global FS semaphore: max concurrent readdir/stat operations\nconst FS_SEMAPHORE = 16\nlet fsInFlight = 0\nconst fsWaiters: Array<() => void> = []\n\nfunction fsAcquire(): Promise<void> {\n if (fsInFlight < FS_SEMAPHORE) {\n fsInFlight++\n return Promise.resolve()\n }\n return new Promise(resolve => { fsWaiters.push(resolve) })\n}\n\nfunction fsRelease(): void {\n fsInFlight--\n const next = fsWaiters.shift()\n if (next !== undefined) {\n fsInFlight++\n next()\n }\n}\n\nexport function invalidateOutputCache(targetId: string): void { outputCache.delete(targetId) }\n\nexport async function buildOutputTreeForTarget(ctx: TargetContext, targetId?: string, signal?: AbortSignal): Promise<OutputTreeResult> {\n // Resolve target context\n let targetCtx = ctx\n if (targetId !== undefined && targetId !== ctx.targetId) {\n const registry = await loadTargetRegistry(ctx.projectDir)\n const record = registry.targets.find(t => t.id === targetId)\n if (record === undefined) throw new Error('target not found')\n targetCtx = buildTargetContext(ctx.projectDir, record)\n }\n\n const cacheKey = targetCtx.targetId\n const cached = outputCache.get(cacheKey)\n if (cached !== undefined && (Date.now() - cached.builtAt) < OUTPUT_CACHE_TTL) {\n console.log(`[OUTPUT_SCAN] cache=hit targetId=${cacheKey}`)\n return { targetId: cacheKey, target: targetCtx.target, current: cacheKey === ctx.targetId, children: cached.tree }\n }\n\n // In-flight dedup: reuse existing build promise for same target\n const inflight = outputInflight.get(cacheKey)\n if (inflight !== undefined) {\n console.log(`[OUTPUT_SCAN] inflight=dedup targetId=${cacheKey}`)\n const tree = await inflight\n return { targetId: cacheKey, target: targetCtx.target, current: cacheKey === ctx.targetId, children: tree }\n }\n\n console.log(`[OUTPUT_SCAN] cache=miss targetId=${cacheKey}`)\n const promise = buildOutputTree(targetCtx, signal)\n outputInflight.set(cacheKey, promise)\n\n try {\n const tree = await promise\n outputCache.set(cacheKey, { tree, builtAt: Date.now() })\n return { targetId: cacheKey, target: targetCtx.target, current: cacheKey === ctx.targetId, children: tree }\n } finally {\n outputInflight.delete(cacheKey)\n }\n}\n\n// ── Output tree builder ────────────────────────────────────────────────────\n\ninterface ScanStats {\n dirs: number\n files: number\n statCalls: number\n readdirCalls: number\n maxDepth: number\n maxDirEntries: number\n}\n\nasync function buildOutputTree(ctx: TargetContext, signal?: AbortSignal): Promise<OutputEntry[]> {\n const root = ctx.targetRoot\n if (!existsSync(root)) return []\n const entries: OutputEntry[] = []\n\n const stats: ScanStats = { dirs: 0, files: 0, statCalls: 0, readdirCalls: 0, maxDepth: 0, maxDirEntries: 0 }\n const categoryTimings: Record<string, number> = {}\n const categoryCounts: Record<string, number> = {}\n\n const categories = [\n { dir: 'report', label: 'Reports', category: 'report' as const },\n { dir: 'findings', label: 'Findings', category: 'finding' as const },\n { dir: 'assets', label: 'Artifacts', category: 'artifact' as const },\n { dir: 'evidence', label: 'Evidence', category: 'evidence' as const },\n ]\n\n for (const cat of categories) {\n signal?.throwIfAborted()\n const catDir = join(root, cat.dir)\n if (!existsSync(catDir)) continue\n const tCat = performance.now()\n const children = await scanDir(catDir, root, cat.category, 0, stats, signal)\n const catMs = (performance.now() - tCat)\n categoryTimings[cat.dir] = catMs\n categoryCounts[cat.dir] = children.length\n if (children.length > 0) {\n entries.push({ path: cat.dir, name: cat.label, kind: 'directory', category: cat.category, children: flattenSingleChildDirs(children) })\n }\n }\n\n // Stage summaries\n const stagesDir = join(root, 'stages')\n if (existsSync(stagesDir)) {\n const tStages = performance.now()\n let stageEntryCount = 0\n for (let i = 0; i < STAGE_IDS.length; i++) {\n signal?.throwIfAborted()\n const stageId = STAGE_IDS[i]\n const stageSubDir = join(stagesDir, `${String(i + 1).padStart(2, '0')}-${stageId}`)\n if (!existsSync(stageSubDir)) continue\n const children: OutputEntry[] = []\n const summaryFile = join(stageSubDir, 'summary.md')\n if (existsSync(summaryFile)) {\n stats.statCalls++\n const st = await stat(summaryFile)\n children.push({ path: relative(root, summaryFile), name: 'summary.md', kind: 'file', size: st.size, mtime: st.mtime.toISOString(), category: 'stage', sourceStage: stageId })\n }\n const delegationsDir = join(stageSubDir, 'delegations')\n if (existsSync(delegationsDir)) {\n stats.readdirCalls++\n const delDirs = await readdir(delegationsDir, { withFileTypes: true })\n for (const delDir of delDirs) {\n if (!delDir.isDirectory()) continue\n const delId = delDir.name\n const resultFile = join(delegationsDir, delId, 'result.md')\n if (existsSync(resultFile)) {\n stats.statCalls++\n const st = await stat(resultFile)\n children.push({ path: relative(root, resultFile), name: `${delId}/result.md`, kind: 'file', size: st.size, mtime: st.mtime.toISOString(), category: 'stage', sourceStage: stageId, sourceDelegationId: delId })\n }\n const evidenceDir = join(delegationsDir, delId, 'evidence')\n if (existsSync(evidenceDir)) children.push(...flattenSingleChildDirs(await scanDir(evidenceDir, root, 'evidence', 0, stats, signal, stageId, delId)))\n const artifactsDir = join(delegationsDir, delId, 'artifacts')\n if (existsSync(artifactsDir)) children.push(...flattenSingleChildDirs(await scanDir(artifactsDir, root, 'artifact', 0, stats, signal, stageId, delId)))\n }\n }\n if (children.length > 0) {\n stageEntryCount += children.length\n entries.push({ path: relative(root, stageSubDir), name: STAGE_SHORT[stageId] ?? stageId, kind: 'directory', category: 'stage', children: flattenSingleChildDirs(children) })\n }\n }\n categoryTimings['stages'] = (performance.now() - tStages)\n categoryCounts['stages'] = stageEntryCount\n }\n\n // Print scan report\n const totalMs = Object.values(categoryTimings).reduce((a, b) => a + b, 0)\n const catReport = Object.entries(categoryTimings)\n .map(([cat, ms]) => `${cat}=${ms.toFixed(0)}ms entries=${categoryCounts[cat] ?? 0}`)\n .join('\\n')\n const totalEntries = Object.values(categoryCounts).reduce((a, b) => a + b, 0)\n console.log(`[OUTPUT_SCAN]\\n${catReport}\\nstages=${categoryTimings['stages']?.toFixed(0) ?? '0'}ms entries=${categoryCounts['stages'] ?? 0}\\ntotal=${totalMs.toFixed(0)}ms entries=${totalEntries}\\ndirs=${stats.dirs} files=${stats.files} stat=${stats.statCalls} readdir=${stats.readdirCalls} maxDepth=${stats.maxDepth} maxDirEntries=${stats.maxDirEntries}`)\n\n return entries\n}\n\n// ── Bounded-concurrency scanDir ────────────────────────────────────────────\n\nconst SCAN_CONCURRENCY = 16\n\nasync function scanDir(\n dir: string, root: string, parentCategory: OutputEntry['category'],\n depth: number = 0, stats?: ScanStats, signal?: AbortSignal,\n sourceStage?: string, sourceDelegationId?: string,\n): Promise<OutputEntry[]> {\n if (depth > 3) return []\n signal?.throwIfAborted()\n try {\n if (stats) {\n stats.dirs++\n if (depth > stats.maxDepth) stats.maxDepth = depth\n }\n await fsAcquire()\n if (stats) stats.readdirCalls++\n const items = await readdir(dir, { withFileTypes: true })\n fsRelease()\n if (stats && items.length > stats.maxDirEntries) stats.maxDirEntries = items.length\n const filtered = items.filter(i => !i.name.startsWith('.') && i.name !== 'tmp' && i.name !== 'cache' && i.name !== '.dsh-pentester' && i.name !== '.git')\n\n // Process in bounded batches\n const entries: OutputEntry[] = []\n for (let batch = 0; batch < filtered.length; batch += SCAN_CONCURRENCY) {\n const batchItems = filtered.slice(batch, batch + SCAN_CONCURRENCY)\n const results = await Promise.all(batchItems.map(async (item) => {\n signal?.throwIfAborted()\n const fullPath = join(dir, item.name)\n const relPath = relative(root, fullPath)\n if (item.isDirectory()) {\n const children = await scanDir(fullPath, root, parentCategory, depth + 1, stats, signal, sourceStage, sourceDelegationId)\n if (children.length === 0) return null\n return { path: relPath, name: item.name, kind: 'directory' as const, category: parentCategory, ...(sourceStage !== undefined ? { sourceStage } : {}), ...(sourceDelegationId !== undefined ? { sourceDelegationId } : {}), children }\n }\n try {\n if (stats) { stats.files++; stats.statCalls++ }\n await fsAcquire()\n const st = await stat(fullPath)\n fsRelease()\n return { path: relPath, name: item.name, kind: 'file' as const, size: st.size, mtime: st.mtime.toISOString(), category: parentCategory, ...(sourceStage !== undefined ? { sourceStage } : {}), ...(sourceDelegationId !== undefined ? { sourceDelegationId } : {}) }\n } catch { return null }\n }))\n for (const r of results) { if (r !== null) entries.push(r) }\n }\n return entries.sort((a, b) => a.kind !== b.kind ? (a.kind === 'directory' ? -1 : 1) : a.name.localeCompare(b.name))\n } catch { return [] }\n}\n\n// ── Flatten single-child dirs ──────────────────────────────────────────────\n\nfunction flattenSingleChildDirs(entries: readonly OutputEntry[]): OutputEntry[] {\n const result: OutputEntry[] = []\n for (const entry of entries) {\n if (entry.kind !== 'directory' || entry.children === undefined || entry.children.length !== 1 || entry.children[0].kind !== 'directory') {\n result.push(entry); continue\n }\n const child = entry.children[0]\n result.push({ path: child.path, name: `${entry.name}/${child.name}`, kind: 'directory', category: entry.category, ...(entry.sourceStage !== undefined ? { sourceStage: entry.sourceStage } : {}), ...(entry.sourceDelegationId !== undefined ? { sourceDelegationId: entry.sourceDelegationId } : {}), children: child.children !== undefined ? flattenSingleChildDirs(child.children) : undefined })\n }\n return result\n}\n\n// ── readOutputFile (partial read, no full 10MB load) ──────────────────────\n\nconst MAX_PREVIEW = 1 * 1024 * 1024 // 1MB\n\nexport async function readOutputFile(\n ctx: TargetContext, relativePath: string,\n): Promise<{ ok: true; content: string; mime: string; size: number; mtime: string; name: string } | { ok: false; error: string }> {\n if (relativePath.includes('..') || relativePath.startsWith('/') || isAbsolute(relativePath) || relativePath.includes('\\0')) {\n return { ok: false, error: 'path denied' }\n }\n const root = ctx.targetRoot\n const fullPath = join(root, relativePath)\n\n const { realpathSync } = await import('node:fs')\n let realRoot: string, realFile: string\n try {\n realRoot = realpathSync(root); realFile = realpathSync(fullPath)\n } catch { return { ok: false, error: 'file not found' } }\n if (!realFile.startsWith(realRoot + sep) && realFile !== realRoot) return { ok: false, error: 'path escape denied' }\n\n try {\n const st = await stat(fullPath)\n if (st.isDirectory()) return { ok: false, error: 'is a directory' }\n\n const ext = relativePath.split('.').pop()?.toLowerCase() ?? ''\n const binaryExts = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'ico', 'pdf', 'zip', 'gz', 'tar', 'pcap', 'mitm', 'bin', 'exe', 'dll', 'so'])\n if (binaryExts.has(ext)) {\n return { ok: true, content: `[Binary file: ${ext.toUpperCase()} — ${(st.size / 1024).toFixed(1)} KB]`, mime: 'binary', size: st.size, mtime: st.mtime.toISOString(), name: relativePath.split('/').pop() ?? relativePath }\n }\n\n // Partial read: only first MAX_PREVIEW bytes\n const fh = await fsOpen(fullPath, 'r')\n const buf = Buffer.alloc(Math.min(st.size, MAX_PREVIEW))\n await fh.read(buf, 0, buf.length, 0)\n await fh.close()\n\n let content = buf.toString('utf8')\n if (st.size > MAX_PREVIEW) content += `\\n\\n... [truncated: ${(st.size / 1024).toFixed(1)} KB total]`\n\n let mime: string = 'text'\n if (ext === 'md') mime = 'markdown'\n else if (ext === 'json') mime = 'json'\n\n return { ok: true, content, mime, size: st.size, mtime: st.mtime.toISOString(), name: relativePath.split('/').pop() ?? relativePath }\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : 'read error' }\n }\n}","/**\n * ui-view/binding.ts — Lightweight session → target resolver.\n *\n * Resolution order:\n * 1. Cache (only bound resolutions, no negative caching)\n * 2. Live: deps.getLiveSessionCwd(sessionId) → ctx.get('sessions') per call\n * 3. Cold: deps.getWorkspaceForSession(sessionId) → ctx.get('workspaceRegistry') per call\n * 4. resolveSessionTargetContext → TargetContext\n *\n * NEVER calls:\n * - sessionPersistence.list()\n * - sessionPersistence.inspect()\n * - sessionQuery.readSession()\n *\n * IMPORTANT: deps are dynamic resolver functions, not static service instances.\n * They call ctx.get() on each invocation so the resolver always reads the\n * current active service. sessions/workspaceRegistry lifecycle changes do\n * not invalidate the RPC endpoint.\n */\nimport { isAbsolute } from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport { resolveSessionTargetContext, type TargetContext } from '../targets.js'\n\n// ── Dynamic dependency contract ────────────────────────────────────────────\n\nexport interface PentesterViewHostDeps {\n /** Resolve the live session cwd from the current active sessions service. */\n readonly getLiveSessionCwd: (sessionId: string) => string | undefined\n /** Resolve workspace path from the current active workspaceRegistry. */\n readonly getWorkspaceForSession: (sessionId: string) => string | undefined\n readonly verbose?: boolean\n}\n\n// ── Resolution types ───────────────────────────────────────────────────────\n\nexport interface BindingResolution {\n kind: 'bound'\n projectDir: string\n targetContext: TargetContext\n}\n\ninterface UnboundResolution {\n kind: 'unbound'\n projectDir: string\n}\n\nexport type ViewResolution = BindingResolution | UnboundResolution\n\n// ── Cache (only bound, no negative) ────────────────────────────────────────\n\nconst cache = new Map<string, BindingResolution>()\n\nexport function invalidateBinding(sessionId: string): void {\n cache.delete(sessionId)\n}\n\n// ── Main resolver ──────────────────────────────────────────────────────────\n\nexport async function resolveBinding(\n deps: PentesterViewHostDeps,\n sessionId: string,\n): Promise<ViewResolution> {\n const t0 = performance.now()\n const perf = deps.verbose || (typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1')\n\n // 1. Cache (only bound)\n const cached = cache.get(sessionId)\n if (cached !== undefined) {\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=cache total=${(performance.now() - t0).toFixed(1)}ms`)\n }\n return cached\n }\n\n // 2. Live session header (O(1) — calls ctx.get('sessions') per invocation)\n const tLive = performance.now()\n const projectDir = deps.getLiveSessionCwd(sessionId)\n const liveMs = (performance.now() - tLive).toFixed(1)\n let source = 'live'\n\n // 3. Cold: workspaceRegistry (sync, in-memory, no persistence)\n let resolvedDir = projectDir\n if (resolvedDir === undefined) {\n const tWs = performance.now()\n resolvedDir = deps.getWorkspaceForSession(sessionId)\n const wsMs = (performance.now() - tWs).toFixed(1)\n source = 'workspace-index'\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} workspaceLookup=${wsMs}ms`)\n }\n }\n\n // 4. Unbound: no projectDir found\n if (resolvedDir === undefined || resolvedDir === '') {\n const totalMs = (performance.now() - t0).toFixed(1)\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=${source} result=unbound total=${totalMs}ms`)\n }\n return { kind: 'unbound', projectDir: '' }\n }\n\n // 5. Resolve target context\n const tTarget = performance.now()\n const targetCtx = await resolveSessionTargetContext(resolvedDir, sessionId)\n const targetMs = (performance.now() - tTarget).toFixed(1)\n\n if (targetCtx !== undefined) {\n const result: BindingResolution = { kind: 'bound', projectDir: resolvedDir, targetContext: targetCtx }\n cache.set(sessionId, result) // Only cache bound\n const totalMs = (performance.now() - t0).toFixed(1)\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=${source} cwd=${resolvedDir} liveLookup=${liveMs}ms targetLookup=${targetMs}ms total=${totalMs}ms`)\n }\n if (Number(totalMs) > 100) {\n console.warn(`[SESSION_SWITCH_PERF] slow binding ${totalMs}ms source=${source}`)\n }\n return result\n }\n\n const totalMs = (performance.now() - t0).toFixed(1)\n if (perf) {\n console.log(`[SESSION_SWITCH_PERF] binding session=${sessionId.slice(0, 8)} source=${source} result=target-unresolved total=${totalMs}ms`)\n }\n return { kind: 'unbound', projectDir: resolvedDir }\n}","/**\n * build-id.ts — Build identity injected at build time.\n *\n * Generated by scripts/build-id.mjs before each build.\n * Both host (tsdown) and client (esbuild) import this module.\n *\n * Format: version+shortSha\n */\nexport const BUILD_ID = \"2.3.0+2a31301\"\n","/**\n * ui-view/invocations.ts — Pentester View 的 Typert 调用描述符与 schemas。\n *\n * 仅包含纯数据常量:客户端和宿主两侧均可安全导入,无 Node.js 依赖。\n */\nimport { z } from 'zod'\n\nconst pentesterViewInputSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('health') }),\n z.object({ kind: z.literal('snapshot'), sessionId: z.string() }),\n z.object({ kind: z.literal('listOutput'), sessionId: z.string(), targetId: z.string().optional() }),\n z.object({ kind: z.literal('readOutput'), sessionId: z.string(), targetId: z.string().optional(), path: z.string() }),\n z.object({ kind: z.literal('readFinding'), sessionId: z.string(), detailFile: z.string() }),\n])\n\nconst snapshotResultSchema = z.object({\n run: z.union([z.object({\n id: z.string(),\n status: z.enum(['active', 'completed']),\n currentStage: z.string().nullable(),\n targets: z.array(z.string()),\n createdAt: z.string(),\n }), z.null()]),\n stats: z.object({\n assets: z.number(),\n findings: z.number(),\n delegations: z.number(),\n }),\n stages: z.array(z.object({\n id: z.string(),\n name: z.string(),\n shortName: z.string(),\n status: z.string(),\n delegationCount: z.number(),\n activeDelegationCount: z.number(),\n })),\n delegations: z.array(z.object({\n id: z.string(),\n stageId: z.string(),\n agentId: z.string(),\n sessionId: z.string().optional(),\n objective: z.string(),\n status: z.string(),\n createdAt: z.string(),\n finishedAt: z.string().optional(),\n })),\n findings: z.array(z.object({\n id: z.string(),\n title: z.string(),\n severity: z.string(),\n status: z.string().optional(),\n sourceStage: z.string(),\n sourceDelegationId: z.string(),\n detailFile: z.string(),\n affectedAsset: z.string().optional(),\n description: z.string().optional(),\n updatedAt: z.string(),\n })),\n trace: z.object({\n nodes: z.array(z.object({\n id: z.string(),\n kind: z.string(),\n label: z.string(),\n status: z.string().optional(),\n sublabel: z.string().optional(),\n timestamp: z.string().optional(),\n })),\n edges: z.array(z.object({\n id: z.string(),\n source: z.string(),\n target: z.string(),\n kind: z.string(),\n label: z.string().optional(),\n })),\n }),\n targets: z.array(z.object({\n id: z.string(),\n target: z.string(),\n canonicalTarget: z.string(),\n rootSessionId: z.string().nullable(),\n status: z.string(),\n currentStage: z.string().nullable(),\n createdAt: z.string(),\n })),\n})\n\nconst unboundResultSchema = z.object({\n kind: z.literal('unbound'),\n targets: z.array(z.object({\n id: z.string(),\n target: z.string(),\n canonicalTarget: z.string(),\n rootSessionId: z.string().nullable(),\n status: z.string(),\n currentStage: z.string().nullable(),\n createdAt: z.string(),\n })),\n})\n\nconst outputFileResultSchema = z.object({\n path: z.string(),\n name: z.string(),\n size: z.number(),\n mtime: z.string(),\n mime: z.enum(['text', 'markdown', 'json', 'image', 'binary']),\n content: z.string().optional(),\n})\n\nconst outputTreeResultSchema = z.object({\n targetId: z.string(),\n target: z.string(),\n current: z.boolean(),\n children: z.array(z.unknown()),\n})\n\n/** 客户端 remote 贡献的 invocation 描述符 */\nexport const PENTESTER_VIEW_INVOCATION = {\n id: 'dsh-pentester#pentesterView/command',\n service: 'pentesterView',\n namespace: 'pentesterView',\n method: 'command',\n invocation: { kind: 'direct' as const },\n cancellation: {\n parameter: 'signal' as const,\n },\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#PentesterViewInput',\n schema: pentesterViewInputSchema,\n },\n },\n ],\n result: {\n mode: 'strict' as const,\n typeSymbol: 'dsh-pentester#PentesterViewResult',\n schema: z.object({\n ok: z.boolean(),\n value: z.union([snapshotResultSchema, outputTreeResultSchema, outputFileResultSchema, unboundResultSchema, z.object({ ready: z.literal(true), buildId: z.string() })]).optional(),\n error: z.string().optional(),\n code: z.string().optional(),\n }),\n },\n} as const\n\n/** 客户端 remote 网关的挂载贡献 */\nexport const PENTESTER_VIEW_REMOTE = {\n package: 'dsh-pentester',\n descriptors: [PENTESTER_VIEW_INVOCATION],\n} as const\n\n/** Typert manifest(供宿主注册)。 */\nexport const PENTESTER_VIEW_MANIFEST = {\n package: 'dsh-pentester',\n face: 'host' as const,\n schemas: [],\n model: {\n services: [\n {\n key: 'pentesterView',\n exportName: 'PentesterViewTypertService',\n description: 'Pentester View 数据服务(snapshot / readOutput)。',\n tags: [],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: {kind: string; ...}): Promise<{ok: boolean; value?: any; error?: string; code?: string}>',\n },\n ],\n types: [],\n },\n ],\n events: [],\n objects: [],\n },\n invocations: [PENTESTER_VIEW_INVOCATION],\n}","/**\n * ui-view/rpc.ts — Pentester View Typert Remote service.\n *\n * Explicit dependency injection: sessions + workspaceRegistry.\n * NEVER calls sessionPersistence, sessionQuery, or agents.\n *\n * Core snapshot: no output trees. Output is lazy via listOutput.\n */\nimport { isAbsolute } from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport { z } from 'zod'\nimport { buildSnapshot, buildOutputTreeForTarget, readOutputFile } from './snapshot.js'\nimport { resolveBinding, type PentesterViewHostDeps } from './binding.js'\nimport { loadTargetRegistry, buildTargetContext } from '../targets.js'\nimport { tryLoadRun } from '../store.js'\nimport type { PentesterViewSnapshot, OutputFileResult, OutputTreeResult, PentesterViewUnbound, TargetSummary } from './types.js'\nimport { BUILD_ID } from '../build-id.js'\nimport { PENTESTER_VIEW_INVOCATION, PENTESTER_VIEW_REMOTE, PENTESTER_VIEW_MANIFEST } from './invocations.js'\n\nexport interface PentesterHealthResult {\n readonly ready: true\n readonly buildId: string\n}\n\nexport { PENTESTER_VIEW_INVOCATION, PENTESTER_VIEW_REMOTE, PENTESTER_VIEW_MANIFEST }\n\nexport function validateCwd(raw: unknown): string | undefined {\n if (typeof raw !== 'string' || raw.length === 0) return undefined\n if (!isAbsolute(raw)) return undefined\n return raw\n}\n\n// ── Input schema (host-side, must match invocations.ts) ────────────────────\n\nconst pentesterViewInputSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('health') }),\n z.object({ kind: z.literal('snapshot'), sessionId: z.string() }),\n z.object({ kind: z.literal('listOutput'), sessionId: z.string(), targetId: z.string().optional() }),\n z.object({ kind: z.literal('readOutput'), sessionId: z.string(), targetId: z.string().optional(), path: z.string() }),\n z.object({ kind: z.literal('readFinding'), sessionId: z.string(), detailFile: z.string() }),\n])\n\n// ── Request ID counter ─────────────────────────────────────────────────────\n\nlet requestSeq = 0\n\n// ── Typert service ─────────────────────────────────────────────────────────\n\nconst HOST_PERF = typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1'\n\nexport class PentesterViewTypertService extends TypertRemoteService {\n private readonly deps: PentesterViewHostDeps\n\n constructor(ctx: unknown, deps: PentesterViewHostDeps) {\n super(ctx as never, 'pentesterView')\n this.deps = deps\n }\n\n async command(\n input: unknown,\n signal?: AbortSignal,\n ): Promise<{\n ok: boolean\n value?: PentesterViewSnapshot | OutputTreeResult | OutputFileResult | PentesterViewUnbound | PentesterHealthResult\n error?: string\n code?: string\n }> {\n const requestId = ++requestSeq\n const t0 = performance.now()\n\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} ENTER +0ms`)\n }\n\n const parsed = pentesterViewInputSchema.safeParse(input)\n if (!parsed.success) {\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} INVALID_REQUEST +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: false, error: 'invalid_request', code: 'invalid_request' }\n }\n\n const data = parsed.data\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} PARSED kind=${data.kind} +${(performance.now() - t0).toFixed(1)}ms`)\n }\n\n try {\n signal?.throwIfAborted()\n\n if (data.kind === 'health') {\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} HEALTH +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: true, value: { ready: true as const, buildId: BUILD_ID } }\n }\n\n if (data.kind === 'snapshot') {\n signal?.throwIfAborted()\n\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} BINDING_START +${(performance.now() - t0).toFixed(1)}ms`)\n }\n const tResolve = performance.now()\n const resolution = await resolveBinding(this.deps, data.sessionId)\n const resolveMs = (performance.now() - tResolve).toFixed(1)\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} BINDING_END kind=${resolution.kind} +${(performance.now() - t0).toFixed(1)}ms`)\n }\n\n if (resolution.kind === 'bound') {\n signal?.throwIfAborted()\n\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} SNAPSHOT_START +${(performance.now() - t0).toFixed(1)}ms`)\n }\n const tBuild = performance.now()\n const snapshot = await buildSnapshot(resolution.targetContext)\n const buildMs = (performance.now() - tBuild).toFixed(1)\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} SNAPSHOT_END +${(performance.now() - t0).toFixed(1)}ms`)\n }\n\n signal?.throwIfAborted()\n\n const totalMs = (performance.now() - t0).toFixed(1)\n if (HOST_PERF) {\n const payload = JSON.stringify(snapshot).length\n console.log(`[PENTESTER_RPC_HOST] #${requestId} RETURN binding=${resolveMs}ms build=${buildMs}ms total=${totalMs}ms payload=${(payload / 1024).toFixed(0)}KB`)\n }\n if (Number(totalMs) > 1000) {\n console.warn(`[PENTESTER_RPC_HOST] #${requestId} slow ${totalMs}ms`)\n }\n return { ok: true, value: snapshot }\n }\n\n if (resolution.projectDir !== '') {\n return buildUnboundSnapshot(resolution.projectDir)\n }\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} RETURN unbound +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: true, value: { kind: 'unbound', targets: [] } }\n }\n\n if (data.kind === 'listOutput') {\n signal?.throwIfAborted()\n\n const tResolve = performance.now()\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} ENTER`)\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} BINDING_START`)\n\n const resolution = await resolveBinding(this.deps, data.sessionId)\n if (resolution.kind !== 'bound') return { ok: false, error: 'not bound', code: 'no_binding' }\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} BINDING_END ${(performance.now() - tResolve).toFixed(1)}ms`)\n\n signal?.throwIfAborted()\n\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} TREE_START targetId=${data.targetId ?? 'default'}`)\n const tTree = performance.now()\n const tree = await buildOutputTreeForTarget(resolution.targetContext, data.targetId, signal)\n const treeMs = (performance.now() - tTree).toFixed(1)\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} TREE_END ${treeMs}ms`)\n\n signal?.throwIfAborted()\n\n const totalMs = (performance.now() - t0).toFixed(1)\n const payload = JSON.stringify(tree).length\n console.log(`[PENTESTER_OUTPUT_PERF] #${requestId} RETURN total=${totalMs}ms entryCount=${tree.children.length} payload=${(payload / 1024).toFixed(0)}KB`)\n return { ok: true, value: tree }\n }\n\n if (data.kind === 'readOutput') {\n signal?.throwIfAborted()\n const resolution = await resolveBinding(this.deps, data.sessionId)\n if (resolution.kind !== 'bound') return { ok: false, error: 'not bound', code: 'no_binding' }\n const path = data.path\n if (path === '') return { ok: false, error: 'path required', code: 'invalid_request' }\n\n let targetCtx = resolution.targetContext\n if (data.targetId !== undefined && data.targetId !== resolution.targetContext.targetId) {\n const registry = await loadTargetRegistry(resolution.projectDir)\n const record = registry.targets.find(t => t.id === data.targetId)\n if (record === undefined) return { ok: false, error: 'target not found', code: 'invalid_target' }\n targetCtx = buildTargetContext(resolution.projectDir, record)\n }\n\n const result = await readOutputFile(targetCtx, path)\n if (!result.ok) return { ok: false, error: result.error, code: 'read_error' }\n return {\n ok: true,\n value: { path, name: result.name, size: result.size, mtime: result.mtime, mime: result.mime as OutputFileResult['mime'], content: result.content },\n }\n }\n\n if (data.kind === 'readFinding') {\n signal?.throwIfAborted()\n const resolution = await resolveBinding(this.deps, data.sessionId)\n if (resolution.kind !== 'bound') return { ok: false, error: 'not bound', code: 'no_binding' }\n const detailFile = data.detailFile\n if (detailFile === '') return { ok: false, error: 'detailFile required', code: 'invalid_request' }\n const result = await readOutputFile(resolution.targetContext, `findings/${detailFile}`)\n if (!result.ok) return { ok: false, error: result.error, code: 'read_error' }\n return { ok: true, value: { path: `findings/${detailFile}`, name: detailFile, size: result.size, mtime: result.mtime, mime: 'markdown', content: result.content } }\n }\n\n return { ok: false, error: 'unknown kind', code: 'invalid_request' }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n if (HOST_PERF) {\n console.log(`[PENTESTER_RPC_HOST] #${requestId} ABORTED +${(performance.now() - t0).toFixed(1)}ms`)\n }\n return { ok: false, error: 'aborted', code: 'aborted' }\n }\n const totalMs = (performance.now() - t0).toFixed(1)\n if (HOST_PERF) console.error(`[PENTESTER_RPC_HOST] #${requestId} FAILED kind=${data.kind} +${totalMs}ms: ${error instanceof Error ? error.message : 'error'}`)\n return { ok: false, error: error instanceof Error ? error.message : 'failed', code: 'snapshot_error' }\n }\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────\n\nasync function buildUnboundSnapshot(projectDir: string): Promise<{ ok: true; value: PentesterViewUnbound }> {\n const registry = await loadTargetRegistry(projectDir)\n const targets: TargetSummary[] = []\n for (const record of registry.targets) {\n const ctx = buildTargetContext(projectDir, record)\n const run = await tryLoadRun(ctx)\n targets.push({\n id: record.id, target: record.target, canonicalTarget: record.canonicalTarget,\n rootSessionId: record.rootSessionId, status: run?.status ?? 'unknown',\n currentStage: run?.currentStage ?? null, createdAt: record.createdAt,\n })\n }\n return { ok: true, value: { kind: 'unbound', targets } }\n}","/**\n * host-manifest.ts — Single unified Typert host manifest for dsh-pentester.\n *\n * Combines pentesterDocker (Settings UI) and pentesterView (Pentester panel)\n * invocations into ONE manifest. Two separate register() calls with the same\n * package name cause the first to be withdrawn (SRC fallback denied).\n *\n * Client uses the same invocation constants via PENTESTER_REMOTE and\n * PENTESTER_VIEW_REMOTE — no duplication of endpoint definitions.\n */\nimport { PENTESTER_DOCKER_INVOCATION } from './invocations.js'\nimport { PENTESTER_VIEW_INVOCATION } from './ui-view/invocations.js'\n\nexport const PENTESTER_HOST_MANIFEST = {\n package: 'dsh-pentester',\n face: 'host' as const,\n schemas: [] as readonly never[],\n model: {\n services: [\n {\n key: 'pentesterDocker',\n exportName: 'PentesterDockerTypertService',\n description: 'Pentester Docker Engine 设置(Settings UI Docker Engine Tab)。',\n tags: [] as readonly never[],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: object): Promise<{ok:boolean; value?:any; error?:string; code?:string}>',\n },\n ],\n types: [] as readonly never[],\n },\n {\n key: 'pentesterView',\n exportName: 'PentesterViewTypertService',\n description: 'Pentester View 数据服务(snapshot / readOutput)。',\n tags: [] as readonly never[],\n members: [\n {\n kind: 'method' as const,\n name: 'command',\n signature: 'command(input: {kind:string; ...}): Promise<{ok:boolean; value?:any; error?:string; code?:string}>',\n },\n ],\n types: [] as readonly never[],\n },\n ],\n events: [] as readonly never[],\n objects: [] as readonly never[],\n },\n invocations: [PENTESTER_DOCKER_INVOCATION, PENTESTER_VIEW_INVOCATION],\n} as const","/**\n * git.ts — GitCheckpointService:target-scoped git 仓库管理(宿主侧)。\n *\n * 仓库根 = targetRoot(每 Target 独立 .git)。\n * 约定式提交:\n * - 初始:`workspace: initialize <target>`\n * - 阶段完成:`ptes(<NN>-<stage>): complete` + tag `ptes/<NN>-<stage>`\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 type { TargetContext } from './targets.js'\n\nexport class GitCheckpointError extends Error {}\n\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 readonly isRepo?: (ctx: TargetContext) => Promise<boolean>\n}\n\nexport class GitCheckpointService {\n private readonly runner: GitRunner\n private readonly userName: string\n private readonly userEmail: string\n private readonly isRepoOverride?: (ctx: TargetContext) => 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 repoDir(ctx: TargetContext): string {\n return ctx.targetRoot\n }\n\n async isRepo(ctx: TargetContext): Promise<boolean> {\n if (this.isRepoOverride !== undefined) return this.isRepoOverride(ctx)\n return existsSync(join(this.repoDir(ctx), '.git'))\n }\n\n async init(ctx: TargetContext, target?: string): Promise<void> {\n const cwd = this.repoDir(ctx)\n await mkdir(cwd, { recursive: true })\n if (await this.isRepo(ctx)) return\n await this.runner(['init', '-b', 'main'], cwd).catch(async () => {\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 async checkpointStage(ctx: TargetContext, stage: StageId): Promise<string> {\n if (!(await this.isRepo(ctx))) {\n throw new GitCheckpointError('workspace is not a git repository; run initTargetWorkspace first')\n }\n const cwd = this.repoDir(ctx)\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 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 async currentBranch(ctx: TargetContext): Promise<string> {\n const cwd = this.repoDir(ctx)\n const out = await this.runner(['branch', '--show-current'], cwd).catch(() => '')\n return out.trim() || 'main'\n }\n\n async hasChanges(ctx: TargetContext): Promise<boolean> {\n const cwd = this.repoDir(ctx)\n const out = await this.runner(['status', '--porcelain'], cwd).catch(() => '')\n return out.trim() !== ''\n }\n\n async findStageCheckpoint(ctx: TargetContext, stage: StageId): Promise<string | undefined> {\n const cwd = this.repoDir(ctx)\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 async createBackupBranch(ctx: TargetContext, stage: string): Promise<string> {\n const cwd = this.repoDir(ctx)\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 async createReworkBranch(ctx: TargetContext, checkpoint: string, nextStageSlug: string): Promise<string> {\n const cwd = this.repoDir(ctx)\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 async checkout(ctx: TargetContext, ref: string): Promise<void> {\n const cwd = this.repoDir(ctx)\n await this.runner(['checkout', ref], cwd)\n }\n\n private async commit(cwd: string, message: string): Promise<void> {\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 * 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 *\n * RPC endpoints (pentesterDocker, pentesterView) are registered in the\n * main fiber — NOT a child plugin. Their lifetime equals the dsh-pentester\n * plugin lifetime. sessions/workspaceRegistry are resolved dynamically\n * via ctx.get() on each command invocation, so their lifecycle does not\n * affect RPC endpoint registration.\n */\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { performance } from 'node:perf_hooks'\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 } from './rpc.js'\nimport { PentesterViewTypertService } from './ui-view/rpc.js'\nimport { PENTESTER_HOST_MANIFEST } from './host-manifest.js'\nimport type { PentesterViewHostDeps } from './ui-view/binding.js'\nimport { GitCheckpointService } from './git.js'\nimport type { TargetContext } from './targets.js'\nimport { BUILD_ID } from './build-id.js'\n\nexport const name = 'dsh-pentester'\n\n// typert is a hard dependency: RPC endpoints must exist for the full\n// plugin lifetime. sessions/workspaceRegistry are NOT hard dependencies\n// — they are resolved dynamically per command invocation.\nexport const inject = ['tools', 'subagents', 'typert']\n\nexport interface Config {\n verbose: boolean\n dockerHost?: string\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 console.log(`[dsh-pentester] host build=${BUILD_ID}`)\n\n // ── Event loop stall detector (DSH_PENTESTER_PERF=1 only) ──────────────\n const perf = config.verbose || (typeof process !== 'undefined' && process.env?.DSH_PENTESTER_PERF === '1')\n if (perf) {\n const INTERVAL = 100\n let expected = performance.now() + INTERVAL\n const timer = setInterval(() => {\n const now = performance.now()\n const lag = now - expected\n if (lag > 250) {\n console.warn(`[HOST_EVENT_LOOP_LAG] ${lag.toFixed(0)}ms (expected interval=${INTERVAL}ms)`)\n }\n expected = now + INTERVAL\n }, INTERVAL)\n timer.unref()\n console.log('[dsh-pentester] event loop stall detector active (interval=100ms, warn>250ms)')\n }\n\n // ── Descriptor lifecycle monitor (verbose/perf only) ───────────────────\n if (perf) {\n try {\n const typertLocal = (ctx as any).typert?.local as {\n subscribe?: (listener: (event: { kind: string; key: string }) => void) => () => void\n }\n if (typertLocal?.subscribe !== undefined) {\n typertLocal.subscribe((event) => {\n if (event.key === 'pentesterView/command') {\n console.log(`[PENTESTER_RPC_LIFECYCLE] pentesterView/command ${event.kind}`)\n }\n })\n }\n } catch { /* best-effort */ }\n }\n\n const profiles = loadAgentProfiles(agentsRoot())\n const presetDir = await publishPentesterPreset()\n if (presetDir !== undefined) {\n await writeStageProfilesManifest(presetDir, profiles)\n }\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 ctx.provide('pentester', {\n registerRootTools: (tools) => registerRootTools(tools, {\n delegations,\n profiles,\n git,\n pushWorkspace: async (targetCtx: TargetContext, run) => { await docker.pushWorkspace(run.id, targetCtx) },\n syncWorkspace: async (targetCtx: TargetContext, run) => { await docker.syncWorkspace(run.id, targetCtx) },\n sessionQuery: {\n readSession: async (sessionId: string) => {\n const sq = (ctx as { get?: (name: string) => unknown }).get?.('sessionQuery') as\n { readSession(id: string): Promise<{ events: ReadonlyArray<{ type: string; data?: unknown }> }> } | undefined\n if (sq === undefined) throw new Error('sessionQuery service unavailable')\n return sq.readSession(sessionId)\n },\n },\n }),\n registerContainerExecTool: (tools) => registerContainerExecTool(tools, docker),\n } satisfies PentesterService)\n\n // ── RPC Services + Manifest — directly in main fiber ───────────────────\n // The endpoint lifetime MUST equal the dsh-pentester plugin lifetime.\n // sessions/workspaceRegistry are resolved dynamically per command.\n //\n // IMPORTANT: manifest MUST be registered before services so the Typert\n // gateway can route requests. Services created before the manifest are\n // invisible to remote clients.\n\n // Register manifest first — gateway routing depends on it.\n ;(ctx as any).typert.register(PENTESTER_HOST_MANIFEST)\n\n // Docker RPC service (settings UI)\n new PentesterDockerTypertService(ctx, {\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 applyHost: (host) => docker.updateHost(host),\n docker,\n })\n\n // Pentester View RPC service — dynamic resolvers, not static instances\n const viewDeps: PentesterViewHostDeps = {\n getLiveSessionCwd(sessionId: string): string | undefined {\n try {\n const sessions = (ctx as { get?: (name: string) => unknown }).get?.('sessions') as\n { get?: (id: string) => { header: { cwd?: string } } | undefined } | undefined\n const session = sessions?.get?.(sessionId)\n const cwd = session?.header?.cwd\n if (typeof cwd === 'string' && cwd.length > 0 && cwd.startsWith('/')) return cwd\n } catch {\n // ctx.get('sessions') may throw if service is not yet available\n }\n return undefined\n },\n\n getWorkspaceForSession(sessionId: string): string | undefined {\n try {\n const registry = (ctx as { get?: (name: string) => unknown }).get?.('workspaceRegistry') as\n { list?: () => readonly { path: string; sessionIds: readonly string[] }[] } | undefined\n if (registry?.list === undefined) return undefined\n for (const workspace of registry.list()) {\n if (workspace.sessionIds.includes(sessionId)) {\n return workspace.path\n }\n }\n } catch {\n // ctx.get('workspaceRegistry') may throw if service is not yet available\n }\n return undefined\n },\n\n verbose: config.verbose,\n }\n\n new PentesterViewTypertService(ctx, viewDeps)\n\n // ── Startup self-check ─────────────────────────────────────────────────\n const typertLocal = (ctx as any).typert.local as {\n get(endpoint: string): unknown\n }\n\n const dockerEndpoint = typertLocal.get('pentesterDocker/command')\n const viewEndpoint = typertLocal.get('pentesterView/command')\n\n if (dockerEndpoint === undefined || viewEndpoint === undefined) {\n throw new Error(\n 'dsh-pentester startup failed: RPC descriptors not registered. ' +\n `docker=${dockerEndpoint !== undefined ? 'ok' : 'MISSING'} ` +\n `view=${viewEndpoint !== undefined ? 'ok' : 'MISSING'}`,\n )\n }\n\n console.log(`[dsh-pentester] RPC ready build=${BUILD_ID}`)\n console.log(` pentesterDocker/command = registered`)\n console.log(` pentesterView/command = registered`)\n console.log(` host module = ${import.meta.url}`)\n\n if (config.verbose) {\n console.log(`[dsh-pentester] loaded with ${profiles.size} agent profiles`)\n }\n}\n\nfunction agentsRoot(): string {\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\nexport const STAGE_PROFILES_FILE = 'stage-profiles.json'\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\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}"],"x_google_ignoreList":[17],"mappings":"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"}