{"version":3,"file":"subagent-prompt-runtime.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/subagent-prompt-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,2BAA2B,CAAC;AAMhF,OAAO,EAEN,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,MAAM,sCAAsC,CAAC;AAI9C,OAAO,EAIN,KAAK,YAAY,EAKjB,MAAM,kCAAkC,CAAC;AA+C1C,eAAO,MAAM,kCAAkC,sCAAsC,CAAC;AAQtF,eAAO,MAAM,oCAAoC,QAMrC,CAAC;AAEb,eAAO,MAAM,kCAAkC,QAOnC,CAAC;AAqGb,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMtE;AAUD,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,qBAAqB,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GACxF,MAAM,CAaR;AA4DD,wBAAgB,+BAA+B,CAC9C,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAO,GACzC,OAAO,EAAE,CAuBX;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAUhE;AAED,wBAAgB,sBAAsB,CACrC,EAAE,EAAE,YAAY,EAChB,iBAAiB,GAAE,CAClB,OAAO,EAAE,yBAAyB,KAC9B,OAAO,CAAC,wBAAwB,CAA6B,GAChE,IAAI,CAwBN;AA4BD,wBAAgB,qBAAqB,CACpC,EAAE,EAAE,YAAY,EAChB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC;IAAC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;CAAO,GACnF,IAAI,CA0LN;AAED,MAAM,CAAC,OAAO,UAAU,6BAA6B,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA0H5E","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ExtensionAPI, ExtensionContext } from \"@lpb-work/pi-coding-agent\";\nimport { registerNativeSupervisorClient } from \"../../intercom/native-supervisor-channel.ts\";\nimport { resolveCurrentSessionId } from \"../../shared/session-identity.ts\";\nimport type { JsonSchemaObject, ResolvedToolBudget, SubagentState } from \"../../shared/types.ts\";\nimport { resolveWatchPath } from \"../../shared/utils.ts\";\nimport { CHILD_WATCHDOG_CONFIG_ENV } from \"../../watchdog/child-status.ts\";\nimport {\n\trequestWatchdogPermission,\n\ttype WatchdogPermissionRequest,\n\ttype WatchdogPermissionResult,\n} from \"../../watchdog/permission-arbiter.ts\";\nimport { registerChildWatchdog } from \"../../watchdog/register-child.ts\";\nimport { SUBAGENT_WATCHDOG_WARNING_TYPE } from \"../../watchdog/types.ts\";\nimport { drainOutstandingWork } from \"../background/auto-drain.ts\";\nimport {\n\tconsumeSteerRequestsFromDir,\n\tMAX_STEER_QUEUE_SIZE,\n\ttype SteerDeliveryStatus,\n\ttype SteerRequest,\n\tsteerAckPathFromDir,\n\twriteSteerAckAt,\n\twriteSteerCapabilityAt,\n\twriteSteerRequestToDir,\n} from \"../background/control-channel.ts\";\nimport { resolveWaitToolConfig } from \"../background/wait-config.ts\";\nimport { registerWaitTool } from \"../background/wait-tool.ts\";\nimport {\n\tdecodePermissionRules,\n\tPERMISSION_AUDIT_PATH_ENV,\n\tPERMISSION_POLICY_ENV,\n\tpermissionDecision,\n} from \"./permissions.ts\";\nimport {\n\tSUBAGENT_CHILD_AGENT_ENV,\n\tSUBAGENT_CHILD_INDEX_ENV,\n\tSUBAGENT_FANOUT_CHILD_ENV,\n\tSUBAGENT_STEER_ACK_DIR_ENV,\n\tSUBAGENT_STEER_CAPABILITY_ENV,\n\tSUBAGENT_STEER_INBOX_ENV,\n} from \"./pi-args.ts\";\nimport {\n\tisRuntimeAcknowledgedExtensionId,\n\tRUNTIME_EXTENSION_ACK_EVENT,\n\tRUNTIME_EXTENSION_ACK_PATH_ENV,\n\twriteRuntimeAcknowledgedExtensions,\n} from \"./runtime-acknowledged-extensions.ts\";\nimport {\n\tcreateStructuredOutputToolParameters,\n\tSTRUCTURED_OUTPUT_CAPTURE_ENV,\n\tSTRUCTURED_OUTPUT_SCHEMA_ENV,\n\tvalidateStructuredOutputValue,\n} from \"./structured-output.ts\";\nimport {\n\tCHILD_TOOL_DIAGNOSTIC_PATH_ENV,\n\ttype ChildToolDiagnostic,\n\tMCP_DIRECT_CHILD_TOOLS_ENV,\n\tREQUIRED_CHILD_TOOLS_ENV,\n\twriteChildToolDiagnostic,\n} from \"./tool-availability.ts\";\nimport {\n\tdecodeToolBudgetEnv,\n\tshouldBlockToolForBudget,\n\tTOOL_BUDGET_ENV,\n\tTOOL_BUDGET_ZERO_AUTH_ENV,\n\ttoolBudgetBlockedMessage,\n\ttoolBudgetSoftNudge,\n} from \"./tool-budget.ts\";\n\nconst SUBAGENT_INHERIT_PROJECT_CONTEXT_ENV = \"PI_SUBAGENT_INHERIT_PROJECT_CONTEXT\";\nconst SUBAGENT_INHERIT_SKILLS_ENV = \"PI_SUBAGENT_INHERIT_SKILLS\";\nexport const SUBAGENT_INTERCOM_SESSION_NAME_ENV = \"PI_SUBAGENT_INTERCOM_SESSION_NAME\";\n\nconst STRUCTURED_OUTPUT_INSTRUCTIONS = [\n\t\"This subagent step has a strict structured output contract.\",\n\t\"Your final action must be to call the `structured_output` tool with JSON matching the provided schema.\",\n\t\"Do not rely on prose-only completion; if you do not call `structured_output`, the parent will fail this step.\",\n].join(\"\\n\");\n\nexport const CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS = [\n\t\"You are a child subagent, not the parent orchestrator.\",\n\t\"The parent session owns delegation, orchestration, review fanout, and follow-up worker launches.\",\n\t\"Ignore prior parent-only orchestration instructions in inherited conversation history.\",\n\t\"Do not propose or run subagents. Complete only your assigned role-specific task with the tools available to you.\",\n\t\"If you need to edit files, use the available editing tools. Do not print tool-call syntax, patches, or pseudo-tool calls as text.\",\n].join(\"\\n\");\n\nexport const CHILD_FANOUT_BOUNDARY_INSTRUCTIONS = [\n\t\"You are a child subagent with explicit fanout responsibility for this assigned task.\",\n\t\"The parent session owns final orchestration, acceptance, and follow-up implementation launches.\",\n\t\"You may use the `subagent` tool only for the fanout work explicitly requested in this task.\",\n\t\"Do not broaden yourself into general parent orchestration. Do not launch follow-up workers unless the task explicitly asks for that.\",\n\t\"The maxSubagentDepth cap still applies and may block further fanout.\",\n\t\"If you need to edit files, use the available editing tools. Do not print tool-call syntax, patches, or pseudo-tool calls as text.\",\n].join(\"\\n\");\n\nconst PARENT_ONLY_CUSTOM_MESSAGE_TYPES = new Set([\n\t\"subagent-orchestration-instructions\",\n\t\"subagent-slash-result\",\n\t\"subagent-slash-text-result\",\n\t\"subagent-notify\",\n\t\"subagent_control_notice\",\n\t\"subagent-control\",\n\t\"subagent-control-notice\",\n]);\nconst SUBAGENT_ORCHESTRATION_SKILL_NAME_PATTERN = /<name>\\s*pi-subagents\\s*<\\/name>/;\nconst PROJECT_CONTEXT_HEADER = \"\\n\\n# Project Context\\n\\nProject-specific instructions and guidelines:\\n\\n\";\nconst SKILLS_HEADER = \"\\n\\nThe following skills provide specialized instructions for specific tasks.\";\nconst DATE_HEADER = \"\\nCurrent date:\";\n\nfunction readBooleanEnv(name: string): boolean | undefined {\n\tconst value = process.env[name];\n\tif (value === undefined) return undefined;\n\treturn value !== \"0\";\n}\n\nfunction readRequiredChildTools(): string[] | undefined {\n\tconst encoded = process.env[REQUIRED_CHILD_TOOLS_ENV]?.trim();\n\tif (!encoded) return undefined;\n\tconst required = JSON.parse(encoded) as unknown;\n\tif (!Array.isArray(required) || required.some((name) => typeof name !== \"string\" || !name)) {\n\t\tthrow new Error(`Invalid ${REQUIRED_CHILD_TOOLS_ENV} payload.`);\n\t}\n\treturn required;\n}\n\nfunction readMcpDirectChildTools(): string[] | undefined {\n\tconst encoded = process.env[MCP_DIRECT_CHILD_TOOLS_ENV]?.trim();\n\tif (!encoded) return undefined;\n\ttry {\n\t\tconst tools = JSON.parse(encoded) as unknown;\n\t\tif (!Array.isArray(tools) || tools.some((name) => typeof name !== \"string\" || !name)) return undefined;\n\t\treturn tools;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction refreshChildToolDiagnostic(pi: ExtensionAPI): ChildToolDiagnostic | undefined {\n\tconst filePath = process.env[CHILD_TOOL_DIAGNOSTIC_PATH_ENV]?.trim();\n\tconst required = readRequiredChildTools();\n\tif (!filePath || !required) return undefined;\n\tconst available = pi.getAllTools().map((tool) => tool.name);\n\treturn writeChildToolDiagnostic(\n\t\tfilePath,\n\t\trequired,\n\t\tavailable,\n\t\tprocess.env[SUBAGENT_CHILD_AGENT_ENV]?.trim(),\n\t\treadMcpDirectChildTools(),\n\t);\n}\n\nfunction registerRuntimeExtensionAcknowledgements(pi: ExtensionAPI): void {\n\tconst outputPath = process.env[RUNTIME_EXTENSION_ACK_PATH_ENV]?.trim();\n\tif (!outputPath) return;\n\tconst ids: string[] = [];\n\tlet finalized = false;\n\tconst acknowledge = (payload: unknown): undefined => {\n\t\tif (finalized || !payload || typeof payload !== \"object\") return undefined;\n\t\tconst id = (payload as { id?: unknown }).id;\n\t\tif (isRuntimeAcknowledgedExtensionId(id)) ids.push(id);\n\t\treturn undefined;\n\t};\n\tconst finalize = (): undefined => {\n\t\tif (finalized) return undefined;\n\t\tfinalized = true;\n\t\twriteRuntimeAcknowledgedExtensions(outputPath, ids);\n\t\treturn undefined;\n\t};\n\ttry {\n\t\tconst events = (pi as { events?: { on?: (event: string, handler: (payload: unknown) => unknown) => unknown } })\n\t\t\t.events;\n\t\tevents?.on?.(RUNTIME_EXTENSION_ACK_EVENT, acknowledge);\n\t\tconst onRuntimeEvent = pi.on as unknown as (\n\t\t\tevent: string,\n\t\t\thandler: (event?: unknown, ctx?: unknown) => unknown,\n\t\t) => void;\n\t\tonRuntimeEvent(\"agent_end\", finalize);\n\t\tonRuntimeEvent(\"session_shutdown\", finalize);\n\t} catch {\n\t\t// Acknowledgement collection is optional observability and must not affect child execution.\n\t}\n}\n\nfunction findSectionEnd(prompt: string, startIndex: number, nextHeaders: string[]): number {\n\tlet endIndex = prompt.length;\n\tfor (const header of nextHeaders) {\n\t\tconst index = prompt.indexOf(header, startIndex);\n\t\tif (index !== -1 && index < endIndex) {\n\t\t\tendIndex = index;\n\t\t}\n\t}\n\treturn endIndex;\n}\n\nexport function stripProjectContext(prompt: string): string {\n\tconst startIndex = prompt.indexOf(PROJECT_CONTEXT_HEADER);\n\tif (startIndex === -1) return prompt;\n\tconst endIndex = findSectionEnd(prompt, startIndex + PROJECT_CONTEXT_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);\n\treturn `${prompt.slice(0, startIndex)}${prompt.slice(endIndex)}`;\n}\n\nexport function stripInheritedSkills(prompt: string): string {\n\tconst startIndex = prompt.indexOf(SKILLS_HEADER);\n\tif (startIndex === -1) return prompt;\n\tconst endIndex = findSectionEnd(prompt, startIndex + SKILLS_HEADER.length, [DATE_HEADER]);\n\treturn `${prompt.slice(0, startIndex)}${prompt.slice(endIndex)}`;\n}\n\nexport function stripSubagentOrchestrationSkill(prompt: string): string {\n\treturn prompt\n\t\t.replace(/\\n{0,2}<skill\\s+name=[\"']pi-subagents[\"'][^>]*>[\\s\\S]*?<\\/skill>\\n{0,2}/g, \"\\n\\n\")\n\t\t.replace(/[ \\t]*<skill>\\s*[\\s\\S]*?<\\/skill>\\s*/g, (block) =>\n\t\t\tSUBAGENT_ORCHESTRATION_SKILL_NAME_PATTERN.test(block) ? \"\" : block,\n\t\t);\n}\n\nfunction stripChildBoundaryInstructions(prompt: string): string {\n\tlet rewritten = prompt;\n\tfor (const boundary of [CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS, CHILD_FANOUT_BOUNDARY_INSTRUCTIONS]) {\n\t\trewritten = rewritten.split(boundary).join(\"\");\n\t}\n\treturn rewritten.replace(/^(?:[ \\t]*\\r?\\n)+/, \"\");\n}\n\nexport function rewriteSubagentPrompt(\n\tprompt: string,\n\toptions: { inheritProjectContext: boolean; inheritSkills: boolean; fanoutChild?: boolean },\n): string {\n\tlet rewritten = prompt;\n\tif (!options.inheritProjectContext) {\n\t\trewritten = stripProjectContext(rewritten);\n\t}\n\tif (!options.inheritSkills) {\n\t\trewritten = stripInheritedSkills(rewritten);\n\t}\n\trewritten = stripSubagentOrchestrationSkill(rewritten);\n\trewritten = stripChildBoundaryInstructions(rewritten);\n\tconst boundary = options.fanoutChild ? CHILD_FANOUT_BOUNDARY_INSTRUCTIONS : CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS;\n\tconst structured = process.env[STRUCTURED_OUTPUT_CAPTURE_ENV] ? `\\n\\n${STRUCTURED_OUTPUT_INSTRUCTIONS}` : \"\";\n\treturn `${boundary}${structured}\\n\\n${rewritten}`;\n}\n\nfunction isParentOnlySubagentMessage(message: unknown): boolean {\n\tconst m = message as { role?: string; customType?: string };\n\tif (m?.role !== \"custom\" || typeof m.customType !== \"string\") return false;\n\tif (m.customType === SUBAGENT_WATCHDOG_WARNING_TYPE) return true;\n\treturn PARENT_ONLY_CUSTOM_MESSAGE_TYPES.has(m.customType);\n}\n\nfunction isSubagentToolResultMessage(message: unknown): boolean {\n\tconst m = message as { role?: string; toolName?: string };\n\treturn m?.role === \"toolResult\" && m.toolName === \"subagent\";\n}\n\nfunction isSubagentToolCallBlock(block: unknown): boolean {\n\tconst b = block as { type?: string; name?: string };\n\treturn b?.type === \"toolCall\" && b.name === \"subagent\";\n}\n\nconst PORTABLE_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;\nconst COMPOSITE_TOOL_ID_APIS = new Set([\n\t\"azure-openai-responses\",\n\t\"openai-codex-responses\",\n\t\"openai-completions\",\n\t\"openai-responses\",\n]);\n\nfunction portableToolId(id: string): string {\n\tif (PORTABLE_TOOL_ID_PATTERN.test(id)) return id;\n\treturn `tool_${Buffer.from(id).toString(\"base64url\") || \"empty\"}`;\n}\n\nfunction sanitizeToolHistoryMessage(message: unknown): unknown {\n\tconst m = message as { role?: string; content?: unknown; toolCallId?: unknown };\n\tif (m?.role === \"toolResult\" && typeof m.toolCallId === \"string\") {\n\t\tconst toolCallId = portableToolId(m.toolCallId);\n\t\treturn toolCallId === m.toolCallId ? message : { ...m, toolCallId };\n\t}\n\tif (m?.role !== \"assistant\" || !Array.isArray(m.content)) return message;\n\tlet changed = false;\n\tconst content = m.content.map((block) => {\n\t\tconst b = block as { type?: string; id?: unknown };\n\t\tif (b?.type !== \"toolCall\" || typeof b.id !== \"string\") return block;\n\t\tconst id = portableToolId(b.id);\n\t\tif (id === b.id) return block;\n\t\tchanged = true;\n\t\treturn { ...b, id };\n\t});\n\treturn changed ? { ...m, content } : message;\n}\n\nfunction stripAssistantSubagentToolCallBlocks(message: unknown): unknown | undefined {\n\tconst m = message as { role?: string; content?: unknown };\n\tif (m?.role !== \"assistant\" || !Array.isArray(m.content)) return message;\n\tconst filteredContent = m.content.filter((block) => !isSubagentToolCallBlock(block));\n\tif (filteredContent.length === m.content.length) return message;\n\tif (filteredContent.length === 0) return undefined;\n\treturn { ...m, content: filteredContent };\n}\n\nexport function stripParentOnlySubagentMessages(\n\tmessages: unknown[],\n\toptions: { sanitizeToolIds?: boolean } = {},\n): unknown[] {\n\tconst preserveCurrentFanoutToolHistory = process.env[SUBAGENT_FANOUT_CHILD_ENV] === \"1\";\n\tconst sanitizeToolIds = options.sanitizeToolIds ?? true;\n\tlet changed = false;\n\tconst filtered: unknown[] = [];\n\tfor (const message of messages) {\n\t\tif (\n\t\t\tisParentOnlySubagentMessage(message) ||\n\t\t\t(!preserveCurrentFanoutToolHistory && isSubagentToolResultMessage(message))\n\t\t) {\n\t\t\tchanged = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconst stripped = preserveCurrentFanoutToolHistory ? message : stripAssistantSubagentToolCallBlocks(message);\n\t\tif (stripped === undefined) {\n\t\t\tchanged = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconst sanitized = sanitizeToolIds ? sanitizeToolHistoryMessage(stripped) : stripped;\n\t\tif (stripped !== message || sanitized !== stripped) changed = true;\n\t\tfiltered.push(sanitized);\n\t}\n\treturn changed ? filtered : messages;\n}\n\nexport function formatSteerMessage(request: SteerRequest): string {\n\treturn [\n\t\trequest.mode === \"follow_up\"\n\t\t\t? \"Queued follow-up from the parent orchestrator:\"\n\t\t\t: \"Mid-run steering from the parent orchestrator:\",\n\t\t\"\",\n\t\trequest.message,\n\t\t\"\",\n\t\t\"Incorporate this guidance at the next safe point. Do not restart the task unless the guidance explicitly asks you to.\",\n\t].join(\"\\n\");\n}\n\nexport function registerPermissionGate(\n\tpi: ExtensionAPI,\n\trequestPermission: (\n\t\trequest: WatchdogPermissionRequest,\n\t) => Promise<WatchdogPermissionResult> = requestWatchdogPermission,\n): void {\n\tconst rules = decodePermissionRules(process.env[PERMISSION_POLICY_ENV]);\n\tif (!rules) return;\n\tconst onRuntimeEvent = pi.on as unknown as (\n\t\tevent: string,\n\t\thandler: (event: { toolName?: string; input?: unknown }, ctx: ExtensionContext) => unknown,\n\t) => void;\n\tonRuntimeEvent(\"tool_call\", async (event, ctx) => {\n\t\tconst toolName = typeof event.toolName === \"string\" ? event.toolName : \"tool\";\n\t\tconst decision = permissionDecision(rules, toolName);\n\t\tif (decision === \"allow\") return undefined;\n\t\tif (decision === \"deny\")\n\t\t\treturn { block: true, reason: `Blocked by pi-subagents permission rule: '${toolName}' is denied.` };\n\t\tconst result = await requestPermission({\n\t\t\tctx,\n\t\t\ttoolName,\n\t\t\targs: event.input ?? {},\n\t\t\trawWatchdogConfig: process.env[CHILD_WATCHDOG_CONFIG_ENV],\n\t\t\tauditPath: process.env[PERMISSION_AUDIT_PATH_ENV],\n\t\t\t...(ctx.signal ? { signal: ctx.signal } : {}),\n\t\t});\n\t\tif (result.approved) return undefined;\n\t\treturn { block: true, reason: `Blocked by pi-subagents permission rule: ${result.reason}` };\n\t});\n}\n\nfunction registerToolBudget(pi: ExtensionAPI, budget: ResolvedToolBudget | undefined): void {\n\tif (!budget) return;\n\tlet toolCount = 0;\n\tlet softNudged = false;\n\tconst sendUserMessage = (pi as { sendUserMessage?: (content: string, options: { deliverAs: \"steer\" }) => unknown })\n\t\t.sendUserMessage;\n\tconst onRuntimeEvent = pi.on as unknown as (\n\t\tevent: string,\n\t\thandler: (event: { toolName?: string }) => unknown,\n\t) => void;\n\tonRuntimeEvent(\"tool_call\", (event) => {\n\t\tconst toolName = typeof event.toolName === \"string\" ? event.toolName : \"tool\";\n\t\ttoolCount++;\n\t\tif (budget.soft !== undefined && toolCount >= budget.soft && !softNudged) {\n\t\t\tsoftNudged = true;\n\t\t\ttry {\n\t\t\t\tsendUserMessage?.(toolBudgetSoftNudge(budget, toolCount), { deliverAs: \"steer\" });\n\t\t\t} catch {\n\t\t\t\t// Budget nudges are advisory; blocking below remains authoritative.\n\t\t\t}\n\t\t}\n\t\tif (!shouldBlockToolForBudget(budget, toolName, toolCount)) return undefined;\n\t\treturn { block: true, reason: toolBudgetBlockedMessage(budget, toolName, toolCount) };\n\t});\n}\n\nexport function registerSteeringInbox(\n\tpi: ExtensionAPI,\n\tdeps: { watch?: typeof fs.watch; nativeRealpath?: (filePath: string) => string } = {},\n): void {\n\tconst steerInbox = process.env[SUBAGENT_STEER_INBOX_ENV]?.trim();\n\tif (!steerInbox) return;\n\tconst capabilityPath = process.env[SUBAGENT_STEER_CAPABILITY_ENV]?.trim();\n\tconst ackDir = process.env[SUBAGENT_STEER_ACK_DIR_ENV]?.trim();\n\tconst sendUserMessage = (\n\t\tpi as { sendUserMessage?: (content: string, options?: { deliverAs: \"steer\" | \"followUp\" }) => unknown }\n\t).sendUserMessage;\n\tconst childIndex = Number(process.env[SUBAGENT_CHILD_INDEX_ENV]);\n\tconst pending = new Map<string, Array<{ request: SteerRequest; deliveryStatus: SteerDeliveryStatus }>>();\n\tconst queued: Array<{ request: SteerRequest; ready: boolean }> = [];\n\tlet disposed = false;\n\tlet agentRunning = false;\n\tlet inTurn = false;\n\tlet flushing = false;\n\tlet started = false;\n\tconst canSteer = typeof sendUserMessage === \"function\";\n\tlet watcher: fs.FSWatcher | undefined;\n\tlet interval: NodeJS.Timeout | undefined;\n\tconst acknowledge = (\n\t\trequest: SteerRequest,\n\t\tstate: \"delivered\" | \"queued\" | \"failed\",\n\t\tmessage: string,\n\t\tdeliveryStatus?: SteerDeliveryStatus,\n\t): void => {\n\t\tif (!ackDir || !Number.isInteger(childIndex) || childIndex < 0) return;\n\t\twriteSteerAckAt(steerAckPathFromDir(ackDir, request.id), {\n\t\t\trequestId: request.id,\n\t\t\tindex: childIndex,\n\t\t\tts: Date.now(),\n\t\t\tstate,\n\t\t\t...(deliveryStatus ? { deliveryStatus } : {}),\n\t\t\tmessage,\n\t\t});\n\t};\n\tconst publishCapability = (): void => {\n\t\tif (!capabilityPath || !Number.isInteger(childIndex) || childIndex < 0) return;\n\t\twriteSteerCapabilityAt(capabilityPath, {\n\t\t\tindex: childIndex,\n\t\t\tpid: process.pid,\n\t\t\treadyAt: Date.now(),\n\t\t\tsupported: canSteer,\n\t\t});\n\t};\n\tconst flush = (): void => {\n\t\tif (disposed || flushing) return;\n\t\tflushing = true;\n\t\ttry {\n\t\t\tconst requests = consumeSteerRequestsFromDir(steerInbox);\n\t\t\tfor (let index = 0; index < requests.length; index++) {\n\t\t\t\tconst request = requests[index]!;\n\t\t\t\tif (!canSteer || typeof sendUserMessage !== \"function\") {\n\t\t\t\t\tacknowledge(request, \"failed\", \"Child Pi session does not support sendUserMessage steering.\");\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst requestedMode = request.mode ?? \"steer\";\n\t\t\t\tconst delivery =\n\t\t\t\t\trequestedMode === \"follow_up\" || (requestedMode === \"auto\" && inTurn)\n\t\t\t\t\t\t? (\"followUp\" as const)\n\t\t\t\t\t\t: (\"steer\" as const);\n\t\t\t\tconst pendingFollowUps = [...pending.values()].reduce(\n\t\t\t\t\t(count, entries) => count + entries.filter((entry) => entry.deliveryStatus === \"queued\").length,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t\tif (delivery === \"followUp\" && queued.length + pendingFollowUps >= MAX_STEER_QUEUE_SIZE) {\n\t\t\t\t\tacknowledge(request, \"failed\", `Follow-up queue is full (${MAX_STEER_QUEUE_SIZE} messages).`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst formatted = formatSteerMessage(request);\n\t\t\t\tconst entries = pending.get(formatted) ?? [];\n\t\t\t\tentries.push({ request, deliveryStatus: delivery === \"followUp\" ? \"queued\" : \"delivered\" });\n\t\t\t\tpending.set(formatted, entries);\n\t\t\t\ttry {\n\t\t\t\t\tsendUserMessage(\n\t\t\t\t\t\tformatted,\n\t\t\t\t\t\trequestedMode === \"auto\" && !agentRunning ? undefined : { deliverAs: delivery },\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tentries.pop();\n\t\t\t\t\tif (entries.length === 0) pending.delete(formatted);\n\t\t\t\t\tacknowledge(request, \"failed\", error instanceof Error ? error.message : String(error));\n\t\t\t\t\tfor (const retry of requests.slice(index + 1)) writeSteerRequestToDir(steerInbox, retry);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tflushing = false;\n\t\t}\n\t};\n\tconst onInput = (event: unknown): undefined => {\n\t\tif (disposed || !event || typeof event !== \"object\") return undefined;\n\t\tconst input = event as { source?: unknown; streamingBehavior?: unknown; text?: unknown; content?: unknown };\n\t\tif (input.source !== \"extension\") return undefined;\n\t\tconst text =\n\t\t\ttypeof input.text === \"string\" ? input.text : typeof input.content === \"string\" ? input.content : undefined;\n\t\tif (!text) return undefined;\n\t\tconst entries = pending.get(text);\n\t\tconst entry = entries?.shift();\n\t\tif (!entry) return undefined;\n\t\tif (entries?.length === 0) pending.delete(text);\n\t\tif (entry.deliveryStatus === \"queued\") {\n\t\t\tqueued.push({ request: entry.request, ready: !inTurn });\n\t\t\tacknowledge(entry.request, \"queued\", \"Pi queued the correlated follow-up input.\", \"queued\");\n\t\t} else {\n\t\t\tacknowledge(entry.request, \"delivered\", \"Pi accepted the correlated steering input.\", \"delivered\");\n\t\t}\n\t\treturn undefined;\n\t};\n\tconst start = (): void => {\n\t\tif (started || disposed) return;\n\t\ttry {\n\t\t\tfs.mkdirSync(steerInbox, { recursive: true });\n\t\t\tpublishCapability();\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tstarted = true;\n\t\ttry {\n\t\t\twatcher = (deps.watch ?? fs.watch)(resolveWatchPath(steerInbox, deps.nativeRealpath), () => flush());\n\t\t\twatcher.on(\"error\", () => {});\n\t\t} catch {\n\t\t\twatcher = undefined;\n\t\t}\n\t\tinterval = setInterval(flush, 250);\n\t\tinterval.unref?.();\n\t};\n\tconst activate = (): undefined => {\n\t\tstart();\n\t\tflush();\n\t\treturn undefined;\n\t};\n\n\tconst onRuntimeEvent = pi.on as unknown as (\n\t\tevent: string,\n\t\thandler: (event: unknown, ctx?: unknown) => unknown,\n\t) => void;\n\t// Register input before the watcher so an accepted extension input cannot race request dispatch.\n\tonRuntimeEvent(\"input\", onInput);\n\tonRuntimeEvent(\"session_start\", () => start());\n\tonRuntimeEvent(\"agent_start\", () => {\n\t\tagentRunning = true;\n\t\treturn activate();\n\t});\n\tonRuntimeEvent(\"agent_end\", () => {\n\t\tagentRunning = false;\n\t\tinTurn = false;\n\t\treturn activate();\n\t});\n\tonRuntimeEvent(\"turn_start\", () => {\n\t\tinTurn = true;\n\t\tconst next = queued.findIndex((entry) => entry.ready);\n\t\tif (next >= 0) {\n\t\t\tconst [entry] = queued.splice(next, 1);\n\t\t\tif (entry)\n\t\t\t\tacknowledge(\n\t\t\t\t\tentry.request,\n\t\t\t\t\t\"delivered\",\n\t\t\t\t\t\"Pi delivered the queued follow-up at a turn boundary.\",\n\t\t\t\t\t\"delivered\",\n\t\t\t\t);\n\t\t}\n\t\treturn activate();\n\t});\n\tonRuntimeEvent(\"turn_end\", () => {\n\t\tinTurn = false;\n\t\tfor (const entry of queued) entry.ready = true;\n\t\treturn activate();\n\t});\n\tfor (const eventName of [\n\t\t\"message_start\",\n\t\t\"message_update\",\n\t\t\"message_end\",\n\t\t\"tool_execution_start\",\n\t\t\"tool_execution_end\",\n\t] as const) {\n\t\tonRuntimeEvent(eventName, activate);\n\t}\n\tonRuntimeEvent(\"session_shutdown\", () => {\n\t\tfor (const entry of queued)\n\t\t\tacknowledge(entry.request, \"failed\", \"Run ended before queued follow-up delivery.\", \"queued\");\n\t\tdisposed = true;\n\t\ttry {\n\t\t\twatcher?.close();\n\t\t} catch {}\n\t\tif (interval) clearInterval(interval);\n\t});\n}\n\nexport default function registerSubagentPromptRuntime(pi: ExtensionAPI): void {\n\tregisterRuntimeExtensionAcknowledgements(pi);\n\tregisterSteeringInbox(pi);\n\tregisterPermissionGate(pi);\n\tregisterToolBudget(\n\t\tpi,\n\t\tdecodeToolBudgetEnv(process.env[TOOL_BUDGET_ENV], { allowZero: process.env[TOOL_BUDGET_ZERO_AUTH_ENV] === \"1\" }),\n\t);\n\tregisterChildWatchdog(pi);\n\tconst waitToolEnabled = resolveWaitToolConfig().enabled;\n\tconst waitState = {\n\t\tbaseCwd: \"\",\n\t\tcurrentSessionId: null,\n\t\tasyncJobs: new Map(),\n\t\tforegroundControls: new Map(),\n\t\tlastForegroundControlId: null,\n\t\tcleanupTimers: new Map(),\n\t\tlastUiContext: null,\n\t\tpoller: null,\n\t\tcompletionSeen: new Map(),\n\t\twatcher: null,\n\t\twatcherRestartTimer: null,\n\t\tresultFileCoalescer: { schedule: () => false, clear: () => {} },\n\t} as unknown as SubagentState;\n\tif (typeof pi.registerTool === \"function\") registerWaitTool(pi, waitState, waitToolEnabled);\n\tlet nativeSupervisorClientRegistered = false;\n\tlet nativeSupervisorFallbackRegistered = false;\n\tconst registerNativeSupervisorClientOnce = (): void => {\n\t\tif (nativeSupervisorClientRegistered) return;\n\t\tnativeSupervisorClientRegistered = true;\n\t\tregisterNativeSupervisorClient(pi, { includeIntercomFallback: false });\n\t};\n\tconst registerNativeSupervisorFallbackOnce = (): void => {\n\t\tregisterNativeSupervisorClientOnce();\n\t\tif (nativeSupervisorFallbackRegistered) return;\n\t\tnativeSupervisorFallbackRegistered = true;\n\t\tregisterNativeSupervisorClient(pi);\n\t};\n\tconst onRuntimeEvent = pi.on as unknown as (\n\t\tevent: string,\n\t\thandler: (event: unknown, ctx?: ExtensionContext) => unknown,\n\t) => void;\n\tonRuntimeEvent(\"session_start\", (_event: unknown, ctx?: ExtensionContext) => {\n\t\tconst sessionManager = (ctx as { sessionManager?: Parameters<typeof resolveCurrentSessionId>[0] } | undefined)\n\t\t\t?.sessionManager;\n\t\twaitState.currentSessionId = sessionManager ? resolveCurrentSessionId(sessionManager) : null;\n\t\tregisterNativeSupervisorClientOnce();\n\t\tif (readRequiredChildTools()?.includes(\"intercom\")) registerNativeSupervisorFallbackOnce();\n\t});\n\tonRuntimeEvent(\"agent_start\", () => {\n\t\trefreshChildToolDiagnostic(pi);\n\t});\n\tonRuntimeEvent(\"agent_end\", async (_event: unknown, ctx: unknown) => {\n\t\tif ((ctx as { hasUI?: boolean } | undefined)?.hasUI === true) return;\n\t\tawait drainOutstandingWork({ state: waitState, events: pi.events });\n\t});\n\tconst structuredOutputPath = process.env[STRUCTURED_OUTPUT_CAPTURE_ENV];\n\tconst structuredSchemaPath = process.env[STRUCTURED_OUTPUT_SCHEMA_ENV];\n\tif (structuredOutputPath && structuredSchemaPath) {\n\t\tconst schema = JSON.parse(fs.readFileSync(structuredSchemaPath, \"utf-8\")) as JsonSchemaObject;\n\t\tconst parameters = createStructuredOutputToolParameters(schema);\n\t\tconst registerTool = pi.registerTool as unknown as (tool: {\n\t\t\tname: string;\n\t\t\tlabel: string;\n\t\t\tdescription: string;\n\t\t\tparameters: unknown;\n\t\t\texecute: (_id: string, params: { value: unknown }) => Promise<unknown>;\n\t\t}) => void;\n\t\tregisterTool({\n\t\t\tname: \"structured_output\",\n\t\t\tlabel: \"Structured Output\",\n\t\t\tdescription: \"Submit the required final structured output for this subagent step. This terminates the step.\",\n\t\t\tparameters: parameters as never,\n\t\t\tasync execute(_id: string, params: { value: unknown }) {\n\t\t\t\tconst validation = await validateStructuredOutputValue(schema, params.value);\n\t\t\t\tif (validation.status === \"invalid\") {\n\t\t\t\t\tthrow new Error(`Structured output validation failed: ${validation.message}`);\n\t\t\t\t}\n\t\t\t\tfs.mkdirSync(path.dirname(structuredOutputPath), { recursive: true });\n\t\t\t\tfs.writeFileSync(structuredOutputPath, JSON.stringify(params.value), { mode: 0o600 });\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Structured output captured.\" }],\n\t\t\t\t\tdetails: { path: structuredOutputPath },\n\t\t\t\t\tterminate: true,\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tonRuntimeEvent(\"context\", (event: unknown, ctx?: ExtensionContext) => {\n\t\tif (!event || typeof event !== \"object\" || !(\"messages\" in event) || !Array.isArray(event.messages))\n\t\t\treturn undefined;\n\t\tconst messages = stripParentOnlySubagentMessages(event.messages, {\n\t\t\tsanitizeToolIds: !COMPOSITE_TOOL_ID_APIS.has(ctx?.model?.api ?? \"\"),\n\t\t});\n\t\tif (messages === event.messages) return undefined;\n\t\treturn { messages };\n\t});\n\n\tonRuntimeEvent(\"before_agent_start\", async (event: unknown) => {\n\t\tif (!event || typeof event !== \"object\" || !(\"systemPrompt\" in event) || typeof event.systemPrompt !== \"string\")\n\t\t\treturn undefined;\n\t\tregisterNativeSupervisorFallbackOnce();\n\t\tconst intercomSessionName = process.env[SUBAGENT_INTERCOM_SESSION_NAME_ENV]?.trim();\n\t\tif (intercomSessionName && typeof pi.setSessionName === \"function\") {\n\t\t\tpi.setSessionName(intercomSessionName);\n\t\t}\n\n\t\tconst inheritProjectContext = readBooleanEnv(SUBAGENT_INHERIT_PROJECT_CONTEXT_ENV);\n\t\tconst inheritSkills = readBooleanEnv(SUBAGENT_INHERIT_SKILLS_ENV);\n\t\tconst fanoutChild = readBooleanEnv(SUBAGENT_FANOUT_CHILD_ENV);\n\t\tlet rewritten = event.systemPrompt;\n\t\tif (inheritProjectContext !== undefined || inheritSkills !== undefined || fanoutChild !== undefined) {\n\t\t\trewritten = rewriteSubagentPrompt(event.systemPrompt, {\n\t\t\t\tinheritProjectContext: inheritProjectContext ?? true,\n\t\t\t\tinheritSkills: inheritSkills ?? true,\n\t\t\t\tfanoutChild: fanoutChild === true,\n\t\t\t});\n\t\t}\n\t\tif (rewritten === event.systemPrompt) return;\n\t\treturn { systemPrompt: rewritten };\n\t});\n}\n"]}