@ashx-j/lunr 0.2.11 → 0.2.13
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/CHANGELOG.md +13 -0
- package/README.md +211 -236
- package/dist/builtin-extensions/ashxj-tui.d.ts +3 -0
- package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.js +28 -11
- package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +0 -2
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/lunr-cron.d.ts +1 -1
- package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-cron.js +1 -1
- package/dist/builtin-extensions/lunr-cron.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/chain-validation.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/chain-validation.js +3 -3
- package/dist/builtin-extensions/pi-subagents/src/extension/chain-validation.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/doctor.d.ts +0 -2
- package/dist/builtin-extensions/pi-subagents/src/extension/doctor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/doctor.js +1 -23
- package/dist/builtin-extensions/pi-subagents/src/extension/doctor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +6 -7
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +7 -14
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +12 -9
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +38 -34
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +32 -47
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +7 -10
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +90 -109
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +3 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +37 -50
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.d.ts +4 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.js +5 -5
- package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +31 -13
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts +4 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +48 -20
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +90 -64
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +6 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +262 -161
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +24 -33
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +25 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +51 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/dynamic-fanout.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/dynamic-fanout.js +20 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/dynamic-fanout.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +4 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +5 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +9 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +2 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +20 -17
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +70 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +153 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/settings.d.ts +13 -8
- package/dist/builtin-extensions/pi-subagents/src/shared/settings.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/settings.js +20 -51
- package/dist/builtin-extensions/pi-subagents/src/shared/settings.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +80 -20
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js +10 -2
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +20 -32
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +23 -449
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +13 -11
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.js +18 -17
- package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.js.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts +2 -2
- package/dist/builtin-extensions/simple-pi-memory.d.ts.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js +41 -17
- package/dist/builtin-extensions/simple-pi-memory.js.map +1 -1
- package/dist/catalog/models.json +1 -1
- package/dist/catalog/providers/amazon-bedrock.json +1 -1
- package/dist/catalog/providers/azure-openai-responses.json +1 -1
- package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
- package/dist/catalog/providers/cloudflare-workers-ai.json +1 -1
- package/dist/catalog/providers/fireworks.json +1 -1
- package/dist/catalog/providers/github-copilot.json +1 -1
- package/dist/catalog/providers/huggingface.json +1 -1
- package/dist/catalog/providers/minimax-cn.json +1 -1
- package/dist/catalog/providers/minimax.json +1 -1
- package/dist/catalog/providers/mistral.json +1 -1
- package/dist/catalog/providers/nvidia.json +1 -1
- package/dist/catalog/providers/openai.json +1 -1
- package/dist/catalog/providers/opencode-go.json +1 -1
- package/dist/catalog/providers/opencode.json +1 -1
- package/dist/catalog/providers/openrouter.json +1 -1
- package/dist/catalog/providers/qwen-cloud-cn.json +1 -1
- package/dist/catalog/providers/qwen-cloud.json +1 -1
- package/dist/catalog/providers/qwen-token-plan-cn.json +1 -1
- package/dist/catalog/providers/qwen-token-plan.json +1 -1
- package/dist/catalog/providers/together.json +1 -1
- package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
- package/dist/catalog/providers/zai-coding-cn.json +1 -1
- package/dist/catalog/providers/zai.json +1 -1
- package/dist/catalog/publication.json +3 -3
- package/dist/core/agent-session.d.ts +7 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +34 -4
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/context-breakdown.d.ts +3 -1
- package/dist/core/context-breakdown.d.ts.map +1 -1
- package/dist/core/context-breakdown.js +5 -2
- package/dist/core/context-breakdown.js.map +1 -1
- package/dist/core/customize.d.ts +2 -0
- package/dist/core/customize.d.ts.map +1 -1
- package/dist/core/customize.js +6 -0
- package/dist/core/customize.js.map +1 -1
- package/dist/core/memory-cap.d.ts +4 -8
- package/dist/core/memory-cap.d.ts.map +1 -1
- package/dist/core/memory-cap.js +8 -8
- package/dist/core/memory-cap.js.map +1 -1
- package/dist/core/permissions.d.ts +2 -0
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +30 -14
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +1 -9
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/rollback.d.ts.map +1 -1
- package/dist/core/rollback.js +1 -1
- package/dist/core/rollback.js.map +1 -1
- package/dist/core/settings-manager.d.ts +16 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +37 -10
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -5
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/subagent-permission-inherit.d.ts +34 -22
- package/dist/core/subagent-permission-inherit.d.ts.map +1 -1
- package/dist/core/subagent-permission-inherit.js +37 -80
- package/dist/core/subagent-permission-inherit.js.map +1 -1
- package/dist/core/swarm.d.ts.map +1 -1
- package/dist/core/swarm.js +13 -7
- package/dist/core/swarm.js.map +1 -1
- package/dist/core/system-prompt.d.ts +6 -4
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +38 -48
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/usage-adapters/openai-codex.d.ts +1 -1
- package/dist/core/usage-adapters/openai-codex.d.ts.map +1 -1
- package/dist/core/usage-adapters/openai-codex.js +22 -17
- package/dist/core/usage-adapters/openai-codex.js.map +1 -1
- package/dist/core/usage-service.d.ts +10 -1
- package/dist/core/usage-service.d.ts.map +1 -1
- package/dist/core/usage-service.js +17 -6
- package/dist/core/usage-service.js.map +1 -1
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +1 -4
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/cron.d.ts.map +1 -1
- package/dist/gateway/cron.js +1 -4
- package/dist/gateway/cron.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +0 -5
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +2 -0
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +21 -0
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +7 -4
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +122 -162
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/usage-view.d.ts +1 -1
- package/dist/modes/interactive/components/usage-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/usage-view.js +7 -4
- package/dist/modes/interactive/components/usage-view.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +55 -96
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/skill-tag-autocomplete.d.ts +13 -0
- package/dist/modes/interactive/skill-tag-autocomplete.d.ts.map +1 -0
- package/dist/modes/interactive/skill-tag-autocomplete.js +72 -0
- package/dist/modes/interactive/skill-tag-autocomplete.js.map +1 -0
- package/docs/compaction.md +23 -23
- package/docs/containerization.md +24 -24
- package/docs/custom-provider.md +18 -18
- package/docs/development.md +16 -15
- package/docs/docs.json +6 -2
- package/docs/extensions.md +82 -80
- package/docs/features.md +102 -0
- package/docs/index.md +25 -19
- package/docs/json.md +7 -7
- package/docs/keybindings.md +4 -4
- package/docs/models.md +2 -2
- package/docs/packages.md +38 -42
- package/docs/prompt-templates.md +4 -4
- package/docs/providers.md +22 -10
- package/docs/quickstart.md +81 -46
- package/docs/rpc.md +7 -13
- package/docs/sdk.md +43 -41
- package/docs/security.md +18 -18
- package/docs/session-format.md +9 -9
- package/docs/sessions.md +13 -12
- package/docs/settings.md +63 -24
- package/docs/shell-aliases.md +2 -2
- package/docs/skills.md +21 -11
- package/docs/terminal-setup.md +5 -5
- package/docs/termux.md +7 -7
- package/docs/themes.md +12 -14
- package/docs/tmux.md +4 -4
- package/docs/tui.md +23 -23
- package/docs/usage.md +112 -87
- package/docs/windows.md +10 -2
- package/examples/README.md +3 -1
- package/examples/extensions/README.md +6 -6
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/README.md +2 -2
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/plan-mode/README.md +3 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/README.md +13 -11
- package/examples/extensions/todo.ts +2 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/README.md +9 -5
- package/package.json +6 -7
- package/dist/builtin-extensions/lunr-behavior.d.ts +0 -44
- package/dist/builtin-extensions/lunr-behavior.d.ts.map +0 -1
- package/dist/builtin-extensions/lunr-behavior.js +0 -213
- package/dist/builtin-extensions/lunr-behavior.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/agents/context-builder.md +0 -46
- package/dist/builtin-extensions/pi-subagents/agents/deep-researcher.md +0 -36
- package/dist/builtin-extensions/pi-subagents/agents/delegate.md +0 -12
- package/dist/builtin-extensions/pi-subagents/agents/oracle.md +0 -73
- package/dist/builtin-extensions/pi-subagents/agents/planner.md +0 -55
- package/dist/builtin-extensions/pi-subagents/agents/research-writer.md +0 -37
- package/dist/builtin-extensions/pi-subagents/agents/researcher.md +0 -52
- package/dist/builtin-extensions/pi-subagents/agents/reviewer.md +0 -79
- package/dist/builtin-extensions/pi-subagents/agents/scout.md +0 -50
- package/dist/builtin-extensions/pi-subagents/agents/worker.md +0 -55
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.d.ts +0 -20
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.js +0 -1273
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.d.ts +0 -49
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.js +0 -252
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.d.ts +0 -3
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.js +0 -6
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.d.ts +0 -3
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.js +0 -23
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.d.ts +0 -8
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.js +0 -143
- package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agents.d.ts +0 -176
- package/dist/builtin-extensions/pi-subagents/src/agents/agents.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/agents.js +0 -1326
- package/dist/builtin-extensions/pi-subagents/src/agents/agents.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.d.ts +0 -7
- package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.js +0 -307
- package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/identity.d.ts +0 -8
- package/dist/builtin-extensions/pi-subagents/src/agents/identity.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/identity.js +0 -30
- package/dist/builtin-extensions/pi-subagents/src/agents/identity.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.d.ts +0 -35
- package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.js +0 -151
- package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.js.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.d.ts +0 -131
- package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.d.ts.map +0 -1
- package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.js +0 -491
- package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.js.map +0 -1
- package/dist/core/behavior-preset.d.ts +0 -60
- package/dist/core/behavior-preset.d.ts.map +0 -1
- package/dist/core/behavior-preset.js +0 -257
- package/dist/core/behavior-preset.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-executor.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAY3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,EASN,KAAK,SAAS,EAId,MAAM,0BAA0B,CAAC;AA8ClC,OAAO,EAGN,KAAK,eAAe,EAGpB,KAAK,aAAa,EAElB,KAAK,OAAO,EACZ,KAAK,eAAe,EAEpB,KAAK,eAAe,EAOpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAErB,KAAK,aAAa,EAgBlB,MAAM,uBAAuB,CAAC;AAG/B,UAAU,SAAS;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IACpC,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,YAAY;IACrB,EAAE,EAAE,YAAY,CAAC;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wBAAwB,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IACpH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IACrE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK;QAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;KAAE,CAAC;IAC7G,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;CAC7D;AAw/FD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG;IAC3D,OAAO,EAAE,CACR,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAC7D,GAAG,EAAE,gBAAgB,KACjB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;CACvC,CAkmBA","sourcesContent":["// @ts-nocheck\nimport { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr\";\nimport { type AgentConfig, type AgentScope } from \"../../agents/agents.ts\";\nimport { planModeWriteSpawnError, snapshotParentPermissionMode } from \"../../../../../core/subagent-permission-inherit.ts\";\nimport { getArtifactsDir, getProjectChainRunsDir } from \"../../shared/artifacts.ts\";\nimport { ChainClarifyComponent, type ChainClarifyResult } from \"./chain-clarify.ts\";\nimport { toModelInfo, type ModelInfo } from \"../../shared/model-info.ts\";\nimport { executeChain } from \"./chain-execution.ts\";\nimport { resolveExecutionAgentScope } from \"../../agents/agent-scope.ts\";\nimport { handleManagementAction } from \"../../agents/agent-management.ts\";\nimport { buildDoctorReport } from \"../../extension/doctor.ts\";\nimport { clearPendingForegroundControlNotices } from \"../../extension/control-notices.ts\";\nimport { runSync } from \"./execution.ts\";\nimport { handleWatchdogToolAction, WATCHDOG_TOOL_ACTIONS } from \"../../watchdog/tool-actions.ts\";\nimport type { MainWatchdogRuntime } from \"../../watchdog/runtime.ts\";\nimport { buildModelCandidates, resolveEffectiveSubagentModel, resolveModelCandidate, resolveTierModelOverride } from \"../shared/model-fallback.ts\";\nimport type { ModelScopeConfig } from \"../shared/model-scope.ts\";\nimport { aggregateParallelOutputs } from \"../shared/parallel-utils.ts\";\nimport { recordRun } from \"../shared/run-history.ts\";\nimport {\n\tbuildChainInstructions,\n\twriteInitialProgressFile,\n\tgetStepAgents,\n\tisParallelStep,\n\tisDynamicParallelStep,\n\tresolveStepBehavior,\n\tsuppressProgressForReadOnlyTask,\n\ttaskDisallowsFileUpdates,\n\ttype ChainStep,\n\ttype ResolvedStepBehavior,\n\ttype SequentialStep,\n\ttype StepOverrides,\n} from \"../../shared/settings.ts\";\nimport { discoverAvailableSkills, normalizeSkillInput } from \"../../agents/skills.ts\";\nimport { buildAsyncRunnerSteps, executeAsyncChain, executeAsyncSingle, formatAsyncStartedMessage, isAsyncAvailable } from \"../background/async-execution.ts\";\nimport type { ScheduledRunAction } from \"../background/scheduled-runs.ts\";\nimport { enqueueChainAppendRequest, readPendingChainAppendRequests, runnerStepOutputNames } from \"../background/chain-append.ts\";\nimport { ChainOutputValidationError, validateChainOutputBindingsWithContext } from \"../shared/chain-outputs.ts\";\nimport { validateExecutionAcceptance } from \"../shared/acceptance.ts\";\nimport { createForkContextResolver, forkedChildRequiresThinkingOff } from \"../../shared/fork-context.ts\";\nimport { lunrContextPolicy } from \"../../shared/lunr-child-context.ts\";\nimport { resolveCurrentSessionId } from \"../../shared/session-identity.ts\";\nimport { applyIntercomBridgeToAgent, INTERCOM_BRIDGE_MARKER, resolveIntercomBridge, resolveIntercomSessionTarget, resolveSubagentIntercomTarget, type IntercomBridgeState } from \"../../intercom/intercom-bridge.ts\";\nimport { formatControlIntercomMessage, formatControlNoticeMessage, resolveControlConfig, shouldNotifyControlEvent } from \"../shared/subagent-control.ts\";\nimport { resolveTurnBudgetConfig } from \"../shared/turn-budget.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\nimport { finalizeSingleOutput, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from \"../shared/single-output.ts\";\nimport { compactForegroundDetails, getSingleResultOutput, mapConcurrent, readStatus, resolveChildCwd, sumResultsCost, sumResultsUsage } from \"../../shared/utils.ts\";\nimport { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from \"../shared/parallel-utils.ts\";\nimport {\n\tattachNestedChildrenToResultChildren,\n\tbuildSubagentResultIntercomPayload,\n\tdeliverSubagentIntercomMessageEvent,\n\tdeliverSubagentResultIntercomEvent,\n\tformatSubagentResultReceipt,\n\tresolveSubagentResultStatus,\n\tstripDetailsOutputsForIntercomReceipt,\n} from \"../../intercom/result-intercom.ts\";\nimport { applySteeringRecoveryAgentConfig, buildRevivedAsyncTask, interruptLiveAsyncResumeTarget, resolveAsyncResumeTarget, resolveAsyncRunLocation } from \"../background/async-resume.ts\";\nimport { deliverInterruptRequest, deliverStopRequest, requestAsyncSteer } from \"../background/control-channel.ts\";\nimport { waitForSteeringAction } from \"../background/steering.ts\";\nimport { steerAsyncRun } from \"./async-steering-action.ts\";\nimport { reconcileAsyncRun } from \"../background/stale-run-reconciler.ts\";\nimport { resolveAsyncRootResultPath } from \"../background/chain-root-attachment.ts\";\nimport { attachRootChildrenToSteps, createNestedRoute, readNestedControlResults, resolveInheritedNestedRouteFromEnv, resolveNestedAsyncDir, resolveNestedParentAddressFromEnv, updateForegroundNestedProjection, writeNestedControlRequest, writeNestedEvent, type NestedRunResolutionScope } from \"../shared/nested-events.ts\";\nimport { resolveSubagentRunId, type ResolvedSubagentRunId } from \"../background/run-id-resolver.ts\";\nimport { formatNestedRunStatusLines } from \"../shared/nested-render.ts\";\nimport { inspectSubagentStatus } from \"../background/run-status.ts\";\nimport { applyForceTopLevelAsyncOverride } from \"../background/top-level-async.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport {\n\ttype AgentProgress,\n\ttype AsyncStatus,\n\ttype AcceptanceInput,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype ControlConfig,\n\ttype ControlEvent,\n\ttype Details,\n\ttype ExtensionConfig,\n\ttype IntercomEventBus,\n\ttype MaxOutputConfig,\n\ttype NestedRouteInfo,\n\ttype NestedRunSummary,\n\ttype ResolvedControlConfig,\n\ttype ResolvedTurnBudget,\n\ttype ResolvedToolBudget,\n\ttype SingleResult,\n\ttype ToolBudgetConfig,\n\ttype TurnBudgetConfig,\n\ttype SubagentRunMode,\n\ttype SubagentState,\n\tASYNC_DIR,\n\tDEFAULT_ARTIFACT_CONFIG,\n\tDEFAULT_FORK_PREAMBLE,\n\tRESULTS_DIR,\n\tSUBAGENT_ACTIONS,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tcheckSubagentDepth,\n\tresolveMaxSubagentSpawnsPerSession,\n\tresolveTopLevelParallelConcurrency,\n\tresolveTopLevelParallelMaxTasks,\n\tresolveChildMaxSubagentDepth,\n\tresolveCurrentMaxSubagentDepth,\n\twrapForkTask,\n} from \"../../shared/types.ts\";\n\nconst MUTATING_MANAGEMENT_ACTIONS = new Set([\"create\", \"update\", \"delete\", \"eject\", \"disable\", \"enable\", \"reset\", \"watchdog.configure\"]);\ninterface TaskParam {\n\tagent: string;\n\ttask: string;\n\tcwd?: string;\n\tcount?: number;\n\toutput?: string | boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\treads?: string[] | boolean;\n\tprogress?: boolean;\n\tmodel?: string;\n\tskill?: string | string[] | boolean;\n\tacceptance?: AcceptanceInput;\n\ttoolBudget?: ToolBudgetConfig;\n}\n\nexport interface SubagentParamsLike {\n\taction?: string;\n\tid?: string;\n\trunId?: string;\n\tdir?: string;\n\tindex?: number;\n\tview?: \"fleet\" | \"transcript\";\n\tlines?: number;\n\tagent?: string;\n\ttask?: string;\n\tmessage?: string;\n\tchain?: ChainStep[];\n\ttasks?: TaskParam[];\n\tconcurrency?: number;\n\tworktree?: boolean;\n\tcontext?: \"fresh\" | \"fork\";\n\tasync?: boolean;\n\tforegroundOnly?: boolean;\n\ttimeoutMs?: number;\n\tmaxRuntimeMs?: number;\n\tturnBudget?: TurnBudgetConfig;\n\ttoolBudget?: ToolBudgetConfig;\n\tclarify?: boolean;\n\tshare?: boolean;\n\tcontrol?: ControlConfig;\n\tsessionDir?: string;\n\tcwd?: string;\n\tmaxOutput?: MaxOutputConfig;\n\tartifacts?: boolean;\n\tincludeProgress?: boolean;\n\tmodel?: string;\n\tthinking?: string | false;\n\tscope?: string;\n\ttarget?: string;\n\tskill?: string | string[] | boolean;\n\toutput?: string | boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\tagentScope?: unknown;\n\tchainDir?: string;\n\tacceptance?: AcceptanceInput;\n\tschedule?: string;\n\tscheduleName?: string;\n}\n\ninterface ExecutorDeps {\n\tpi: ExtensionAPI;\n\tstate: SubagentState;\n\tconfig: ExtensionConfig;\n\tasyncByDefault: boolean;\n\twaitToolEnabled?: boolean;\n\thandleScheduledRunAction?: (params: SubagentParamsLike, ctx: ExtensionContext) => Promise<AgentToolResult<Details>>;\n\twatchdog?: MainWatchdogRuntime;\n\ttempArtifactsDir: string;\n\tgetSubagentSessionRoot: (parentSessionFile: string | null) => string;\n\texpandTilde: (p: string) => string;\n\tdiscoverAgents: (cwd: string, scope: AgentScope) => { agents: AgentConfig[]; modelScope?: ModelScopeConfig };\n\tallowMutatingManagementActions?: boolean;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n}\n\ntype ForkSessionFileForTask = (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\ntype ForkThinkingOverrideForTask = (agentName: string, idx?: number, modelOverride?: string) => AgentConfig[\"thinking\"] | undefined;\n\ninterface ExecutionContextData {\n\tparams: SubagentParamsLike;\n\teffectiveCwd: string;\n\tctx: ExtensionContext;\n\tsignal: AbortSignal;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tagents: AgentConfig[];\n\trunId: string;\n\tshareEnabled: boolean;\n\tsessionRoot: string;\n\tsessionDirForIndex: (idx?: number) => string;\n\tsessionFileForIndex: (idx?: number) => string | undefined;\n\tsessionFileForTask: ForkSessionFileForTask;\n\tthinkingOverrideForTask: ForkThinkingOverrideForTask;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\tbackgroundRequestedWhileClarifying: boolean;\n\teffectiveAsync: boolean;\n\tcontrolConfig: ResolvedControlConfig;\n\tintercomBridge: IntercomBridgeState;\n\tnestedRoute?: NestedRouteInfo;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ResolvedToolBudget;\n\tcontextPolicy: AgentDefaultContextPolicy;\n\tmodelScope?: ModelScopeConfig;\n\tparentSessionId: string | null;\n}\n\nfunction resolveRequestedCwd(runtimeCwd: string, requestedCwd: string | undefined): string {\n\treturn requestedCwd ? path.resolve(runtimeCwd, requestedCwd) : runtimeCwd;\n}\n\nfunction getForegroundControl(state: SubagentState, runId: string | undefined) {\n\tif (runId) return state.foregroundControls.get(runId);\n\tif (state.lastForegroundControlId) {\n\t\tconst latest = state.foregroundControls.get(state.lastForegroundControlId);\n\t\tif (latest) return latest;\n\t}\n\tlet newest: (SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never) | undefined;\n\tfor (const control of state.foregroundControls.values()) {\n\t\tif (!newest || control.updatedAt > newest.updatedAt) newest = control;\n\t}\n\treturn newest;\n}\n\nfunction formatForegroundActivity(control: SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never): string | undefined {\n\tconst facts: string[] = [];\n\tif (control.currentTool && control.currentToolStartedAt) facts.push(`tool ${control.currentTool} for ${Math.floor(Math.max(0, Date.now() - control.currentToolStartedAt) / 1000)}s`);\n\telse if (control.currentTool) facts.push(`tool ${control.currentTool}`);\n\tif (control.currentPath) facts.push(`path ${control.currentPath}`);\n\tif (control.turnCount !== undefined) facts.push(`${control.turnCount} turns`);\n\tif (control.tokens !== undefined) facts.push(`${control.tokens} tokens`);\n\tif (control.toolCount !== undefined) facts.push(`${control.toolCount} tools`);\n\tif (!control.lastActivityAt) {\n\t\tif (control.currentActivityState === \"needs_attention\") return [\"needs attention\", ...facts].join(\" | \");\n\t\tif (control.currentActivityState === \"active_long_running\") return [\"active but long-running\", ...facts].join(\" | \");\n\t\treturn facts.length ? facts.join(\" | \") : undefined;\n\t}\n\tconst seconds = Math.floor(Math.max(0, Date.now() - control.lastActivityAt) / 1000);\n\tif (control.currentActivityState === \"needs_attention\") return [`no activity for ${seconds}s`, ...facts].join(\" | \");\n\tif (control.currentActivityState === \"active_long_running\") return [`active but long-running; last activity ${seconds}s ago`, ...facts].join(\" | \");\n\treturn [`active ${seconds}s ago`, ...facts].join(\" | \");\n}\n\nfunction nestedResolutionScopeForExecutor(deps: ExecutorDeps): NestedRunResolutionScope | undefined {\n\tif (deps.allowMutatingManagementActions !== false) return undefined;\n\tconst route = resolveInheritedNestedRouteFromEnv();\n\tconst address = route ? resolveNestedParentAddressFromEnv() : undefined;\n\treturn {\n\t\troutes: route ? [route] : [],\n\t\t...(address ? { descendantOf: { parentRunId: address.parentRunId, ...(address.parentStepIndex !== undefined ? { parentStepIndex: address.parentStepIndex } : {}) } } : {}),\n\t};\n}\n\nfunction trustedSessionRootsForStatus(ctx: ExtensionContext, deps: ExecutorDeps): string[] {\n\tconst roots = deps.config.defaultSessionDir ? [path.resolve(deps.expandTilde(deps.config.defaultSessionDir))] : [];\n\tconst parentSessionFile = ctx.sessionManager.getSessionFile() ?? null;\n\tif (parentSessionFile) roots.push(deps.getSubagentSessionRoot(parentSessionFile));\n\treturn [...new Set(roots)];\n}\n\nfunction reserveSubagentSpawns(input: { state: SubagentState; config: ExtensionConfig; sessionId: string | null; requested: number; mode: \"single\" | \"parallel\" | \"chain\" }): AgentToolResult<Details> | undefined {\n\tif (input.requested <= 0) return undefined;\n\tconst maxSpawns = resolveMaxSubagentSpawnsPerSession(input.config.maxSubagentSpawnsPerSession);\n\tif (maxSpawns === undefined) return undefined;\n\tif (input.state.subagentSpawns?.sessionId !== input.sessionId) {\n\t\tinput.state.subagentSpawns = { sessionId: input.sessionId, count: 0 };\n\t}\n\tconst used = input.state.subagentSpawns.count;\n\tif (used + input.requested > maxSpawns) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Subagent spawn limit reached for this session (${used}/${maxSpawns} used, ${input.requested} requested). Complete the work directly or start a new session.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: input.mode, results: [] },\n\t\t};\n\t}\n\tinput.state.subagentSpawns.count = used + input.requested;\n\treturn undefined;\n}\n\nfunction countRequestedSubagentSpawns(params: SubagentParamsLike, config: ExtensionConfig): number {\n\tif (params.tasks) return params.tasks.length;\n\tif (params.chain) {\n\t\treturn params.chain.reduce((total, step) => {\n\t\t\tif (isDynamicParallelStep(step)) return total + (step.expand.maxItems ?? config.chain?.dynamicFanout?.maxItems ?? 0);\n\t\t\treturn total + getStepAgents(step).length;\n\t\t}, 0);\n\t}\n\treturn params.agent ? 1 : 0;\n}\n\nfunction foregroundStatusResult(control: SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never): AgentToolResult<Details> {\n\tlet nestedWarning: string | undefined;\n\ttry {\n\t\tupdateForegroundNestedProjection(control);\n\t} catch (error) {\n\t\tnestedWarning = `Nested status unavailable: ${error instanceof Error ? error.message : String(error)}`;\n\t}\n\tconst activity = formatForegroundActivity(control);\n\tconst lines = [\n\t\t`Run: ${control.runId}`,\n\t\t\"State: running\",\n\t\t`Mode: ${control.mode}`,\n\t\tcontrol.currentAgent ? `Current: ${control.currentAgent}${control.currentIndex !== undefined ? ` step ${control.currentIndex + 1}` : \"\"}` : undefined,\n\t\tactivity ? `Activity: ${activity}` : undefined,\n\t].filter((line): line is string => Boolean(line));\n\tlines.push(...formatNestedRunStatusLines(control.nestedChildren, { indent: \"\", commandHints: true, maxLines: 20 }));\n\tif (nestedWarning) lines.push(`Warning: ${nestedWarning}`);\n\treturn { content: [{ type: \"text\", text: lines.join(\"\\n\") }], details: { mode: \"management\", results: [] } };\n}\n\nfunction trimRememberedForegroundRuns(state: SubagentState): void {\n\tif (!state.foregroundRuns) return;\n\twhile (state.foregroundRuns.size > 50) {\n\t\tconst oldestTerminal = [...state.foregroundRuns.values()]\n\t\t\t.filter((run) => !run.children.some((child) => child.status === \"detached\"))\n\t\t\t.sort((left, right) => left.updatedAt - right.updatedAt)[0];\n\t\tif (!oldestTerminal) break;\n\t\tstate.foregroundRuns.delete(oldestTerminal.runId);\n\t}\n}\n\nfunction rememberForegroundRun(state: SubagentState, input: { runId: string; mode: \"single\" | \"parallel\" | \"chain\"; cwd: string; sessionId: string | null; results: SingleResult[] }): void {\n\tstate.foregroundRuns ??= new Map();\n\tconst previous = state.foregroundRuns.get(input.runId);\n\tconst updatedAt = Date.now();\n\tstate.foregroundRuns.set(input.runId, {\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tcwd: input.cwd,\n\t\t...(input.sessionId ? { sessionId: input.sessionId } : {}),\n\t\tupdatedAt,\n\t\tchildren: input.results.map((result, index) => {\n\t\t\tconst child = {\n\t\t\t\tagent: result.agent,\n\t\t\t\tindex,\n\t\t\t\tstatus: resolveSubagentResultStatus({ exitCode: result.exitCode, interrupted: result.interrupted, detached: result.detached }),\n\t\t\t\tupdatedAt,\n\t\t\t\t...(result.exitCode !== undefined ? { exitCode: result.exitCode } : {}),\n\t\t\t\t...(result.error ? { error: result.error } : {}),\n\t\t\t\t...(result.finalOutput ? { finalOutput: result.finalOutput } : {}),\n\t\t\t\t...(result.outputMode ? { outputMode: result.outputMode } : {}),\n\t\t\t\t...(result.savedOutputPath ? { savedOutputPath: result.savedOutputPath } : {}),\n\t\t\t\t...(result.outputSaveError ? { outputSaveError: result.outputSaveError } : {}),\n\t\t\t\t...(result.sessionFile ? { sessionFile: result.sessionFile } : {}),\n\t\t\t\t...(result.artifactPaths ? { artifactPaths: result.artifactPaths } : {}),\n\t\t\t\t...(result.transcriptPath ? { transcriptPath: result.transcriptPath } : {}),\n\t\t\t\t...(result.transcriptError ? { transcriptError: result.transcriptError } : {}),\n\t\t\t\t...(result.detachedReason ? { detachedReason: result.detachedReason } : {}),\n\t\t\t\t...(result.acceptance ? { acceptance: result.acceptance } : {}),\n\t\t\t};\n\t\t\tconst recovered = previous?.children[index];\n\t\t\treturn child.status === \"detached\" && recovered && recovered.status !== \"detached\" ? recovered : child;\n\t\t}),\n\t});\n\ttrimRememberedForegroundRuns(state);\n}\n\nfunction updateRememberedForegroundChild(state: SubagentState, input: { runId: string; mode: \"single\" | \"parallel\" | \"chain\"; cwd: string; sessionId: string | null; index: number; result: SingleResult; events: IntercomEventBus }): void {\n\tstate.foregroundRuns ??= new Map();\n\tconst updatedAt = Date.now();\n\tlet run = state.foregroundRuns.get(input.runId);\n\tif (!run) {\n\t\trun = { runId: input.runId, mode: input.mode, cwd: input.cwd, ...(input.sessionId ? { sessionId: input.sessionId } : {}), updatedAt, children: [] };\n\t\tstate.foregroundRuns.set(input.runId, run);\n\t}\n\trun.updatedAt = updatedAt;\n\tconst child = run.children[input.index] ?? { agent: input.result.agent, index: input.index, status: \"detached\" as const };\n\trun.children[input.index] = {\n\t\t...child,\n\t\tagent: input.result.agent,\n\t\tindex: input.index,\n\t\tstatus: input.result.acceptance?.status === \"rejected\"\n\t\t\t? \"failed\"\n\t\t\t: resolveSubagentResultStatus({ exitCode: input.result.exitCode, interrupted: input.result.interrupted, detached: false }),\n\t\tupdatedAt,\n\t\t...(input.result.exitCode !== undefined ? { exitCode: input.result.exitCode } : {}),\n\t\t...(input.result.error ? { error: input.result.error } : {}),\n\t\t...(input.result.finalOutput ? { finalOutput: input.result.finalOutput } : {}),\n\t\toutputMode: input.result.outputMode,\n\t\tsavedOutputPath: input.result.savedOutputPath,\n\t\toutputSaveError: input.result.outputSaveError,\n\t\t...(input.result.sessionFile ? { sessionFile: input.result.sessionFile } : {}),\n\t\t...(input.result.artifactPaths ? { artifactPaths: input.result.artifactPaths } : {}),\n\t\t...(input.result.transcriptPath ? { transcriptPath: input.result.transcriptPath } : {}),\n\t\t...(input.result.transcriptError ? { transcriptError: input.result.transcriptError } : {}),\n\t\t...(input.result.detachedReason ? { detachedReason: input.result.detachedReason } : {}),\n\t\t...(input.result.acceptance ? { acceptance: input.result.acceptance } : {}),\n\t};\n\ttrimRememberedForegroundRuns(state);\n\tconst output = getSingleResultOutput(input.result).trim();\n\tconst success = input.result.exitCode === 0 && input.result.acceptance?.status !== \"rejected\";\n\tconst summary = !success && input.result.error\n\t\t? `${input.result.error}${output ? `\\n\\nOutput:\\n${output}` : \"\"}`\n\t\t: output || input.result.error || \"Detached child exited without final output.\";\n\tinput.events.emit(SUBAGENT_FOREGROUND_COMPLETE_EVENT, {\n\t\tid: `${input.runId}:${input.index}`,\n\t\trunId: input.runId,\n\t\tsource: \"foreground\",\n\t\tmode: input.mode,\n\t\tagent: input.result.agent,\n\t\tsuccess,\n\t\tsummary,\n\t\texitCode: input.result.exitCode,\n\t\tstate: success ? \"complete\" : \"failed\",\n\t\ttimestamp: updatedAt,\n\t\tcwd: input.cwd,\n\t\tsessionFile: input.result.sessionFile,\n\t\tsessionId: input.sessionId,\n\t\ttaskIndex: input.index,\n\t});\n}\n\nfunction resolveForegroundResumeTarget(params: SubagentParamsLike, state: SubagentState): { runId: string; mode: \"single\" | \"parallel\" | \"chain\"; state: \"complete\"; agent: string; index: number; intercomTarget: string; cwd: string; sessionFile: string } | undefined {\n\tconst requested = (params.id ?? params.runId)?.trim();\n\tif (!requested || !state.foregroundRuns?.size || !state.currentSessionId) return undefined;\n\tconst sessionRuns = [...state.foregroundRuns.values()].filter((run) => run.sessionId === state.currentSessionId);\n\tconst direct = sessionRuns.find((run) => run.runId === requested);\n\tconst matches = direct ? [direct] : sessionRuns.filter((run) => run.runId.startsWith(requested));\n\tif (matches.length === 0) return undefined;\n\tif (matches.length > 1) throw new Error(`Ambiguous foreground run id prefix '${requested}' matched: ${matches.map((run) => run.runId).join(\", \")}. Provide a longer id.`);\n\tconst run = matches[0]!;\n\tif (run.children.some((child) => child.status === \"detached\")) throw new Error(`Foreground run '${run.runId}' is detached for intercom coordination and cannot be revived safely while any child may still be live. Reply to the supervisor request first, then wait with subagent_wait({ id: \"${run.runId}\" }); use status to recover the result and do not launch a replacement while it remains detached.`);\n\tif (run.children.length > 1 && params.index === undefined) throw new Error(`Foreground run '${run.runId}' has ${run.children.length} children. Provide index to choose one.`);\n\tconst index = params.index ?? 0;\n\tif (!Number.isInteger(index)) throw new Error(`Foreground run '${run.runId}' index must be an integer.`);\n\tif (index < 0 || index >= run.children.length) throw new Error(`Foreground run '${run.runId}' has ${run.children.length} children. Index ${index} is out of range.`);\n\tconst child = run.children[index]!;\n\tif (!child.sessionFile) throw new Error(`Foreground run '${run.runId}' child ${index} does not have a persisted session file to resume from.`);\n\tif (path.extname(child.sessionFile) !== \".jsonl\") throw new Error(`Foreground run '${run.runId}' child ${index} session file must be a .jsonl file: ${child.sessionFile}`);\n\tconst sessionFile = path.resolve(child.sessionFile);\n\tif (!fs.existsSync(sessionFile)) throw new Error(`Foreground run '${run.runId}' child ${index} session file does not exist: ${child.sessionFile}`);\n\treturn { runId: run.runId, mode: run.mode, state: \"complete\", agent: child.agent, index, intercomTarget: resolveSubagentIntercomTarget(run.runId, child.agent, index), cwd: run.cwd, sessionFile };\n}\n\ntype AsyncResumeSourceTarget = ReturnType<typeof resolveAsyncResumeTarget> & { source: \"async\" };\ntype ForegroundResumeSourceTarget = NonNullable<ReturnType<typeof resolveForegroundResumeTarget>> & { kind: \"revive\"; source: \"foreground\" };\ntype NestedResumeSourceTarget = {\n\tkind: \"revive\";\n\tsource: \"nested\";\n\trunId: string;\n\tstate: \"complete\" | \"failed\" | \"paused\" | \"stopped\";\n\tagent: string;\n\tindex: number;\n\tintercomTarget: string;\n\tcwd?: string;\n\tsessionFile: string;\n};\ntype ResumeSourceTarget = AsyncResumeSourceTarget | ForegroundResumeSourceTarget | NestedResumeSourceTarget;\n\nfunction isAsyncRunNotFound(error: unknown): boolean {\n\treturn error instanceof Error && error.message.startsWith(\"Async run not found.\");\n}\n\nfunction isResumeAmbiguity(error: unknown): boolean {\n\treturn error instanceof Error && /Ambiguous .*run id prefix/.test(error.message);\n}\n\nfunction resumeTargetExact(target: { runId: string } | undefined, requested: string): boolean {\n\treturn target?.runId === requested;\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction isExactResumeError(error: unknown, source: \"async\" | \"foreground\", requested: string): boolean {\n\tif (!(error instanceof Error) || !requested) return false;\n\treturn new RegExp(`\\\\b${source} run '${escapeRegExp(requested)}'`, \"i\").test(error.message);\n}\n\nfunction resolveResumeTarget(params: SubagentParamsLike, state: SubagentState, options: { asyncRequireSessionFile?: boolean } = {}): ResumeSourceTarget {\n\tconst requested = (params.id ?? params.runId)?.trim() ?? \"\";\n\tlet foregroundTarget: ForegroundResumeSourceTarget | undefined;\n\tlet foregroundError: unknown;\n\tlet asyncTarget: AsyncResumeSourceTarget | undefined;\n\tlet asyncError: unknown;\n\n\ttry {\n\t\tconst target = resolveForegroundResumeTarget(params, state);\n\t\tif (target) foregroundTarget = { kind: \"revive\", source: \"foreground\", ...target };\n\t} catch (error) {\n\t\tforegroundError = error;\n\t}\n\ttry {\n\t\tasyncTarget = { source: \"async\", ...resolveAsyncResumeTarget(params, {}, { requireSessionFile: options.asyncRequireSessionFile }) };\n\t} catch (error) {\n\t\tasyncError = error;\n\t}\n\n\tif (foregroundTarget && asyncTarget) {\n\t\tconst foregroundExact = resumeTargetExact(foregroundTarget, requested);\n\t\tconst asyncExact = resumeTargetExact(asyncTarget, requested);\n\t\tif (foregroundExact && !asyncExact) return foregroundTarget;\n\t\tif (asyncExact && !foregroundExact) return asyncTarget;\n\t\tthrow new Error(`Resume id '${requested}' is ambiguous between foreground run '${foregroundTarget.runId}' and async run '${asyncTarget.runId}'. Provide a full run id.`);\n\t}\n\tif (foregroundTarget) {\n\t\tif (isExactResumeError(asyncError, \"async\", requested)) throw asyncError;\n\t\tif (isResumeAmbiguity(asyncError) && !resumeTargetExact(foregroundTarget, requested)) throw asyncError;\n\t\treturn foregroundTarget;\n\t}\n\tif (asyncTarget) {\n\t\tif (isExactResumeError(foregroundError, \"foreground\", requested)) throw foregroundError;\n\t\tif (isResumeAmbiguity(foregroundError) && !resumeTargetExact(asyncTarget, requested)) throw foregroundError;\n\t\treturn asyncTarget;\n\t}\n\tif (foregroundError && !isAsyncRunNotFound(asyncError)) throw foregroundError;\n\tif (foregroundError) throw foregroundError;\n\tif (asyncError) throw asyncError;\n\tthrow new Error(\"Run not found. Provide id or runId.\");\n}\n\nfunction getAsyncInterruptTarget(\n\tstate: SubagentState,\n\trunId: string | undefined,\n\tlocation?: { asyncDir: string | null; resolvedId?: string },\n\toptions: { fallbackToNewest?: boolean } = {},\n): { asyncId: string; asyncDir: string } | undefined {\n\tif (location?.asyncDir) {\n\t\treturn {\n\t\t\tasyncId: location.resolvedId ?? runId ?? path.basename(location.asyncDir),\n\t\t\tasyncDir: location.asyncDir,\n\t\t};\n\t}\n\tif (runId) {\n\t\tconst direct = state.asyncJobs.get(runId);\n\t\tif (direct) return { asyncId: direct.asyncId, asyncDir: direct.asyncDir };\n\t\tif (options.fallbackToNewest === false) return undefined;\n\t}\n\tlet newest: { asyncId: string; asyncDir: string; updatedAt: number } | undefined;\n\tfor (const job of state.asyncJobs.values()) {\n\t\tif (job.status !== \"running\") continue;\n\t\tif (!newest || (job.updatedAt ?? 0) > newest.updatedAt) {\n\t\t\tnewest = { asyncId: job.asyncId, asyncDir: job.asyncDir, updatedAt: job.updatedAt ?? 0 };\n\t\t}\n\t}\n\treturn newest ? { asyncId: newest.asyncId, asyncDir: newest.asyncDir } : undefined;\n}\n\nfunction emitControlNotification(input: {\n\tpi: ExtensionAPI;\n\tcontrolConfig: ResolvedControlConfig;\n\tintercomBridge: IntercomBridgeState;\n\tevent: ControlEvent;\n}): void {\n\tif (!shouldNotifyControlEvent(input.controlConfig, input.event)) return;\n\tconst childIntercomTarget = input.intercomBridge.active\n\t\t? resolveSubagentIntercomTarget(input.event.runId, input.event.agent, input.event.index)\n\t\t: undefined;\n\tconst payload = {\n\t\tevent: input.event,\n\t\tsource: \"foreground\" as const,\n\t\tchildIntercomTarget,\n\t\tnoticeText: formatControlNoticeMessage(input.event, childIntercomTarget),\n\t};\n\tif (input.controlConfig.notifyChannels.includes(\"event\")) {\n\t\tinput.pi.events.emit(SUBAGENT_CONTROL_EVENT, payload);\n\t}\n\tif (input.event.type !== \"active_long_running\" && input.controlConfig.notifyChannels.includes(\"intercom\") && input.intercomBridge.active && input.intercomBridge.orchestratorTarget) {\n\t\tinput.pi.events.emit(SUBAGENT_CONTROL_INTERCOM_EVENT, {\n\t\t\t...payload,\n\t\t\tto: input.intercomBridge.orchestratorTarget,\n\t\t\tmessage: formatControlIntercomMessage(input.event, childIntercomTarget),\n\t\t});\n\t}\n}\n\nfunction interruptAsyncRun(\n\tstate: SubagentState,\n\trunId: string | undefined,\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean,\n\tlocation?: { asyncDir: string | null; resolvedId?: string },\n): AgentToolResult<Details> | null {\n\tconst target = getAsyncInterruptTarget(state, runId, location);\n\tif (!target) return null;\n\tconst status = reconcileAsyncRun(target.asyncDir, { kill }).status;\n\tif (!status || status.state !== \"running\" || typeof status.pid !== \"number\") {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No running async run with an interrupt-capable pid was found for '${runId ?? \"current\"}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\ttry {\n\t\tdeliverInterruptRequest({ asyncDir: target.asyncDir, pid: status.pid, kill, source: \"interrupt-action\" });\n\t\tconst tracked = state.asyncJobs.get(target.asyncId);\n\t\tif (tracked) {\n\t\t\ttracked.activityState = undefined;\n\t\t\ttracked.updatedAt = Date.now();\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Interrupt requested for async run ${target.asyncId}.` }],\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Failed to interrupt async run ${target.asyncId}: ${message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n}\n\nfunction stopAsyncRun(\n\tstate: SubagentState,\n\trunId: string | undefined,\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean,\n\tlocation?: { asyncDir: string | null; resolvedId?: string },\n): AgentToolResult<Details> | null {\n\tconst target = getAsyncInterruptTarget(state, runId, location, { fallbackToNewest: false });\n\tif (!target) return null;\n\tconst status = reconcileAsyncRun(target.asyncDir, { kill }).status;\n\tif (state.currentSessionId && status?.sessionId !== state.currentSessionId) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Async run '${target.asyncId}' was not found in the active session.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (!status || (status.state !== \"running\" && status.state !== \"queued\")) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No running or queued async run was found for '${runId ?? \"current\"}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\ttry {\n\t\tdeliverStopRequest({ asyncDir: target.asyncDir, pid: typeof status.pid === \"number\" ? status.pid : undefined, kill, source: \"stop-action\" });\n\t\tconst tracked = state.asyncJobs.get(target.asyncId);\n\t\tif (tracked) {\n\t\t\ttracked.activityState = undefined;\n\t\t\ttracked.updatedAt = Date.now();\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Stop requested for async run ${target.asyncId}.` }],\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Failed to stop async run ${target.asyncId}: ${message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n}\n\nfunction duplicateNames(names: string[]): string[] {\n\tconst seen = new Set<string>();\n\tconst duplicates = new Set<string>();\n\tfor (const name of names) {\n\t\tif (seen.has(name)) duplicates.add(name);\n\t\telse seen.add(name);\n\t}\n\treturn [...duplicates];\n}\n\nfunction appendStepToAsyncChain(input: {\n\tparams: SubagentParamsLike;\n\trequestCwd: string;\n\tctx: ExtensionContext;\n\tdeps: ExecutorDeps;\n}): AgentToolResult<Details> {\n\tconst targetRunId = input.params.id ?? input.params.runId;\n\tif (!targetRunId) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"action='append-step' requires id.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (!input.params.chain || input.params.chain.length !== 1) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"action='append-step' requires chain with exactly one step.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst acceptanceErrors = validateExecutionAcceptance(input.params);\n\tif (acceptanceErrors.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step: ${acceptanceErrors.join(\" \")}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tlet resolved: ResolvedSubagentRunId | undefined;\n\ttry {\n\t\tresolved = resolveSubagentRunId(targetRunId, { state: input.deps.state, nested: nestedResolutionScopeForExecutor(input.deps) });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tif (!resolved) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No async chain run found for '${targetRunId}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (resolved.kind !== \"async\" || !resolved.location.asyncDir) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' is not an append-capable async chain run.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst status = readStatus(resolved.location.asyncDir);\n\tif (!status) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No async run status found for '${resolved.id}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (status.mode !== \"chain\") {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' is ${status.mode}; only active chain runs accept appended steps.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (status.state !== \"running\") {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' is ${status.state}; only running chain runs accept appended steps.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst stillInProgress = (status.steps ?? []).some((step) => step.status === \"running\" || step.status === \"pending\") || (status.pendingAppends ?? 0) > 0;\n\tif (!stillInProgress) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' has no running or pending chain steps left; append-step must target an in-progress chain.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst pendingAppendRequests = readPendingChainAppendRequests(resolved.location.asyncDir);\n\tconst reservedOutputNames = new Set<string>([\n\t\t...Object.keys(status.outputs ?? {}),\n\t\t...(status.steps ?? []).map((step) => step.outputName).filter((name): name is string => Boolean(name)),\n\t\t...pendingAppendRequests.flatMap((request) => runnerStepOutputNames(request.steps)),\n\t]);\n\ttry {\n\t\tvalidateChainOutputBindingsWithContext(input.params.chain, { maxItems: input.deps.config.chain?.dynamicFanout?.maxItems }, {\n\t\t\tpriorOutputNames: reservedOutputNames,\n\t\t\tstartStepIndex: status.chainStepCount ?? status.steps?.length ?? 0,\n\t\t});\n\t} catch (error) {\n\t\tif (!(error instanceof ChainOutputValidationError)) throw error;\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step to run '${resolved.id}': ${error.message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst scope: AgentScope = resolveExecutionAgentScope(input.params.agentScope);\n\tconst discoveredForAppend = input.deps.discoverAgents(input.requestCwd, scope);\n\tconst agents = discoveredForAppend.agents;\n\tconst appendWriteSpawnError = planModeWriteSpawnError(\n\t\tsnapshotParentPermissionMode(input.deps.state.currentSessionId),\n\t\tcollectRequestedAgents(input.params, agents),\n\t);\n\tif (appendWriteSpawnError) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: appendWriteSpawnError }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst contextPolicy = resolveExplicitContextPolicy(input.params);\n\tconst chainSkillInput = normalizeSkillInput(input.params.skill);\n\tconst chainSkills = chainSkillInput === false ? [] : (chainSkillInput ?? []);\n\tconst asyncCtx = {\n\t\tpi: input.deps.pi,\n\t\tcwd: input.ctx.cwd,\n\t\tcurrentSessionId: resolveCurrentSessionId(input.ctx.sessionManager),\n\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\tcurrentModelProvider: input.ctx.model?.provider,\n\t\tcurrentModel: input.ctx.model,\n\t\tmodelScope: discoveredForAppend.modelScope,\n\t};\n\tconst built = buildAsyncRunnerSteps(resolved.id, {\n\t\tchain: wrapChainTasksForFork(input.params.chain, contextPolicy),\n\t\ttask: input.params.task,\n\t\tresultMode: \"chain\",\n\t\tagents,\n\t\tctx: asyncCtx,\n\t\tavailableModels: input.ctx.modelRegistry.getAvailable().map(toModelInfo),\n\t\tcwd: status.cwd ?? input.requestCwd,\n\t\tchainSkills,\n\t\tdynamicFanoutMaxItems: input.deps.config.chain?.dynamicFanout?.maxItems,\n\t\tmaxSubagentDepth: resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth),\n\t\twaitToolEnabled: input.deps.waitToolEnabled,\n\t\tasyncDir: resolved.location.asyncDir,\n\t\tvalidateOutputBindings: false,\n\t});\n\tif (\"error\" in built) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: built.error }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst appendedOutputNames = runnerStepOutputNames(built.steps);\n\tconst duplicateAppendedOutputs = duplicateNames(appendedOutputNames);\n\tif (duplicateAppendedOutputs.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step to run '${resolved.id}': duplicate output name in appended step: ${duplicateAppendedOutputs.join(\", \")}.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst pendingOutputNames = new Set(pendingAppendRequests.flatMap((request) => runnerStepOutputNames(request.steps)));\n\tconst pendingDuplicateOutputs = appendedOutputNames.filter((name) => pendingOutputNames.has(name));\n\tif (pendingDuplicateOutputs.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step to run '${resolved.id}': output name already belongs to a pending append: ${pendingDuplicateOutputs.join(\", \")}.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\ttry {\n\t\tconst result = enqueueChainAppendRequest({\n\t\t\tasyncDir: resolved.location.asyncDir,\n\t\t\trunId: resolved.id,\n\t\t\tsteps: built.steps,\n\t\t});\n\t\tconst stepText = built.steps.length === 1 ? \"step\" : \"steps\";\n\t\treturn {\n\t\t\tcontent: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: `Append queued for chain run ${resolved.id}: ${built.steps.length} ${stepText}. It becomes eligible after the chain's already-queued steps finish. Pending appends: ${result.pendingCount}.`,\n\t\t\t}],\n\t\t\tdetails: { mode: \"management\", results: [], asyncId: resolved.id, asyncDir: resolved.location.asyncDir },\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Failed to append step to chain run ${resolved.id}: ${message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n}\n\nfunction nestedRunSessionFile(run: NestedRunSummary): string | undefined {\n\treturn run.sessionFile ?? (run.steps?.length === 1 ? run.steps[0]?.sessionFile : undefined);\n}\n\nfunction nestedRunAgent(run: NestedRunSummary): string | undefined {\n\treturn run.agent ?? run.agents?.[0] ?? (run.steps?.length === 1 ? run.steps[0]?.agent : undefined);\n}\n\nfunction pathWithin(base: string, candidate: string): boolean {\n\tconst resolvedBase = path.resolve(base);\n\tconst resolvedCandidate = path.resolve(candidate);\n\treturn resolvedCandidate === resolvedBase || resolvedCandidate.startsWith(`${resolvedBase}${path.sep}`);\n}\n\nfunction validateNestedSessionFile(run: NestedRunSummary, trustedSessionRoots: string[]): string {\n\tconst sessionFile = nestedRunSessionFile(run);\n\tif (!sessionFile) throw new Error(`Nested run '${run.id}' does not have a persisted session file to resume from.`);\n\tif (path.extname(sessionFile) !== \".jsonl\") throw new Error(`Nested run '${run.id}' session file must be a .jsonl file: ${sessionFile}`);\n\tconst resolved = path.resolve(sessionFile);\n\tif (!path.isAbsolute(sessionFile)) throw new Error(`Nested run '${run.id}' session file must be absolute: ${sessionFile}`);\n\tif (!fs.existsSync(resolved)) throw new Error(`Nested run '${run.id}' session file does not exist: ${sessionFile}`);\n\tconst stat = fs.lstatSync(resolved);\n\tif (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`Nested run '${run.id}' session file is not a regular file: ${sessionFile}`);\n\tconst realSessionFile = fs.realpathSync(resolved);\n\tconst trustedRoots = trustedSessionRoots\n\t\t.filter((root) => fs.existsSync(root))\n\t\t.map((root) => fs.realpathSync(root));\n\tif (!trustedRoots.some((root) => pathWithin(root, realSessionFile))) {\n\t\tthrow new Error(`Nested run '${run.id}' session file is outside trusted nested session roots: ${sessionFile}`);\n\t}\n\tif (!realSessionFile.split(path.sep).includes(run.id)) {\n\t\tthrow new Error(`Nested run '${run.id}' session file is not under that nested run's session directory: ${sessionFile}`);\n\t}\n\treturn realSessionFile;\n}\n\nfunction resolveNestedResumeTarget(match: ResolvedSubagentRunId & { kind: \"nested\" }, trustedSessionRoots: string[]): NestedResumeSourceTarget {\n\tconst run = match.match.run;\n\tif (run.state === \"running\" || run.state === \"queued\") throw new Error(`Nested run '${run.id}' is live; route the follow-up to the owner process instead.`);\n\tconst agent = nestedRunAgent(run);\n\tif (!agent) throw new Error(`Could not determine child agent for nested run '${run.id}'.`);\n\tconst state = run.state === \"complete\" || run.state === \"failed\" || run.state === \"paused\" || run.state === \"stopped\" ? run.state : \"failed\";\n\tconst asyncDir = resolveNestedAsyncDir(match.match.rootRunId, run);\n\treturn {\n\t\tkind: \"revive\",\n\t\tsource: \"nested\",\n\t\trunId: run.id,\n\t\tstate,\n\t\tagent,\n\t\tindex: 0,\n\t\tintercomTarget: resolveSubagentIntercomTarget(run.id, agent, 0),\n\t\tcwd: asyncDir ? path.dirname(asyncDir) : undefined,\n\t\tsessionFile: validateNestedSessionFile(run, trustedSessionRoots),\n\t};\n}\n\nasync function waitForNestedControlResult(target: ResolvedSubagentRunId & { kind: \"nested\" }, requestId: string, timeoutMs = 1_000) {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tconst result = readNestedControlResults(target.match.route).find((candidate) => candidate.requestId === requestId && candidate.targetRunId === target.match.run.id);\n\t\tif (result) return result;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 50));\n\t}\n\treturn undefined;\n}\n\nasync function sendNestedControlRequest(target: ResolvedSubagentRunId & { kind: \"nested\" }, action: \"interrupt\" | \"resume\", message?: string) {\n\tconst requestId = randomUUID();\n\twriteNestedControlRequest(target.match.route, {\n\t\tts: Date.now(),\n\t\trequestId,\n\t\ttargetRunId: target.match.run.id,\n\t\taction,\n\t\t...(message ? { message } : {}),\n\t});\n\treturn waitForNestedControlResult(target, requestId);\n}\n\nfunction directNestedAsyncInterrupt(target: ResolvedSubagentRunId & { kind: \"nested\" }): AgentToolResult<Details> | undefined {\n\tconst run = target.match.run;\n\tconst asyncDir = resolveNestedAsyncDir(target.match.rootRunId, run);\n\tif (!asyncDir) return undefined;\n\tconst status = reconcileAsyncRun(asyncDir, { resultsDir: path.join(RESULTS_DIR, \"nested\", target.match.rootRunId) }).status;\n\tconst pid = typeof status?.pid === \"number\" && status.pid > 0 ? status.pid : run.pid;\n\tif (!status || status.state !== \"running\" || typeof pid !== \"number\" || pid <= 0) return undefined;\n\ttry {\n\t\tdeliverInterruptRequest({ asyncDir, pid, source: \"nested-interrupt\" });\n\t\treturn { content: [{ type: \"text\", text: `Interrupt requested for nested async run ${run.id}.` }], details: { mode: \"management\", results: [] } };\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { content: [{ type: \"text\", text: `Failed to interrupt nested async run ${run.id}: ${message}` }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n}\n\nasync function directNestedAsyncSteer(input: { target: ResolvedSubagentRunId & { kind: \"nested\" }; message: string; index?: number; signal?: AbortSignal }): Promise<AgentToolResult<Details> | undefined> {\n\tconst run = input.target.match.run;\n\tconst asyncDir = resolveNestedAsyncDir(input.target.match.rootRunId, run);\n\tif (!asyncDir) return undefined;\n\tconst status = reconcileAsyncRun(asyncDir, { resultsDir: path.join(RESULTS_DIR, \"nested\", input.target.match.rootRunId) }).status;\n\tif (!status || (status.state !== \"running\" && status.state !== \"queued\")) return undefined;\n\tconst steps = status.steps ?? [];\n\tif (input.index !== undefined) {\n\t\tif (input.index < 0 || input.index >= steps.length) return { content: [{ type: \"text\", text: `Nested async run ${run.id} has ${steps.length} children. Index ${input.index} is out of range.` }], isError: true, details: { mode: \"management\", results: [] } };\n\t\tconst step = steps[input.index];\n\t\tif (step && step.status !== \"running\" && step.status !== \"pending\") return { content: [{ type: \"text\", text: `Nested async run ${run.id} child ${input.index} is ${step.status} and cannot be steered.` }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tconst runningIndexes = steps\n\t\t.map((step, index) => step.status === \"running\" ? index : undefined)\n\t\t.filter((index): index is number => index !== undefined);\n\tconst effectiveTargetIndex = input.index ?? (status.mode === \"single\" && runningIndexes.length === 0 && steps[0]?.status === \"pending\" ? 0 : undefined);\n\tconst targetIndexes = effectiveTargetIndex !== undefined ? [effectiveTargetIndex] : runningIndexes;\n\tif (targetIndexes.length === 0) return { content: [{ type: \"text\", text: `Nested async run ${run.id} has no running child to steer.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tconst requestId = randomUUID();\n\ttry {\n\t\trequestAsyncSteer(asyncDir, {\n\t\t\tmessage: input.message,\n\t\t\t...(effectiveTargetIndex !== undefined ? { targetIndex: effectiveTargetIndex } : { targetIndexes }),\n\t\t\tsource: \"nested-steer\",\n\t\t\tid: requestId,\n\t\t});\n\t} catch (error) {\n\t\treturn { content: [{ type: \"text\", text: `Failed to queue steering for nested async run ${run.id}: ${error instanceof Error ? error.message : String(error)}` }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tconst targets = targetIndexes.map((index) => ({ index, state: steps[index]?.status === \"pending\" ? \"scheduled\" as const : \"pending\" as const }));\n\tif (targets.every((target) => target.state === \"scheduled\")) {\n\t\tconst scheduled = { requestId, state: \"scheduled\" as const, sourceRunId: run.id, targets };\n\t\treturn { content: [{ type: \"text\", text: `Steering scheduled for nested async run ${run.id} (request ${requestId}).` }], details: { mode: \"management\", results: [], steering: scheduled } };\n\t}\n\tconst waited = await waitForSteeringAction({ asyncDir, sourceRunId: run.id, requestId, timeoutMs: 3_000, signal: input.signal });\n\tconst result = waited ?? { requestId, state: \"pending\" as const, sourceRunId: run.id, targets };\n\tconst stateText = result.state === \"delivered\" ? \"delivered\" : result.state === \"failed\" ? \"failed\" : result.state === \"partial\" ? \"partial\" : \"pending\";\n\treturn { content: [{ type: \"text\", text: `Steering ${stateText} for nested async run ${run.id} (request ${requestId}).` }], ...(result.state === \"failed\" || result.state === \"partial\" ? { isError: true } : {}), details: { mode: \"management\", results: [], steering: result } };\n}\n\nasync function interruptNestedRun(target: ResolvedSubagentRunId & { kind: \"nested\" }): Promise<AgentToolResult<Details>> {\n\tconst run = target.match.run;\n\tif (run.state === \"complete\") return { content: [{ type: \"text\", text: `Nested run ${run.id} is already complete and cannot be interrupted.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tif (run.state === \"failed\") return { content: [{ type: \"text\", text: `Nested run ${run.id} has failed and cannot be interrupted.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tif (run.state === \"paused\") return { content: [{ type: \"text\", text: `Nested run ${run.id} is already paused.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tconst result = await sendNestedControlRequest(target, \"interrupt\");\n\tif (result) return { content: [{ type: \"text\", text: result.message }], isError: result.ok ? undefined : true, details: { mode: \"management\", results: [] } };\n\tconst direct = directNestedAsyncInterrupt(target);\n\tif (direct) return direct;\n\treturn { content: [{ type: \"text\", text: `Nested run ${run.id} owner is not reachable and no safe direct async interrupt fallback is available.` }], isError: true, details: { mode: \"management\", results: [] } };\n}\n\nasync function resumeLiveNestedRun(input: { target: ResolvedSubagentRunId & { kind: \"nested\" }; message: string }): Promise<AgentToolResult<Details>> {\n\tconst run = input.target.match.run;\n\tconst result = await sendNestedControlRequest(input.target, \"resume\", input.message);\n\tif (result) return { content: [{ type: \"text\", text: result.message }], isError: result.ok ? undefined : true, details: { mode: \"management\", results: [] } };\n\treturn { content: [{ type: \"text\", text: `Nested run ${run.id} appears live but its owner route is not reachable. Wait for completion, then retry action='resume'.` }], isError: true, details: { mode: \"management\", results: [] } };\n}\n\nasync function steerNestedRun(input: { target: ResolvedSubagentRunId & { kind: \"nested\" }; message: string; index?: number; signal?: AbortSignal }): Promise<AgentToolResult<Details>> {\n\tconst run = input.target.match.run;\n\tif (run.state !== \"running\" && run.state !== \"queued\") return { content: [{ type: \"text\", text: `Nested run ${run.id} is ${run.state} and cannot be steered.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tconst direct = await directNestedAsyncSteer(input);\n\tif (direct) return direct;\n\treturn { content: [{ type: \"text\", text: `Nested run ${run.id} is not a live async Pi child session with a steering inbox. action='steer' cannot target foreground nested runs.` }], isError: true, details: { mode: \"management\", results: [] } };\n}\n\nasync function resumeAsyncRun(input: {\n\tparams: SubagentParamsLike;\n\trequestCwd: string;\n\tctx: ExtensionContext;\n\tdeps: ExecutorDeps;\n\tabsoluteDeadlineAt?: number;\n}): Promise<AgentToolResult<Details>> {\n\tconst followUp = (input.params.message ?? input.params.task ?? \"\").trim();\n\tconst attachChain = (input.params.chain?.length ?? 0) > 0 ? input.params.chain as ChainStep[] : undefined;\n\tif (!followUp && !attachChain) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"action='resume' requires message.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst acceptanceErrors = validateExecutionAcceptance(input.params);\n\tif (acceptanceErrors.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot resume: ${acceptanceErrors.join(\" \")}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tinput.deps.state.currentSessionId = resolveCurrentSessionId(input.ctx.sessionManager);\n\n\tlet target: ResumeSourceTarget;\n\tconst parentSessionFile = input.ctx.sessionManager.getSessionFile() ?? null;\n\ttry {\n\t\tconst requestedId = input.params.id ?? input.params.runId;\n\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\ttry {\n\t\t\tresolved = requestedId ? resolveSubagentRunId(requestedId, { state: input.deps.state, nested: nestedResolutionScopeForExecutor(input.deps) }) : undefined;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"\";\n\t\t\tconst asyncMatches = message.match(/async:/g)?.length ?? 0;\n\t\t\tif (!isResumeAmbiguity(error) || !message.includes(\"foreground:\") || asyncMatches !== 1) throw error;\n\t\t}\n\t\tif (resolved?.kind === \"nested\") {\n\t\t\tif (attachChain) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Attaching a running subagent as a chain root is currently available for top-level async runs only.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (resolved.match.run.state === \"running\" || resolved.match.run.state === \"queued\") {\n\t\t\t\treturn resumeLiveNestedRun({ target: resolved, message: followUp });\n\t\t\t}\n\t\t\tconst trustedSessionRoots = [\n\t\t\t\t...(input.deps.config.defaultSessionDir ? [path.resolve(input.deps.expandTilde(input.deps.config.defaultSessionDir))] : []),\n\t\t\t\t...(parentSessionFile ? [input.deps.getSubagentSessionRoot(parentSessionFile)] : []),\n\t\t\t];\n\t\t\ttarget = resolveNestedResumeTarget(resolved, trustedSessionRoots);\n\t\t} else {\n\t\t\ttarget = resolveResumeTarget(input.params, input.deps.state, { asyncRequireSessionFile: !attachChain });\n\t\t}\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\n\tif (target.kind === \"live\" && !attachChain) {\n\t\tconst interrupt = interruptLiveAsyncResumeTarget({\n\t\t\ttarget,\n\t\t\tstate: input.deps.state,\n\t\t\tkill: input.deps.kill,\n\t\t\tresultsDir: RESULTS_DIR,\n\t\t});\n\t\tif (!interrupt.ok) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: interrupt.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t};\n\t\t}\n\t\tconst delivered = await deliverSubagentIntercomMessageEvent(\n\t\t\tinput.deps.pi.events,\n\t\t\ttarget.intercomTarget,\n\t\t\t`Follow-up for async run ${target.runId} (${target.agent}):\\n\\n${followUp}`,\n\t\t\t500,\n\t\t\t{ source: \"async-resume\", runId: target.runId, agent: target.agent, index: target.index },\n\t\t);\n\t\tif (delivered) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: [`Interrupted live async child, then delivered follow-up.`, `Run: ${target.runId}`, `Intercom target: ${target.intercomTarget}`].join(\"\\n\") }],\n\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: [`Async child appears live but its intercom target is not registered.`, `Run: ${target.runId}`, `Intercom target: ${target.intercomTarget}`, `Wait for completion, then retry action='resume'.`].join(\"\\n\") }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst { blocked, depth, maxDepth } = checkSubagentDepth(input.deps.config.maxSubagentDepth);\n\tif (blocked) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Nested subagent resume blocked (depth=${depth}, max=${maxDepth}). Complete the follow-up directly instead.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tinput.deps.state.currentSessionId = resolveCurrentSessionId(input.ctx.sessionManager);\n\tconst effectiveCwd = target.cwd ?? input.requestCwd;\n\tconst scope: AgentScope = resolveExecutionAgentScope(input.params.agentScope);\n\tconst discovered = input.deps.discoverAgents(effectiveCwd, scope);\n\tconst discoveredAgents = discovered.agents;\n\tconst modelScope = discovered.modelScope;\n\tconst sessionName = resolveIntercomSessionTarget(input.deps.pi.getSessionName(), input.ctx.sessionManager.getSessionId());\n\tconst intercomBridge = resolveIntercomBridge({\n\t\tconfig: input.deps.config.intercomBridge,\n\t\tcontext: input.params.context,\n\t\torchestratorTarget: sessionName,\n\t});\n\tconst agents = intercomBridge.active\n\t\t? discoveredAgents.map((agent) => applyIntercomBridgeToAgent(agent, intercomBridge))\n\t\t: discoveredAgents;\n\tconst recoveryDescriptor = \"recoveryDescriptor\" in target ? target.recoveryDescriptor : undefined;\n\tconst discoveredAgentConfig = agents.find((agent) => agent.name === target.agent);\n\tconst agentConfig: AgentConfig | undefined = discoveredAgentConfig ?? (recoveryDescriptor ? {\n\t\tname: recoveryDescriptor.agent,\n\t\tdescription: \"Persisted async recovery contract\",\n\t\tsystemPrompt: \"\",\n\t\tsystemPromptMode: recoveryDescriptor.systemPromptMode,\n\t\tinheritProjectContext: recoveryDescriptor.inheritProjectContext,\n\t\tinheritSkills: recoveryDescriptor.inheritSkills,\n\t\tsource: \"project\",\n\t\tfilePath: recoveryDescriptor.agentFilePath ?? path.join(recoveryDescriptor.cwd, \".pi-subagents-recovery-agent\"),\n\t} : undefined);\n\tif (!agentConfig) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Unknown agent for resume: ${target.agent}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tif (attachChain) {\n\t\tif (target.source !== \"async\") {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Attaching a running subagent as a chain root is currently available for async runs only.\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t};\n\t\t}\n\t\tif (!isAsyncAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Async mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\", results: [] },\n\t\t\t};\n\t\t}\n\t\tconst runId = randomUUID().slice(0, 8);\n\t\tconst artifactConfig: ArtifactConfig = { ...DEFAULT_ARTIFACT_CONFIG, enabled: input.params.artifacts !== false };\n\t\tconst availableModels = input.ctx.modelRegistry.getAvailable().map(toModelInfo);\n\t\tconst contextPolicy = resolveExplicitContextPolicy(input.params);\n\t\tconst workflowTask = (input.params.task ?? followUp) || undefined;\n\t\tconst goal = resolveAsyncEventGoal(workflowTask, attachChain);\n\t\tconst chain = wrapChainTasksForFork(attachChain, contextPolicy);\n\t\tconst normalized = normalizeSkillInput(input.params.skill);\n\t\tconst result = executeAsyncChain(runId, {\n\t\t\tchain,\n\t\t\ttask: workflowTask,\n\t\t\tgoal,\n\t\t\tattachRoot: {\n\t\t\t\trunId: target.runId,\n\t\t\t\tasyncDir: target.asyncDir ?? path.join(ASYNC_DIR, target.runId),\n\t\t\t\tresultPath: resolveAsyncRootResultPath(RESULTS_DIR, target.runId),\n\t\t\t\tindex: target.index,\n\t\t\t\tagent: target.agent,\n\t\t\t\tlabel: `Attached ${target.runId}`,\n\t\t\t},\n\t\t\tagents,\n\t\t\tctx: {\n\t\t\t\tpi: input.deps.pi,\n\t\t\t\tcwd: input.requestCwd,\n\t\t\t\tcurrentSessionId: input.deps.state.currentSessionId,\n\t\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcurrentModelProvider: input.ctx.model?.provider,\n\t\t\t\tcurrentModel: input.ctx.model,\n\t\t\t\tmodelScope,\n\t\t\t},\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: input.params.maxOutput,\n\t\t\tartifactsDir: getArtifactsDir(parentSessionFile, effectiveCwd),\n\t\t\tartifactConfig,\n\t\t\tshareEnabled: input.params.share === true,\n\t\t\tsessionRoot: input.deps.getSubagentSessionRoot(parentSessionFile),\n\t\t\tchainSkills: normalized === false ? [] : (normalized ?? []),\n\t\t\tdynamicFanoutMaxItems: input.deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\tmaxSubagentDepth: resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth),\n\t\t\twaitToolEnabled: input.deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: input.deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: input.deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: input.deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig: resolveControlConfig(input.deps.config.control, input.params.control),\n\t\t\tcontrolIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,\n\t\t\tchildIntercomTarget: intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(runId, agent, index) : undefined,\n\t\t\tglobalConcurrencyLimit: input.deps.config.globalConcurrencyLimit,\n\t\t});\n\t\tif (result.isError) return result;\n\t\tconst attachedId = result.details.asyncId ?? runId;\n\t\tconst lines = [\n\t\t\t`Attached async subagent ${target.runId} as the first step of a new chain.`,\n\t\t\t`Chain run: ${attachedId}`,\n\t\t\t`Root: ${target.agent} (step ${target.index + 1})`,\n\t\t\tresult.details.asyncDir ? `Async dir: ${result.details.asyncDir}` : undefined,\n\t\t\t`Status if needed: subagent({ action: \"status\", id: \"${attachedId}\" })`,\n\t\t].filter((line): line is string => Boolean(line));\n\t\treturn { content: [{ type: \"text\", text: formatAsyncStartedMessage(lines.join(\"\\n\")) }], details: result.details };\n\t}\n\n\tconst runId = randomUUID().slice(0, 8);\n\tconst recoveryAgentConfig = recoveryDescriptor ? applySteeringRecoveryAgentConfig(agentConfig, recoveryDescriptor) : agentConfig;\n\tconst artifactConfig: ArtifactConfig = recoveryDescriptor?.artifactConfig ?? { ...DEFAULT_ARTIFACT_CONFIG, enabled: input.params.artifacts !== false };\n\tconst artifactsDir = recoveryDescriptor?.artifactsDir ?? getArtifactsDir(parentSessionFile, effectiveCwd);\n\tconst availableModels = input.ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tconst result = executeAsyncSingle(runId, {\n\t\tagent: target.agent,\n\t\ttask: buildRevivedAsyncTask(target, followUp),\n\t\tgoal: followUp,\n\t\tagentConfig: recoveryAgentConfig,\n\t\tctx: {\n\t\t\tpi: input.deps.pi,\n\t\t\tcwd: input.requestCwd,\n\t\t\tcurrentSessionId: input.deps.state.currentSessionId,\n\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\tcurrentModelProvider: input.ctx.model?.provider,\n\t\t\tcurrentModel: input.ctx.model,\n\t\t\tmodelScope,\n\t\t},\n\t\tcwd: effectiveCwd,\n\t\tmaxOutput: input.params.maxOutput ?? recoveryDescriptor?.maxOutput,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tshareEnabled: recoveryDescriptor?.share ?? input.params.share === true,\n\t\tsessionRoot: input.deps.getSubagentSessionRoot(parentSessionFile),\n\t\t...(recoveryDescriptor?.sessionDir ? { sessionDir: recoveryDescriptor.sessionDir } : {}),\n\t\tsessionFile: target.sessionFile,\n\t\trevivalLease: {\n\t\t\tsessionFile: target.sessionFile,\n\t\t\trunId,\n\t\t\tsourceRunId: target.runId,\n\t\t\t...(input.deps.state.currentSessionId ? { parentSessionId: input.deps.state.currentSessionId } : {}),\n\t\t},\n\t\tmodelOverride: input.params.model ?? recoveryDescriptor?.model ?? target.model,\n\t\tthinkingOverride: input.params.model ? undefined : recoveryDescriptor?.thinking ?? target.thinking,\n\t\toutputBaseDir: resolveSingleRunOutputBaseDir(input.deps, artifactsDir, runId),\n\t\tmaxSubagentDepth: recoveryDescriptor?.maxSubagentDepth ?? resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth),\n\t\twaitToolEnabled: input.deps.waitToolEnabled,\n\t\tworktreeSetupHook: input.deps.config.worktreeSetupHook,\n\t\tworktreeSetupHookTimeoutMs: input.deps.config.worktreeSetupHookTimeoutMs,\n\t\tworktreeBaseDir: input.deps.config.worktreeBaseDir,\n\t\tcontrolConfig: recoveryDescriptor?.controlConfig ?? resolveControlConfig(input.deps.config.control, input.params.control),\n\t\tcontrolIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,\n\t\tchildIntercomTarget: intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(runId, agent, index) : undefined,\n\t\tavailableModels,\n\t\toutput: recoveryDescriptor?.outputPath,\n\t\toutputMode: recoveryDescriptor?.outputMode,\n\t\t...(recoveryDescriptor?.skills ? { skills: [...recoveryDescriptor.skills] } : {}),\n\t\t...(recoveryDescriptor?.acceptance !== undefined && input.params.acceptance === undefined ? { acceptance: recoveryDescriptor.acceptance } : {}),\n\t\t...(input.params.timeoutMs !== undefined ? { timeoutMs: input.params.timeoutMs } : {}),\n\t\t...(input.absoluteDeadlineAt !== undefined ? { absoluteDeadlineAt: input.absoluteDeadlineAt } : {}),\n\t\t...(input.params.turnBudget !== undefined ? { turnBudget: input.params.turnBudget } : {}),\n\t\t...(input.params.toolBudget !== undefined ? { toolBudget: input.params.toolBudget } : {}),\n\t});\n\tif (result.isError) return result;\n\n\tconst revivedId = result.details.asyncId ?? runId;\n\tconst revivedTarget = intercomBridge.active ? resolveSubagentIntercomTarget(revivedId, target.agent, 0) : undefined;\n\tconst sourceLabel = target.source;\n\tconst lines = [\n\t\t`Revived ${sourceLabel} subagent from ${target.runId}.`,\n\t\t`Revived run: ${revivedId}`,\n\t\t`Agent: ${target.agent}`,\n\t\t`Session: ${target.sessionFile}`,\n\t\tresult.details.asyncDir ? `Async dir: ${result.details.asyncDir}` : undefined,\n\t\trevivedTarget ? `Intercom target: ${revivedTarget} (if registered)` : undefined,\n\t\t`Status if needed: subagent({ action: \"status\", id: \"${revivedId}\" })`,\n\t].filter((line): line is string => Boolean(line));\n\treturn { content: [{ type: \"text\", text: formatAsyncStartedMessage(lines.join(\"\\n\")) }], details: result.details };\n}\n\nfunction resultSummaryForIntercom(result: SingleResult): string {\n\tconst output = getSingleResultOutput(result);\n\tif (result.exitCode !== 0 && result.error) {\n\t\treturn output ? `${result.error}\\n\\nOutput:\\n${output}` : result.error;\n\t}\n\treturn output || result.error || \"(no output)\";\n}\n\nfunction formatFailedSingleRunOutput(result: SingleResult, displayOutput: string): string {\n\tconst error = result.error || \"Failed\";\n\tconst output = displayOutput.trim();\n\tconst lines = [error];\n\tif (output && output !== error.trim()) {\n\t\tlines.push(\"\", \"Output:\", output);\n\t}\n\tif (result.artifactPaths?.outputPath) {\n\t\tlines.push(\"\", `Output artifact: ${result.artifactPaths.outputPath}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction createForegroundControlNotifier(data: Pick<ExecutionContextData, \"controlConfig\" | \"intercomBridge\">, deps: Pick<ExecutorDeps, \"pi\">): (event: ControlEvent) => void {\n\treturn (event) => emitControlNotification({\n\t\tpi: deps.pi,\n\t\tcontrolConfig: data.controlConfig,\n\t\tintercomBridge: data.intercomBridge,\n\t\tevent,\n\t});\n}\n\nasync function emitForegroundResultIntercom(input: {\n\tpi: ExtensionAPI;\n\tintercomBridge: IntercomBridgeState;\n\trunId: string;\n\tmode: SubagentRunMode;\n\tresults: SingleResult[];\n\tchainSteps?: number;\n\tnestedChildren?: NestedRunSummary[];\n}): Promise<ReturnType<typeof buildSubagentResultIntercomPayload> | null> {\n\tif (!input.intercomBridge.active || !input.intercomBridge.orchestratorTarget) return null;\n\tconst children = input.results.flatMap((result, index) => result.detached ? [] : [{\n\t\tagent: result.agent,\n\t\tstatus: resolveSubagentResultStatus({\n\t\t\texitCode: result.exitCode,\n\t\t\tinterrupted: result.interrupted,\n\t\t\tdetached: result.detached,\n\t\t}),\n\t\tsummary: resultSummaryForIntercom(result),\n\t\tindex,\n\t\tartifactPath: result.artifactPaths?.outputPath,\n\t\tsessionPath: result.sessionFile,\n\t\tintercomTarget: resolveSubagentIntercomTarget(input.runId, result.agent, index),\n\t}]);\n\tif (children.length === 0) return null;\n\tconst payload = buildSubagentResultIntercomPayload({\n\t\tto: input.intercomBridge.orchestratorTarget,\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tsource: \"foreground\",\n\t\tchildren: attachNestedChildrenToResultChildren(input.runId, children, input.nestedChildren),\n\t\t...(typeof input.chainSteps === \"number\" ? { chainSteps: input.chainSteps } : {}),\n\t});\n\tconst delivered = await deliverSubagentResultIntercomEvent(input.pi.events, payload);\n\tif (!delivered) return null;\n\treturn payload;\n}\n\nasync function maybeBuildForegroundIntercomReceipt(input: {\n\tpi: ExtensionAPI;\n\tintercomBridge: IntercomBridgeState;\n\trunId: string;\n\tmode: SubagentRunMode;\n\tdetails: Details;\n\tnestedChildren?: NestedRunSummary[];\n}): Promise<{ text: string; details: Details } | null> {\n\tconst payload = await emitForegroundResultIntercom({\n\t\tpi: input.pi,\n\t\tintercomBridge: input.intercomBridge,\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tresults: input.details.results,\n\t\t...(typeof input.details.totalSteps === \"number\" ? { chainSteps: input.details.totalSteps } : {}),\n\t\t...(input.nestedChildren?.length ? { nestedChildren: input.nestedChildren } : {}),\n\t});\n\tif (!payload) return null;\n\treturn {\n\t\ttext: formatSubagentResultReceipt({ mode: input.mode, runId: input.runId, payload }),\n\t\tdetails: stripDetailsOutputsForIntercomReceipt(input.details),\n\t};\n}\n\nfunction validateExecutionInput(\n\tparams: SubagentParamsLike,\n\tagents: AgentConfig[],\n\thasChain: boolean,\n\thasTasks: boolean,\n\thasSingle: boolean,\n\tallowClarifyTaskPrompt: boolean,\n): AgentToolResult<Details> | null {\n\tif (Number(hasChain) + Number(hasTasks) + Number(hasSingle) !== 1) {\n\t\treturn {\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: `Provide exactly one mode. Agents: ${agents.map((a) => a.name).join(\", \") || \"none\"}`,\n\t\t\t\t},\n\t\t\t],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t};\n\t}\n\n\tconst acceptanceErrors = validateExecutionAcceptance(params);\n\tif (acceptanceErrors.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: acceptanceErrors.join(\" \") }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: getRequestedModeLabel(params), results: [] },\n\t\t};\n\t}\n\n\tif (hasSingle && params.agent && !agents.find((agent) => agent.name === params.agent)) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${params.agent}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t};\n\t}\n\n\tif (hasTasks && params.tasks) {\n\t\tfor (let i = 0; i < params.tasks.length; i++) {\n\t\t\tconst task = params.tasks[i]!;\n\t\t\tif (!agents.find((agent) => agent.name === task.agent)) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${task.agent} (task ${i + 1})` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasChain && params.chain) {\n\t\tif (params.chain.length === 0) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Chain must have at least one step\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tconst firstStep = params.chain[0] as ChainStep;\n\t\tif (isParallelStep(firstStep)) {\n\t\t\tconst missingTaskIndex = firstStep.parallel.findIndex((t) => !t.task);\n\t\t\tif (missingTaskIndex !== -1) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `First parallel step: task ${missingTaskIndex + 1} must have a task (no previous output to reference)` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (isDynamicParallelStep(firstStep)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"First step in chain cannot be dynamic fanout; expand.from requires a prior structured named output\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t} else if (!(firstStep as SequentialStep).task && !params.task && !allowClarifyTaskPrompt) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"First step in chain must have a task\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tfor (let i = 0; i < params.chain.length; i++) {\n\t\t\tconst step = params.chain[i] as ChainStep;\n\t\t\tconst stepAgents = getStepAgents(step);\n\t\t\tfor (const agentName of stepAgents) {\n\t\t\t\tif (!agents.find((a) => a.name === agentName)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${agentName} (step ${i + 1})` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (isParallelStep(step) && step.parallel.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Parallel step ${i + 1} must have at least one task` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction validateExecutionChainBindings(params: SubagentParamsLike, dynamicFanoutMaxItems?: number): AgentToolResult<Details> | null {\n\tif ((params.chain?.length ?? 0) === 0) return null;\n\ttry {\n\t\tvalidateChainOutputBindingsWithContext(params.chain as ChainStep[], { maxItems: dynamicFanoutMaxItems });\n\t} catch (error) {\n\t\tif (error instanceof ChainOutputValidationError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: error.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\treturn null;\n}\n\nfunction getRequestedModeLabel(params: SubagentParamsLike): Details[\"mode\"] {\n\tif ((params.chain?.length ?? 0) > 0) return \"chain\";\n\tif ((params.tasks?.length ?? 0) > 0) return \"parallel\";\n\tif (params.agent) return \"single\";\n\treturn \"single\";\n}\n\ninterface AgentDefaultContextPolicy {\n\tparams: SubagentParamsLike;\n\tcontextForAgent(agentName: string): \"fresh\" | \"fork\";\n\tusesFork: boolean;\n}\n\nfunction resolveAgentDefaultContextPolicy(params: SubagentParamsLike, _agents: AgentConfig[]): AgentDefaultContextPolicy {\n\t// lunr: hide fork from the model; force every child to fresh. Fork internals stay.\n\treturn lunrContextPolicy(params);\n}\n\nfunction resolveExplicitContextPolicy(params: SubagentParamsLike): AgentDefaultContextPolicy {\n\t// lunr: `context: \"fork\"` from the model is coerced to fresh.\n\treturn lunrContextPolicy(params);\n}\n\nfunction collectRequestedAgentNames(params: SubagentParamsLike): string[] {\n\tconst names: string[] = [];\n\tif (params.agent) names.push(params.agent);\n\tfor (const task of params.tasks ?? []) names.push(task.agent);\n\tfor (const step of params.chain ?? []) names.push(...getStepAgents(step));\n\treturn names;\n}\n\nfunction collectRequestedAgents(\n\tparams: SubagentParamsLike,\n\tagents: AgentConfig[],\n): Array<{ name: string; tools?: string[] }> {\n\tconst byName = new Map(agents.map((agent) => [agent.name, agent]));\n\treturn collectRequestedAgentNames(params).map((name) => {\n\t\tconst agent = byName.get(name);\n\t\treturn { name, tools: agent?.tools };\n\t});\n}\n\nfunction shouldForkAgent(contextPolicy: AgentDefaultContextPolicy, agentName: string): boolean {\n\treturn contextPolicy.contextForAgent(agentName) === \"fork\";\n}\n\nfunction buildRequestedModeError(params: SubagentParamsLike, message: string): AgentToolResult<Details> {\n\treturn withForkContext(\n\t\t{\n\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: getRequestedModeLabel(params), results: [] },\n\t\t},\n\t\tparams.context,\n\t);\n}\n\nfunction applySingleAgentLaunchDefaults(params: SubagentParamsLike, agents: AgentConfig[]): SubagentParamsLike {\n\tif ((params.chain?.length ?? 0) > 0 || (params.tasks?.length ?? 0) > 0 || !params.agent) return params;\n\tconst agent = agents.find((candidate) => candidate.name === params.agent);\n\tif (!agent) return params;\n\treturn {\n\t\t...params,\n\t\t...(params.async === undefined && agent.defaultAsync !== undefined ? { async: agent.defaultAsync } : {}),\n\t\t...(params.timeoutMs === undefined && params.maxRuntimeMs === undefined && agent.defaultTimeoutMs !== undefined\n\t\t\t? { timeoutMs: agent.defaultTimeoutMs }\n\t\t\t: {}),\n\t\t...(params.turnBudget === undefined && agent.defaultTurnBudget !== undefined\n\t\t\t? { turnBudget: agent.defaultTurnBudget }\n\t\t\t: {}),\n\t\t...(params.acceptance === undefined && agent.defaultAcceptance !== undefined\n\t\t\t? { acceptance: agent.defaultAcceptance }\n\t\t\t: {}),\n\t};\n}\n\nfunction resolveForegroundTimeout(params: SubagentParamsLike): { timeoutMs?: number; error?: string } {\n\tconst rawTimeout = params.timeoutMs;\n\tconst rawMaxRuntime = params.maxRuntimeMs;\n\tif (rawTimeout === undefined && rawMaxRuntime === undefined) return {};\n\tfor (const [name, value] of [[\"timeoutMs\", rawTimeout], [\"maxRuntimeMs\", rawMaxRuntime]] as const) {\n\t\tif (value === undefined) continue;\n\t\tif (typeof value !== \"number\" || !Number.isInteger(value) || value <= 0) {\n\t\t\treturn { error: `${name} must be a positive integer.` };\n\t\t}\n\t}\n\tif (rawTimeout !== undefined && rawMaxRuntime !== undefined && rawTimeout !== rawMaxRuntime) {\n\t\treturn { error: \"timeoutMs and maxRuntimeMs are aliases; provide only one value or use the same value for both.\" };\n\t}\n\treturn { timeoutMs: rawTimeout ?? rawMaxRuntime };\n}\n\nfunction resolveToolBudget(raw: unknown, label = \"toolBudget\"): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tconst resolved = validateToolBudgetConfig(raw, label);\n\treturn { toolBudget: resolved.budget, error: resolved.error };\n}\n\nfunction resolveEffectiveToolBudget(input: { stepBudget?: ToolBudgetConfig; runBudget?: ResolvedToolBudget; agentBudget?: ToolBudgetConfig; configBudget?: ToolBudgetConfig }): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tif (input.stepBudget !== undefined) return resolveToolBudget(input.stepBudget, \"toolBudget\");\n\tif (input.runBudget !== undefined) return { toolBudget: input.runBudget };\n\tif (input.agentBudget !== undefined) return resolveToolBudget(input.agentBudget, \"agent.toolBudget\");\n\treturn resolveToolBudget(input.configBudget, \"config.toolBudget\");\n}\n\nfunction expandTopLevelTaskCounts(tasks: TaskParam[]): { tasks?: TaskParam[]; error?: string } {\n\tconst expanded: TaskParam[] = [];\n\tfor (let taskIndex = 0; taskIndex < tasks.length; taskIndex++) {\n\t\tconst task = tasks[taskIndex]!;\n\t\tconst rawCount = (task as TaskParam & { count?: unknown }).count;\n\t\tif (rawCount !== undefined && (typeof rawCount !== \"number\" || !Number.isInteger(rawCount) || rawCount < 1)) {\n\t\t\treturn { error: `tasks[${taskIndex}].count must be an integer >= 1` };\n\t\t}\n\t\tconst { count, ...concreteTask } = task;\n\t\tfor (let repeat = 0; repeat < (rawCount ?? 1); repeat++) {\n\t\t\texpanded.push({ ...concreteTask });\n\t\t}\n\t}\n\treturn { tasks: expanded };\n}\n\nfunction expandChainParallelCounts(chain: ChainStep[]): { chain?: ChainStep[]; error?: string } {\n\tconst expandedChain: ChainStep[] = [];\n\tfor (let stepIndex = 0; stepIndex < chain.length; stepIndex++) {\n\t\tconst step = chain[stepIndex]!;\n\t\tif (!isParallelStep(step)) {\n\t\t\texpandedChain.push(step);\n\t\t\tcontinue;\n\t\t}\n\t\tconst expandedParallel = [];\n\t\tfor (let taskIndex = 0; taskIndex < step.parallel.length; taskIndex++) {\n\t\t\tconst task = step.parallel[taskIndex]!;\n\t\t\tconst rawCount = (task as typeof task & { count?: unknown }).count;\n\t\t\tif (rawCount !== undefined && (typeof rawCount !== \"number\" || !Number.isInteger(rawCount) || rawCount < 1)) {\n\t\t\t\treturn { error: `chain[${stepIndex}].parallel[${taskIndex}].count must be an integer >= 1` };\n\t\t\t}\n\t\t\tconst { count, ...concreteTask } = task;\n\t\t\tfor (let repeat = 0; repeat < (rawCount ?? 1); repeat++) {\n\t\t\t\texpandedParallel.push({ ...concreteTask });\n\t\t\t}\n\t\t}\n\t\texpandedChain.push({ ...step, parallel: expandedParallel });\n\t}\n\treturn { chain: expandedChain };\n}\n\nfunction normalizeRepeatedParallelCounts(params: SubagentParamsLike): { params?: SubagentParamsLike; error?: AgentToolResult<Details> } {\n\tif (params.tasks) {\n\t\tconst expandedTasks = expandTopLevelTaskCounts(params.tasks);\n\t\tif (expandedTasks.error) {\n\t\t\treturn { error: buildRequestedModeError(params, expandedTasks.error) };\n\t\t}\n\t\treturn { params: { ...params, tasks: expandedTasks.tasks } };\n\t}\n\tif (params.chain) {\n\t\tconst expandedChain = expandChainParallelCounts(params.chain);\n\t\tif (expandedChain.error) {\n\t\t\treturn { error: buildRequestedModeError(params, expandedChain.error) };\n\t\t}\n\t\treturn { params: { ...params, chain: expandedChain.chain } };\n\t}\n\treturn { params };\n}\n\nfunction withForkContext(\n\tresult: AgentToolResult<Details>,\n\tcontext: SubagentParamsLike[\"context\"],\n): AgentToolResult<Details> {\n\tif (context !== \"fork\" || !result.details) return result;\n\treturn {\n\t\t...result,\n\t\tdetails: {\n\t\t\t...result.details,\n\t\t\tcontext: \"fork\",\n\t\t},\n\t};\n}\n\nfunction withForkThinkingNotes(\n\tresult: AgentToolResult<Details>,\n\tdowngrades: Map<number, string>,\n): AgentToolResult<Details> {\n\tif (downgrades.size === 0) return result;\n\tconst children = [...downgrades.entries()]\n\t\t.sort(([a], [b]) => a - b)\n\t\t.map(([index, agent]) => `${agent} (child ${index})`)\n\t\t.join(\", \");\n\tconst note = `Note: fork context forced thinking off for ${children}. The forked transcript contained signed Anthropic thinking blocks that were sanitized, and Anthropic children cannot resume such a transcript with thinking enabled. Use context: \"fresh\" when an Anthropic child needs thinking.`;\n\treturn { ...result, content: [...result.content, { type: \"text\", text: note }] };\n}\n\nfunction toExecutionErrorResult(params: SubagentParamsLike, error: unknown): AgentToolResult<Details> {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn withForkContext(\n\t\t{\n\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: getRequestedModeLabel(params), results: [] },\n\t\t},\n\t\tparams.context,\n\t);\n}\n\nfunction collectChainSessionFiles(\n\tchain: ChainStep[],\n\tsessionFileForTask: ForkSessionFileForTask,\n\tdynamicFanoutMaxItems?: number,\n): (string | undefined)[] {\n\tconst sessionFiles: (string | undefined)[] = [];\n\tlet flatIndex = 0;\n\tfor (const step of chain) {\n\t\tif (isParallelStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tsessionFiles.push(sessionFileForTask(task.agent, flatIndex, task.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\tconst maxItems = step.expand.maxItems ?? dynamicFanoutMaxItems ?? 0;\n\t\t\tfor (let itemIndex = 0; itemIndex < maxItems; itemIndex++) {\n\t\t\t\tsessionFiles.push(sessionFileForTask(step.parallel.agent, flatIndex, step.parallel.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\tsessionFiles.push(sessionFileForTask(sequential.agent, flatIndex, sequential.model));\n\t\tflatIndex++;\n\t}\n\treturn sessionFiles;\n}\n\nfunction collectChainThinkingOverrides(\n\tchain: ChainStep[],\n\tthinkingOverrideForTask: ForkThinkingOverrideForTask,\n\tdynamicFanoutMaxItems?: number,\n): (AgentConfig[\"thinking\"] | undefined)[] {\n\tconst thinkingOverrides: (AgentConfig[\"thinking\"] | undefined)[] = [];\n\tlet flatIndex = 0;\n\tfor (const step of chain) {\n\t\tif (isParallelStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tthinkingOverrides.push(thinkingOverrideForTask(task.agent, flatIndex, task.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\tconst maxItems = step.expand.maxItems ?? dynamicFanoutMaxItems ?? 0;\n\t\t\tfor (let itemIndex = 0; itemIndex < maxItems; itemIndex++) {\n\t\t\t\tthinkingOverrides.push(thinkingOverrideForTask(step.parallel.agent, flatIndex, step.parallel.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\tthinkingOverrides.push(thinkingOverrideForTask(sequential.agent, flatIndex, sequential.model));\n\t\tflatIndex++;\n\t}\n\treturn thinkingOverrides;\n}\n\nfunction firstChainAgent(chain: ChainStep[]): string | undefined {\n\tconst first = chain[0];\n\tif (!first) return undefined;\n\tif (isParallelStep(first)) return first.parallel[0]?.agent;\n\tif (isDynamicParallelStep(first)) return first.parallel.agent;\n\treturn (first as SequentialStep).agent;\n}\n\nfunction firstRawChainTask(chain: ChainStep[]): string | undefined {\n\tconst first = chain[0];\n\tif (!first) return undefined;\n\tif (isParallelStep(first)) return first.parallel[0]?.task;\n\tif (isDynamicParallelStep(first)) return first.parallel.task;\n\treturn (first as SequentialStep).task;\n}\n\nfunction resolveAsyncEventGoal(workflowTask: string | undefined, rawChain: ChainStep[], unwrapForkFallback = false): string {\n\tif (workflowTask?.trim()) return workflowTask;\n\tconst fallback = firstRawChainTask(rawChain) || \"\";\n\tif (!unwrapForkFallback) return fallback;\n\tconst forkPrefix = `${DEFAULT_FORK_PREAMBLE}\\n\\nTask:\\n`;\n\treturn fallback.startsWith(forkPrefix) ? fallback.slice(forkPrefix.length) : fallback;\n}\n\nfunction wrapChainTasksForFork(chain: ChainStep[], contextPolicy: AgentDefaultContextPolicy): ChainStep[] {\n\treturn chain.map((step, stepIndex) => {\n\t\tif (isParallelStep(step)) {\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tparallel: step.parallel.map((task) => ({\n\t\t\t\t\t...task,\n\t\t\t\t\ttask: shouldForkAgent(contextPolicy, task.agent)\n\t\t\t\t\t\t? wrapForkTask(task.task ?? \"{previous}\")\n\t\t\t\t\t\t: task.task,\n\t\t\t\t})),\n\t\t\t};\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tparallel: {\n\t\t\t\t\t...step.parallel,\n\t\t\t\t\ttask: shouldForkAgent(contextPolicy, step.parallel.agent)\n\t\t\t\t\t\t? wrapForkTask(step.parallel.task ?? \"{previous}\")\n\t\t\t\t\t\t: step.parallel.task,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\treturn {\n\t\t\t...sequential,\n\t\t\ttask: shouldForkAgent(contextPolicy, sequential.agent)\n\t\t\t\t? wrapForkTask(sequential.task ?? (stepIndex === 0 ? \"{task}\" : \"{previous}\"))\n\t\t\t\t: sequential.task,\n\t\t};\n\t});\n}\n\nfunction preflightForkSessionsForStaticTasks(\n\tparams: SubagentParamsLike,\n\tcontextPolicy: AgentDefaultContextPolicy,\n\tsessionFileForTask: ForkSessionFileForTask,\n\tdynamicFanoutMaxItems?: number,\n): void {\n\tif (!contextPolicy.usesFork) return;\n\tif (params.agent) {\n\t\tif (shouldForkAgent(contextPolicy, params.agent)) sessionFileForTask(params.agent, 0, params.model);\n\t\treturn;\n\t}\n\tif (params.tasks) {\n\t\tparams.tasks.forEach((task, index) => {\n\t\t\tif (shouldForkAgent(contextPolicy, task.agent)) sessionFileForTask(task.agent, index, task.model);\n\t\t});\n\t\treturn;\n\t}\n\tif (!params.chain?.length) return;\n\tlet flatIndex = 0;\n\tfor (const step of params.chain) {\n\t\tif (isParallelStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tif (shouldForkAgent(contextPolicy, task.agent)) sessionFileForTask(task.agent, flatIndex, task.model);\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\tconst maxItems = step.expand.maxItems ?? dynamicFanoutMaxItems ?? 0;\n\t\t\tif (shouldForkAgent(contextPolicy, step.parallel.agent)) {\n\t\t\t\tfor (let itemIndex = 0; itemIndex < maxItems; itemIndex++) sessionFileForTask(step.parallel.agent, flatIndex + itemIndex, step.parallel.model);\n\t\t\t}\n\t\t\tflatIndex += maxItems;\n\t\t\tcontinue;\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\tif (shouldForkAgent(contextPolicy, sequential.agent)) sessionFileForTask(sequential.agent, flatIndex, sequential.model);\n\t\tflatIndex++;\n\t}\n}\n\nfunction runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentToolResult<Details> | null {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tshareEnabled,\n\t\tsessionRoot,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactConfig,\n\t\tartifactsDir,\n\t\teffectiveAsync,\n\t\tcontrolConfig,\n\t\tintercomBridge,\n\t\tnestedRoute,\n\t\tcontextPolicy,\n\t} = data;\n\tconst hasChain = (params.chain?.length ?? 0) > 0;\n\tconst hasTasks = (params.tasks?.length ?? 0) > 0;\n\tconst hasSingle = !hasChain && !hasTasks && Boolean(params.agent);\n\tif (!effectiveAsync) return null;\n\n\tif (hasChain && params.chain) {\n\t\tconst chainWorktreeTaskCwdError = buildChainWorktreeTaskCwdError(params.chain as ChainStep[], effectiveCwd);\n\t\tif (chainWorktreeTaskCwdError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: chainWorktreeTaskCwdError }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t}\n\n\tif (hasTasks && params.tasks) {\n\t\tconst maxParallelTasks = resolveTopLevelParallelMaxTasks(deps.config.parallel?.maxTasks);\n\t\tif (params.tasks.length > maxParallelTasks) {\n\t\t\treturn buildParallelModeError(`Max ${maxParallelTasks} tasks`);\n\t\t}\n\t\tif (params.worktree) {\n\t\t\tconst worktreeTaskCwdError = buildParallelWorktreeTaskCwdError(params.tasks, effectiveCwd);\n\t\t\tif (worktreeTaskCwdError) return buildParallelModeError(worktreeTaskCwdError);\n\t\t}\n\t}\n\n\tif (!isAsyncAvailable()) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"Async mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t};\n\t}\n\tconst id = randomUUID();\n\tconst asyncCtx = {\n\t\tpi: deps.pi,\n\t\tcwd: ctx.cwd,\n\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\tcurrentModelProvider: ctx.model?.provider,\n\t\tcurrentModel: ctx.model,\n\t\tmodelScope: data.modelScope,\n\t};\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst currentProvider = ctx.model?.provider;\n\tconst controlIntercomTarget = intercomBridge.active ? intercomBridge.orchestratorTarget : undefined;\n\tconst childIntercomTarget = intercomBridge.active ? (agent: string, index: number) => resolveSubagentIntercomTarget(id, agent, index) : undefined;\n\n\tif (hasTasks && params.tasks) {\n\t\tconst skillOverrides = params.tasks.map((task) => normalizeSkillInput(task.skill));\n\t\tconst parallelTasks = params.tasks.map((task, index) => ({\n\t\t\tagent: task.agent,\n\t\t\ttask: shouldForkAgent(contextPolicy, task.agent) ? wrapForkTask(task.task) : task.task,\n\t\t\tcwd: task.cwd,\n\t\t\t...(task.model !== undefined ? { model: task.model } : {}),\n\t\t\t...(skillOverrides[index] !== undefined ? { skill: skillOverrides[index] } : {}),\n\t\t\t...(task.output !== undefined && task.output !== true ? { output: task.output } : {}),\n\t\t\t...(task.outputMode !== undefined ? { outputMode: task.outputMode } : {}),\n\t\t\t...(task.reads !== undefined && task.reads !== true ? { reads: task.reads } : {}),\n\t\t\t...(task.progress !== undefined ? { progress: task.progress } : {}),\n\t\t\t...(task.toolBudget !== undefined ? { toolBudget: task.toolBudget } : {}),\n\t\t\t...(task.acceptance !== undefined ? { acceptance: task.acceptance } : {}),\n\t\t}));\n\t\treturn executeAsyncChain(id, {\n\t\t\tchain: [{\n\t\t\t\tparallel: parallelTasks,\n\t\t\t\tconcurrency: resolveTopLevelParallelConcurrency(params.concurrency, deps.config.parallel?.concurrency),\n\t\t\t\tworktree: params.worktree,\n\t\t\t}],\n\t\t\tresultMode: \"parallel\",\n\t\t\tgoal: params.tasks[0]?.task ?? \"\",\n\t\t\tagents,\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tchainSkills: [],\n\t\t\tsessionFilesByFlatIndex: params.tasks.map((task, index) => sessionFileForTask(task.agent, index, task.model)),\n\t\t\tthinkingOverridesByFlatIndex: params.tasks.map((task, index) => thinkingOverrideForTask(task.agent, index, task.model)),\n\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget,\n\t\t\tchildIntercomTarget,\n\t\t\tnestedRoute,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t});\n\t}\n\n\tif (hasChain && params.chain) {\n\t\tconst normalized = normalizeSkillInput(params.skill);\n\t\tconst chainSkills = normalized === false ? [] : (normalized ?? []);\n\t\tconst rawChain = params.chain as ChainStep[];\n\t\tconst chain = wrapChainTasksForFork(rawChain, contextPolicy);\n\t\treturn executeAsyncChain(id, {\n\t\t\tchain,\n\t\t\ttask: params.task,\n\t\t\tgoal: resolveAsyncEventGoal(params.task, rawChain),\n\t\t\tagents,\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tchainSkills,\n\t\t\tsessionFilesByFlatIndex: collectChainSessionFiles(chain, sessionFileForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tthinkingOverridesByFlatIndex: collectChainThinkingOverrides(chain, thinkingOverrideForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget,\n\t\t\tchildIntercomTarget,\n\t\t\tnestedRoute,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t});\n\t}\n\n\tif (hasSingle) {\n\t\tconst a = agents.find((x) => x.name === params.agent);\n\t\tif (!a) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${params.agent}` }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tconst rawOutput = params.output !== undefined ? params.output : a.output;\n\t\tconst effectiveOutput = normalizeSingleOutputOverride(rawOutput, a.output);\n\t\tconst effectiveOutputMode = params.outputMode ?? \"inline\";\n\t\tconst normalizedSkills = normalizeSkillInput(params.skill);\n\t\tconst skills = normalizedSkills === false ? [] : normalizedSkills;\n\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(currentMaxSubagentDepth, a.maxSubagentDepth);\n\t\t// lunr: model tiers — explicit model wins; otherwise resolve params.tier via the tier bridge.\n\t\tconst modelOverride = resolveEffectiveSubagentModel((params.model as string | undefined) ?? resolveTierModelOverride(params.tier), a.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope });\n\t\treturn executeAsyncSingle(id, {\n\t\t\tagent: params.agent!,\n\t\t\ttask: shouldForkAgent(contextPolicy, params.agent!) ? wrapForkTask(params.task ?? \"\") : (params.task ?? \"\"),\n\t\t\tgoal: params.task ?? \"\",\n\t\t\tagentConfig: a,\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tsessionFile: sessionFileForTask(params.agent!, 0, modelOverride),\n\t\t\tskills,\n\t\t\toutput: effectiveOutput,\n\t\t\toutputMode: effectiveOutputMode,\n\t\t\toutputBaseDir: resolveSingleRunOutputBaseDir(deps, artifactsDir, id),\n\t\t\tmodelOverride,\n\t\t\tthinkingOverride: thinkingOverrideForTask(params.agent!, 0, modelOverride),\n\t\t\tmaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget,\n\t\t\tchildIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(agent, index) : undefined,\n\t\t\tnestedRoute,\n\t\t\tacceptance: params.acceptance,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t});\n\t}\n\n\treturn null;\n}\n\nasync function runChainPath(data: ExecutionContextData, deps: ExecutorDeps): Promise<AgentToolResult<Details>> {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tonUpdate,\n\t\tsessionRoot,\n\t\tcontrolConfig,\n\t\tcontextPolicy,\n\t} = data;\n\tconst onControlEvent = createForegroundControlNotifier(data, deps);\n\tconst childIntercomTarget = data.intercomBridge.active ? resolveSubagentIntercomTarget : undefined;\n\tconst foregroundControl = deps.state.foregroundControls.get(runId);\n\tconst normalized = normalizeSkillInput(params.skill);\n\tconst chainSkills = normalized === false ? [] : (normalized ?? []);\n\tconst chain = wrapChainTasksForFork(params.chain as ChainStep[], contextPolicy);\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst chainResult = await executeChain({\n\t\tchain,\n\t\ttask: params.task,\n\t\tagents,\n\t\tctx,\n\t\tmodelScope: data.modelScope,\n\t\tintercomEvents: deps.pi.events,\n\t\tsignal,\n\t\trunId,\n\t\tcwd: effectiveCwd,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tincludeProgress: params.includeProgress,\n\t\tclarify: params.clarify,\n\t\tonUpdate,\n\t\tonControlEvent,\n\t\tcontrolConfig,\n\t\tchildIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(runId, agent, index) : undefined,\n\t\torchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\tforegroundControl,\n\t\tnestedRoute: foregroundControl?.nestedRoute,\n\t\tchainSkills,\n\t\tchainDir: params.chainDir ?? getProjectChainRunsDir(effectiveCwd),\n\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\ttimeoutMs: data.timeoutMs,\n\t\tdeadlineAt: data.deadlineAt,\n\t\tturnBudget: data.turnBudget,\n\t\tonDetachedExit: (index, result) => updateRememberedForegroundChild(deps.state, { runId, mode: \"chain\", cwd: effectiveCwd, sessionId: data.parentSessionId, index, result, events: deps.pi.events }),\n\t\ttoolBudget: data.toolBudget,\n\t\tconfigToolBudget: data.configToolBudget,\n\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t});\n\n\tif (chainResult.requestedAsync) {\n\t\tif (!isAsyncAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tconst id = randomUUID();\n\t\tconst asyncCtx = {\n\t\t\tpi: deps.pi,\n\t\t\tcwd: ctx.cwd,\n\t\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\tcurrentModelProvider: ctx.model?.provider,\n\t\t\tcurrentModel: ctx.model,\n\t\t\tmodelScope: data.modelScope,\n\t\t};\n\t\tconst rawAsyncChain = chainResult.requestedAsync.chain;\n\t\tconst asyncChain = wrapChainTasksForFork(rawAsyncChain, contextPolicy);\n\t\tconst firstAgent = firstChainAgent(rawAsyncChain);\n\t\treturn executeAsyncChain(id, {\n\t\t\tchain: asyncChain,\n\t\t\ttask: params.task,\n\t\t\tgoal: resolveAsyncEventGoal(params.task, rawAsyncChain, firstAgent ? shouldForkAgent(contextPolicy, firstAgent) : false),\n\t\t\tagents,\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels: ctx.modelRegistry.getAvailable().map(toModelInfo),\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tchainSkills: chainResult.requestedAsync.chainSkills,\n\t\t\tsessionFilesByFlatIndex: collectChainSessionFiles(asyncChain, sessionFileForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tthinkingOverridesByFlatIndex: collectChainThinkingOverrides(asyncChain, thinkingOverrideForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\tchildIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,\n\t\t\tnestedRoute: data.nestedRoute,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t});\n\t}\n\n\tconst rawChainDetails = chainResult.details ? { ...chainResult.details, runId } : undefined;\n\tif (foregroundControl && rawChainDetails) {\n\t\tupdateForegroundNestedProjection(foregroundControl);\n\t\tattachRootChildrenToSteps(runId, rawChainDetails.results, foregroundControl.nestedChildren);\n\t\trawChainDetails.totalCost = sumResultsCost(rawChainDetails.results);\n\t}\n\tconst chainDetails = rawChainDetails ? compactForegroundDetails(rawChainDetails) : undefined;\n\tif (chainDetails) rememberForegroundRun(deps.state, { runId, mode: \"chain\", cwd: effectiveCwd, sessionId: data.parentSessionId, results: chainDetails.results });\n\tconst intercomReceipt = chainDetails && !chainDetails.results.some((result) => result.interrupted || result.detached)\n\t\t? await maybeBuildForegroundIntercomReceipt({\n\t\t\tpi: deps.pi,\n\t\t\tintercomBridge: data.intercomBridge,\n\t\t\trunId,\n\t\t\tmode: \"chain\",\n\t\t\tdetails: chainDetails,\n\t\t\t...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),\n\t\t})\n\t\t: null;\n\tif (intercomReceipt) {\n\t\treturn {\n\t\t\t...chainResult,\n\t\t\tcontent: [{ type: \"text\", text: intercomReceipt.text }],\n\t\t\tdetails: intercomReceipt.details,\n\t\t};\n\t}\n\n\treturn chainDetails ? { ...chainResult, details: chainDetails } : chainResult;\n}\n\ninterface ForegroundParallelRunInput {\n\ttasks: TaskParam[];\n\ttaskTexts: string[];\n\tagents: AgentConfig[];\n\tctx: ExtensionContext;\n\tstate: SubagentState;\n\tintercomEvents: IntercomEventBus;\n\tparentSessionId: string | null;\n\tsignal: AbortSignal;\n\trunId: string;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex: (idx?: number) => string | undefined;\n\tsessionFileForTask: ForkSessionFileForTask;\n\tthinkingOverrideForTask: ForkThinkingOverrideForTask;\n\tshareEnabled: boolean;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\toutputBaseDir: string;\n\tmaxOutput?: MaxOutputConfig;\n\tparamsCwd: string;\n\tprogressDir: string;\n\tmaxSubagentDepths: number[];\n\twaitToolEnabled?: boolean;\n\tavailableModels: ModelInfo[];\n\tmodelScope?: ModelScopeConfig;\n\tmodelOverrides: (string | undefined)[];\n\tbehaviors: Array<ReturnType<typeof resolveStepBehavior>>;\n\tfirstProgressIndex: number;\n\tcontrolConfig: ResolvedControlConfig;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never;\n\tconcurrencyLimit: number;\n\tglobalSemaphore?: Semaphore;\n\tliveResults: (SingleResult | undefined)[];\n\tliveProgress: (AgentProgress | undefined)[];\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tworktreeSetup?: WorktreeSetup;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\ttoolBudgets: (ResolvedToolBudget | undefined)[];\n}\n\nfunction buildParallelModeError(message: string): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tisError: true,\n\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t};\n}\n\nfunction createParallelWorktreeSetup(\n\tenabled: boolean | undefined,\n\tcwd: string,\n\trunId: string,\n\ttasks: TaskParam[],\n\tsetupHook: ExtensionConfig[\"worktreeSetupHook\"],\n\tsetupHookTimeoutMs: ExtensionConfig[\"worktreeSetupHookTimeoutMs\"],\n\tbaseDir: ExtensionConfig[\"worktreeBaseDir\"],\n): { setup?: WorktreeSetup; errorResult?: AgentToolResult<Details> } {\n\tif (!enabled) return {};\n\ttry {\n\t\treturn {\n\t\t\tsetup: createWorktrees(cwd, runId, tasks.length, {\n\t\t\t\tagents: tasks.map((task) => task.agent),\n\t\t\t\tsetupHook: setupHook\n\t\t\t\t\t? { hookPath: setupHook, timeoutMs: setupHookTimeoutMs }\n\t\t\t\t\t: undefined,\n\t\t\t\tbaseDir,\n\t\t\t}),\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { errorResult: buildParallelModeError(message) };\n\t}\n}\n\nfunction buildParallelWorktreeTaskCwdError(\n\ttasks: ReadonlyArray<{ agent: string; cwd?: string }>,\n\tsharedCwd: string,\n): string | undefined {\n\tconst conflict = findWorktreeTaskCwdConflict(tasks, sharedCwd);\n\tif (!conflict) return undefined;\n\treturn formatWorktreeTaskCwdConflict(conflict, sharedCwd);\n}\n\nfunction resolveSingleRunOutputBaseDir(deps: ExecutorDeps, artifactsDir: string, runId: string): string {\n\treturn deps.config.singleRunOutputBaseDir\n\t\t? path.resolve(deps.expandTilde(deps.config.singleRunOutputBaseDir))\n\t\t: path.join(artifactsDir, \"outputs\", runId);\n}\n\nfunction buildChainWorktreeTaskCwdError(chain: ChainStep[], sharedCwd: string): string | undefined {\n\tfor (let stepIndex = 0; stepIndex < chain.length; stepIndex++) {\n\t\tconst step = chain[stepIndex]!;\n\t\tif (!isParallelStep(step) || !step.worktree) continue;\n\t\tconst stepCwd = resolveChildCwd(sharedCwd, step.cwd);\n\t\tconst conflict = findWorktreeTaskCwdConflict(step.parallel, stepCwd);\n\t\tif (!conflict) continue;\n\t\tconst detail = formatWorktreeTaskCwdConflict(conflict, stepCwd);\n\t\treturn `parallel chain step ${stepIndex + 1}: ${detail}`;\n\t}\n\treturn undefined;\n}\n\nfunction resolveParallelTaskCwd(\n\ttask: TaskParam,\n\tparamsCwd: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\tindex: number,\n): string {\n\tif (worktreeSetup) return worktreeSetup.worktrees[index]!.agentCwd;\n\treturn resolveChildCwd(paramsCwd, task.cwd);\n}\n\nfunction buildParallelWorktreeSuffix(\n\tworktreeSetup: WorktreeSetup | undefined,\n\tartifactsDir: string,\n\ttasks: TaskParam[],\n): string {\n\tif (!worktreeSetup) return \"\";\n\tconst diffsDir = path.join(artifactsDir, \"worktree-diffs\");\n\tconst diffs = diffWorktrees(worktreeSetup, tasks.map((task) => task.agent), diffsDir);\n\treturn formatWorktreeDiffSummary(diffs);\n}\n\nfunction findDuplicateParallelOutputPath(input: {\n\ttasks: TaskParam[];\n\tbehaviors: ResolvedStepBehavior[];\n\tparamsCwd: string;\n\tctxCwd: string;\n\toutputBaseDir: string;\n\tworktreeSetup?: WorktreeSetup;\n}): string | undefined {\n\tconst seen = new Map<string, { index: number; agent: string }>();\n\tfor (let index = 0; index < input.tasks.length; index++) {\n\t\tconst behavior = input.behaviors[index];\n\t\tif (!behavior?.output) continue;\n\t\tconst task = input.tasks[index]!;\n\t\tconst taskCwd = resolveParallelTaskCwd(task, input.paramsCwd, input.worktreeSetup, index);\n\t\tconst outputPath = resolveSingleOutputPath(behavior.output, input.ctxCwd, taskCwd, input.outputBaseDir);\n\t\tif (!outputPath) continue;\n\t\tconst previous = seen.get(outputPath);\n\t\tif (previous) {\n\t\t\treturn `Parallel tasks ${previous.index + 1} (${previous.agent}) and ${index + 1} (${task.agent}) resolve output to the same path: ${outputPath}. Use distinct output paths.`;\n\t\t}\n\t\tseen.set(outputPath, { index, agent: task.agent });\n\t}\n\treturn undefined;\n}\n\nasync function runForegroundParallelTasks(input: ForegroundParallelRunInput): Promise<SingleResult[]> {\n\t// Pre-warm fork session files sequentially before concurrent dispatch to avoid\n\t// races where multiple workers simultaneously try to branch the same parent session.\n\tfor (let i = 0; i < input.tasks.length; i++) {\n\t\tinput.sessionFileForTask(input.tasks[i]!.agent, i, input.modelOverrides[i]);\n\t}\n\treturn mapConcurrent(input.tasks, input.concurrencyLimit, async (task, index) => {\n\t\tconst behavior = input.behaviors[index];\n\t\tconst effectiveSkills = behavior?.skills;\n\t\tconst taskCwd = resolveParallelTaskCwd(task, input.paramsCwd, input.worktreeSetup, index);\n\t\tconst readInstructions = behavior\n\t\t\t? buildChainInstructions({ ...behavior, output: false, progress: false }, taskCwd, false)\n\t\t\t: { prefix: \"\", suffix: \"\" };\n\t\tconst progressInstructions = behavior\n\t\t\t? buildChainInstructions({ ...behavior, output: false, reads: false }, input.progressDir, index === input.firstProgressIndex)\n\t\t\t: { prefix: \"\", suffix: \"\" };\n\t\tconst outputPath = resolveSingleOutputPath(behavior?.output, input.ctx.cwd, taskCwd, input.outputBaseDir);\n\t\tconst agentConfig = input.agents.find((agent) => agent.name === task.agent);\n\t\tconst taskText = injectSingleOutputInstruction(\n\t\t\t`${readInstructions.prefix}${input.taskTexts[index]!}${progressInstructions.suffix}`,\n\t\t\toutputPath,\n\t\t\tagentConfig,\n\t\t);\n\t\tconst interruptController = new AbortController();\n\t\tif (input.foregroundControl) {\n\t\t\tinput.foregroundControl.currentAgent = task.agent;\n\t\t\tinput.foregroundControl.currentIndex = index;\n\t\t\tinput.foregroundControl.currentActivityState = undefined;\n\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\tinput.foregroundControl.interrupt = () => {\n\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\tinterruptController.abort();\n\t\t\t\tinput.foregroundControl!.currentActivityState = undefined;\n\t\t\t\tinput.foregroundControl!.updatedAt = Date.now();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\t\treturn runSync(input.ctx.cwd, input.agents, task.agent, taskText, {\n\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\tcwd: taskCwd,\n\t\t\tsignal: input.signal,\n\t\t\tinterruptSignal: interruptController.signal,\n\t\t\tallowIntercomDetach: agentConfig?.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\tintercomEvents: input.intercomEvents,\n\t\t\trunId: input.runId,\n\t\t\tindex,\n\t\t\tsessionDir: input.sessionDirForIndex(index),\n\t\t\tsessionFile: input.sessionFileForTask(task.agent, index, input.modelOverrides[index]),\n\t\t\tshare: input.shareEnabled,\n\t\t\tartifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,\n\t\t\tartifactConfig: input.artifactConfig,\n\t\t\tmaxOutput: input.maxOutput,\n\t\t\toutputPath,\n\t\t\toutputMode: behavior?.outputMode,\n\t\t\tmaxSubagentDepth: input.maxSubagentDepths[index],\n\t\t\twaitToolEnabled: input.waitToolEnabled,\n\t\t\tcontrolConfig: input.controlConfig,\n\t\t\tonControlEvent: input.onControlEvent,\n\t\t\tonDetachedExit: (result) => updateRememberedForegroundChild(input.state, { runId: input.runId, mode: \"parallel\", cwd: taskCwd, sessionId: input.parentSessionId, index, result, events: input.intercomEvents }),\n\t\t\tintercomSessionName: input.childIntercomTarget?.(task.agent, index),\n\t\t\torchestratorIntercomTarget: input.orchestratorIntercomTarget,\n\t\t\tnestedRoute: input.foregroundControl?.nestedRoute,\n\t\t\tmodelOverride: input.modelOverrides[index],\n\t\t\tthinkingOverride: input.thinkingOverrideForTask(task.agent, index, input.modelOverrides[index]),\n\t\t\tavailableModels: input.availableModels,\n\t\t\tpreferredModelProvider: input.ctx.model?.provider,\n\t\t\tmodelScope: input.modelScope,\n\t\t\tskills: effectiveSkills === false ? [] : effectiveSkills,\n\t\t\tacceptance: task.acceptance,\n\t\t\tacceptanceContext: { mode: \"parallel\" },\n\t\t\ttimeoutMs: input.timeoutMs,\n\t\t\tdeadlineAt: input.deadlineAt,\n\t\t\tturnBudget: input.turnBudget,\n\t\t\ttoolBudget: input.toolBudgets[index],\n\t\t\tonUpdate: input.onUpdate\n\t\t\t\t? (progressUpdate) => {\n\t\t\t\t\tconst stepResults = progressUpdate.details?.results || [];\n\t\t\t\t\tconst stepProgress = progressUpdate.details?.progress || [];\n\t\t\t\t\tif (input.foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\tconst current = stepProgress[0];\n\t\t\t\t\t\tinput.foregroundControl.currentAgent = task.agent;\n\t\t\t\t\t\tinput.foregroundControl.currentIndex = index;\n\t\t\t\t\t\tinput.foregroundControl.currentActivityState = current?.activityState;\n\t\t\t\t\t\tinput.foregroundControl.lastActivityAt = current?.lastActivityAt;\n\t\t\t\t\t\tinput.foregroundControl.currentTool = current?.currentTool;\n\t\t\t\t\t\tinput.foregroundControl.currentToolStartedAt = current?.currentToolStartedAt;\n\t\t\t\t\t\tinput.foregroundControl.currentPath = current?.currentPath;\n\t\t\t\t\t\tinput.foregroundControl.turnCount = current?.turnCount;\n\t\t\t\t\t\tinput.foregroundControl.tokens = current?.tokens;\n\t\t\t\t\t\tinput.foregroundControl.toolCount = current?.toolCount;\n\t\t\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t\tif (stepResults.length > 0) input.liveResults[index] = stepResults[0];\n\t\t\t\t\tif (stepProgress.length > 0) input.liveProgress[index] = stepProgress[0];\n\t\t\t\t\tconst mergedResults = input.liveResults.filter((result): result is SingleResult => result !== undefined);\n\t\t\t\t\tconst mergedProgress = input.liveProgress.filter((progress): progress is AgentProgress => progress !== undefined);\n\t\t\t\t\tinput.onUpdate?.({\n\t\t\t\t\t\tcontent: progressUpdate.content,\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\tmode: \"parallel\",\n\t\t\t\t\t\t\tresults: mergedResults,\n\t\t\t\t\t\t\tprogress: mergedProgress,\n\t\t\t\t\t\t\tcontrolEvents: progressUpdate.details?.controlEvents,\n\t\t\t\t\t\t\ttotalSteps: input.tasks.length,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t}).finally(() => {\n\t\t\tif (input.foregroundControl?.currentIndex === index) {\n\t\t\t\tinput.foregroundControl.interrupt = undefined;\n\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t}\n\t\t});\n\t}, input.globalSemaphore);\n}\n\nasync function runParallelPath(data: ExecutionContextData, deps: ExecutorDeps): Promise<AgentToolResult<Details>> {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tshareEnabled,\n\t\tartifactConfig,\n\t\tartifactsDir,\n\t\tbackgroundRequestedWhileClarifying,\n\t\tonUpdate,\n\t\tsessionRoot,\n\t\tcontrolConfig,\n\t\tcontextPolicy,\n\t} = data;\n\tconst onControlEvent = createForegroundControlNotifier(data, deps);\n\tconst childIntercomTarget = data.intercomBridge.active ? resolveSubagentIntercomTarget : undefined;\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\tconst tasks = params.tasks!;\n\tconst maxParallelTasks = resolveTopLevelParallelMaxTasks(deps.config.parallel?.maxTasks);\n\tconst parallelConcurrency = resolveTopLevelParallelConcurrency(params.concurrency, deps.config.parallel?.concurrency);\n\n\tif (tasks.length > maxParallelTasks)\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Max ${maxParallelTasks} tasks` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t};\n\n\tconst agentConfigs: AgentConfig[] = [];\n\tfor (const t of tasks) {\n\t\tconst config = agents.find((a) => a.name === t.agent);\n\t\tif (!config) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${t.agent}` }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tagentConfigs.push(config);\n\t}\n\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst maxSubagentDepths = agentConfigs.map((config) =>\n\t\tresolveChildMaxSubagentDepth(currentMaxSubagentDepth, config.maxSubagentDepth),\n\t);\n\tconst toolBudgets: (ResolvedToolBudget | undefined)[] = [];\n\tfor (let index = 0; index < tasks.length; index++) {\n\t\tconst resolved = resolveEffectiveToolBudget({ stepBudget: tasks[index]?.toolBudget, runBudget: data.toolBudget, agentBudget: agentConfigs[index]?.toolBudget, configBudget: data.configToolBudget });\n\t\tif (resolved.error) return buildParallelModeError(resolved.error);\n\t\ttoolBudgets.push(resolved.toolBudget);\n\t}\n\n\tif (params.worktree) {\n\t\tconst worktreeTaskCwdError = buildParallelWorktreeTaskCwdError(tasks, effectiveCwd);\n\t\tif (worktreeTaskCwdError) return buildParallelModeError(worktreeTaskCwdError);\n\t}\n\n\tconst currentProvider = ctx.model?.provider;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tlet taskTexts = tasks.map((t) => t.task);\n\tconst skillOverrides: (string[] | false | undefined)[] = tasks.map((t) =>\n\t\tnormalizeSkillInput(t.skill),\n\t);\n\tconst behaviorOverrides: StepOverrides[] = tasks.map((task, index) => ({\n\t\t...(task.output !== undefined && task.output !== true ? { output: task.output } : {}),\n\t\t...(task.outputMode !== undefined ? { outputMode: task.outputMode } : {}),\n\t\t...(task.reads !== undefined && task.reads !== true ? { reads: task.reads } : {}),\n\t\t...(task.progress !== undefined ? { progress: task.progress } : {}),\n\t\t...(skillOverrides[index] !== undefined ? { skills: skillOverrides[index] } : {}),\n\t\t...(task.model !== undefined ? { model: task.model } : {}),\n\t}));\n\tconst modelOverrides: (string | undefined)[] = tasks.map((task, i) =>\n\t\t// lunr: model tiers — explicit per-task model wins; otherwise resolve task.tier via the tier bridge.\n\t\tresolveEffectiveSubagentModel(behaviorOverrides[i]?.model ?? resolveTierModelOverride(task.tier), agentConfigs[i]?.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope }),\n\t);\n\n\tif (params.clarify === true && ctx.hasUI) {\n\t\tconst behaviors = agentConfigs.map((c, i) =>\n\t\t\tresolveStepBehavior(c, behaviorOverrides[i]!),\n\t\t);\n\t\tconst availableSkills = discoverAvailableSkills(effectiveCwd);\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui, theme,\n\t\t\t\t\tagentConfigs,\n\t\t\t\t\ttaskTexts,\n\t\t\t\t\t\"\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tbehaviors,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tcurrentProvider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t\t\"parallel\",\n\t\t\t\t),\n\t\t\t{ overlay: true, overlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" } },\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\treturn { content: [{ type: \"text\", text: \"Cancelled\" }], details: { mode: \"parallel\", results: [] } };\n\t\t}\n\n\t\ttaskTexts = result.templates;\n\t\tfor (let i = 0; i < result.behaviorOverrides.length; i++) {\n\t\t\tconst override = result.behaviorOverrides[i];\n\t\t\tif (override?.model !== undefined) {\n\t\t\t\tmodelOverrides[i] = resolveEffectiveSubagentModel(override.model, agentConfigs[i]?.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope });\n\t\t\t\tbehaviorOverrides[i]!.model = override.model;\n\t\t\t}\n\t\t\tif (override?.output !== undefined) behaviorOverrides[i]!.output = override.output;\n\t\t\tif (override?.reads !== undefined) behaviorOverrides[i]!.reads = override.reads;\n\t\t\tif (override?.progress !== undefined) behaviorOverrides[i]!.progress = override.progress;\n\t\t\tif (override?.skills !== undefined) {\n\t\t\t\tskillOverrides[i] = override.skills;\n\t\t\t\tbehaviorOverrides[i]!.skills = override.skills;\n\t\t\t}\n\t\t}\n\n\t\tif (result.runInBackground) {\n\t\t\tif (!isAsyncAvailable()) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst id = randomUUID();\n\t\t\tconst asyncCtx = {\n\t\t\t\tpi: deps.pi,\n\t\t\t\tcwd: ctx.cwd,\n\t\t\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcurrentModelProvider: ctx.model?.provider,\n\t\t\t\tcurrentModel: ctx.model,\n\t\t\t\tmodelScope: data.modelScope,\n\t\t\t};\n\t\t\tconst parallelTasks = tasks.map((t, i) => {\n\t\t\t\tconst taskText = shouldForkAgent(contextPolicy, t.agent) ? wrapForkTask(taskTexts[i]!) : taskTexts[i]!;\n\t\t\t\tconst progress = taskDisallowsFileUpdates(taskText) ? false : behaviorOverrides[i]?.progress;\n\t\t\t\treturn {\n\t\t\t\t\tagent: t.agent,\n\t\t\t\t\ttask: taskText,\n\t\t\t\t\tcwd: t.cwd,\n\t\t\t\t\t...(behaviorOverrides[i]?.model !== undefined ? { model: behaviorOverrides[i]!.model } : {}),\n\t\t\t\t\t...(skillOverrides[i] !== undefined ? { skill: skillOverrides[i] } : {}),\n\t\t\t\t\t...(behaviorOverrides[i]?.output !== undefined ? { output: behaviorOverrides[i]!.output } : {}),\n\t\t\t\t\t...(behaviorOverrides[i]?.outputMode !== undefined ? { outputMode: behaviorOverrides[i]!.outputMode } : {}),\n\t\t\t\t\t...(behaviorOverrides[i]?.reads !== undefined ? { reads: behaviorOverrides[i]!.reads } : {}),\n\t\t\t\t\t...(progress !== undefined ? { progress } : {}),\n\t\t\t\t\t...(t.toolBudget !== undefined ? { toolBudget: t.toolBudget } : {}),\n\t\t\t\t\t...(t.acceptance !== undefined ? { acceptance: t.acceptance } : {}),\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn executeAsyncChain(id, {\n\t\t\t\tchain: [{ parallel: parallelTasks, concurrency: parallelConcurrency, worktree: params.worktree }],\n\t\t\t\tresultMode: \"parallel\",\n\t\t\t\tgoal: taskTexts[0] ?? \"\",\n\t\t\t\tagents,\n\t\t\t\tctx: asyncCtx,\n\t\t\t\tavailableModels,\n\t\t\t\tcwd: effectiveCwd,\n\t\t\t\tmaxOutput: params.maxOutput,\n\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\tartifactConfig,\n\t\t\t\tshareEnabled,\n\t\t\t\tsessionRoot,\n\t\t\t\tchainSkills: [],\n\t\t\t\tsessionFilesByFlatIndex: tasks.map((task, index) => sessionFileForTask(task.agent, index, modelOverrides[index])),\n\t\t\t\tthinkingOverridesByFlatIndex: tasks.map((task, index) => thinkingOverrideForTask(task.agent, index, modelOverrides[index])),\n\t\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\t\tcontrolConfig,\n\t\t\t\tcontrolIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\t\tchildIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,\n\t\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\t\tturnBudget: data.turnBudget,\n\t\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t\t});\n\t\t}\n\t}\n\n\tconst behaviors = agentConfigs.map((config, index) => suppressProgressForReadOnlyTask(resolveStepBehavior(config, behaviorOverrides[index]!), taskTexts[index]));\n\tconst firstProgressIndex = behaviors.findIndex((behavior) => behavior.progress);\n\tconst liveResults: (SingleResult | undefined)[] = new Array(tasks.length).fill(undefined);\n\tconst liveProgress: (AgentProgress | undefined)[] = new Array(tasks.length).fill(undefined);\n\tconst foregroundControl = deps.state.foregroundControls.get(runId);\n\tconst { setup: worktreeSetup, errorResult } = createParallelWorktreeSetup(\n\t\tparams.worktree,\n\t\teffectiveCwd,\n\t\trunId,\n\t\ttasks,\n\t\tdeps.config.worktreeSetupHook,\n\t\tdeps.config.worktreeSetupHookTimeoutMs,\n\t\tdeps.config.worktreeBaseDir,\n\t);\n\tif (errorResult) return errorResult;\n\n\ttry {\n\t\tconst outputBaseDir = path.join(artifactsDir, \"outputs\", runId);\n\t\tconst duplicateOutputError = findDuplicateParallelOutputPath({\n\t\t\ttasks,\n\t\t\tbehaviors,\n\t\t\tparamsCwd: effectiveCwd,\n\t\t\tctxCwd: ctx.cwd,\n\t\t\toutputBaseDir,\n\t\t\tworktreeSetup,\n\t\t});\n\t\tif (duplicateOutputError) return buildParallelModeError(duplicateOutputError);\n\t\tfor (let index = 0; index < tasks.length; index++) {\n\t\t\tconst taskCwd = resolveParallelTaskCwd(tasks[index]!, effectiveCwd, worktreeSetup, index);\n\t\t\tconst outputPath = resolveSingleOutputPath(behaviors[index]?.output, ctx.cwd, taskCwd, outputBaseDir);\n\t\t\tconst validationError = validateFileOnlyOutputMode(behaviors[index]?.outputMode, outputPath, `Parallel task ${index + 1} (${tasks[index]!.agent})`);\n\t\t\tif (validationError) return buildParallelModeError(validationError);\n\t\t}\n\n\t\tconst parallelProgressPrecreated = firstProgressIndex !== -1;\n\t\tconst parallelProgressDir = path.join(artifactsDir, \"progress\", runId);\n\t\tif (parallelProgressPrecreated) writeInitialProgressFile(parallelProgressDir);\n\n\t\tfor (let i = 0; i < taskTexts.length; i++) {\n\t\t\tif (shouldForkAgent(contextPolicy, tasks[i]!.agent)) taskTexts[i] = wrapForkTask(taskTexts[i]!);\n\t\t}\n\n\t\tconst deadlineAt = data.deadlineAt ?? (data.timeoutMs !== undefined ? Date.now() + data.timeoutMs : undefined);\n\t\tconst results = await runForegroundParallelTasks({\n\t\t\ttasks,\n\t\t\ttaskTexts,\n\t\t\tagents,\n\t\t\tctx,\n\t\t\tstate: deps.state,\n\t\t\tintercomEvents: deps.pi.events,\n\t\t\tparentSessionId: data.parentSessionId,\n\t\t\tsignal,\n\t\t\trunId,\n\t\t\tsessionDirForIndex,\n\t\t\tsessionFileForIndex,\n\t\t\tsessionFileForTask,\n\t\t\tthinkingOverrideForTask,\n\t\t\tshareEnabled,\n\t\t\tartifactConfig,\n\t\t\tartifactsDir,\n\t\t\toutputBaseDir,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tparamsCwd: effectiveCwd,\n\t\t\tprogressDir: parallelProgressDir,\n\t\t\tavailableModels,\n\t\t\tmodelScope: data.modelScope,\n\t\t\tmodelOverrides,\n\t\t\tbehaviors,\n\t\t\tfirstProgressIndex: parallelProgressPrecreated ? -1 : firstProgressIndex,\n\t\t\tcontrolConfig,\n\t\t\tonControlEvent,\n\t\t\tchildIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(runId, agent, index) : undefined,\n\t\t\torchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\tforegroundControl,\n\t\t\tconcurrencyLimit: parallelConcurrency,\n\t\t\tglobalSemaphore: new Semaphore(deps.config.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT),\n\t\t\tmaxSubagentDepths,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tliveResults,\n\t\t\tliveProgress,\n\t\t\tonUpdate,\n\t\t\tworktreeSetup,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tdeadlineAt,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudgets,\n\t\t});\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst run = results[i]!;\n\t\t\trecordRun(run.agent, taskTexts[i]!, run.exitCode, run.progressSummary?.durationMs ?? 0);\n\t\t}\n\n\t\tfor (const result of results) {\n\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t}\n\n\t\tif (foregroundControl) {\n\t\t\tupdateForegroundNestedProjection(foregroundControl);\n\t\t\tattachRootChildrenToSteps(runId, results, foregroundControl.nestedChildren);\n\t\t}\n\t\tconst interrupted = results.find((result) => result.interrupted);\n\t\tconst details = compactForegroundDetails({\n\t\t\tmode: \"parallel\",\n\t\t\trunId,\n\t\t\tresults,\n\t\t\tprogress: params.includeProgress ? allProgress : undefined,\n\t\t\tartifacts: allArtifactPaths.length ? { dir: artifactsDir, files: allArtifactPaths } : undefined,\n\t\t\ttotalChildUsage: sumResultsUsage(results),\n\t\t\ttotalCost: sumResultsCost(results),\n\t\t});\n\t\trememberForegroundRun(deps.state, { runId, mode: \"parallel\", cwd: effectiveCwd, sessionId: data.parentSessionId, results: details.results });\n\t\tif (interrupted) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Parallel run paused after interrupt (${interrupted.agent}). Waiting for explicit next action.` }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t}\n\t\tconst detachedIndex = results.findIndex((result) => result.detached);\n\t\tconst detached = detachedIndex >= 0 ? results[detachedIndex] : undefined;\n\t\tif (detached) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Parallel run detached for intercom coordination (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t}\n\n\t\tif (foregroundControl) updateForegroundNestedProjection(foregroundControl);\n\t\tconst intercomReceipt = await maybeBuildForegroundIntercomReceipt({\n\t\t\tpi: deps.pi,\n\t\t\tintercomBridge: data.intercomBridge,\n\t\t\trunId,\n\t\t\tmode: \"parallel\",\n\t\t\tdetails,\n\t\t\t...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),\n\t\t});\n\t\tif (intercomReceipt) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: intercomReceipt.text }],\n\t\t\t\tdetails: intercomReceipt.details,\n\t\t\t};\n\t\t}\n\n\t\tconst worktreeSuffix = buildParallelWorktreeSuffix(worktreeSetup, artifactsDir, tasks);\n\t\tconst ok = results.filter((result) => result.exitCode === 0).length;\n\t\tconst downgradeNote = backgroundRequestedWhileClarifying ? \" (background requested, but clarify kept this run foreground)\" : \"\";\n\t\tconst aggregatedOutput = aggregateParallelOutputs(\n\t\t\tresults.map((result) => ({\n\t\t\t\tagent: result.agent,\n\t\t\t\toutput: result.truncation?.text || getSingleResultOutput(result),\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\terror: result.error,\n\t\t\t\ttimedOut: result.timedOut,\n\t\t\t})),\n\t\t\t(i, agent) => `=== Task ${i + 1}: ${agent} ===`,\n\t\t);\n\n\t\tconst summary = `${ok}/${results.length} succeeded${downgradeNote}`;\n\t\tconst fullContent = worktreeSuffix\n\t\t\t? `${summary}\\n\\n${aggregatedOutput}\\n\\n${worktreeSuffix}`\n\t\t\t: `${summary}\\n\\n${aggregatedOutput}`;\n\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: fullContent }],\n\t\t\tdetails,\n\t\t};\n\t} finally {\n\t\tif (worktreeSetup) cleanupWorktrees(worktreeSetup);\n\t}\n}\n\nasync function runSinglePath(data: ExecutionContextData, deps: ExecutorDeps): Promise<AgentToolResult<Details>> {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tsessionDirForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tshareEnabled,\n\t\tartifactConfig,\n\t\tartifactsDir,\n\t\tonUpdate,\n\t\tsessionRoot,\n\t\tcontrolConfig,\n\t\tcontextPolicy,\n\t} = data;\n\tconst onControlEvent = createForegroundControlNotifier(data, deps);\n\tconst childIntercomTarget = data.intercomBridge.active ? resolveSubagentIntercomTarget(runId, params.agent!, 0) : undefined;\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\tconst agentConfig = agents.find((a) => a.name === params.agent);\n\tif (!agentConfig) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${params.agent}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\", results: [] },\n\t\t};\n\t}\n\tconst effectiveToolBudget = resolveEffectiveToolBudget({ runBudget: data.toolBudget, agentBudget: agentConfig.toolBudget, configBudget: data.configToolBudget });\n\tif (effectiveToolBudget.error) return toExecutionErrorResult(params, new Error(effectiveToolBudget.error));\n\n\tconst currentProvider = ctx.model?.provider;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tlet task = params.task ?? \"\";\n\t// lunr: model tiers — explicit model wins; otherwise resolve params.tier via the tier bridge.\n\tlet modelOverride: string | undefined = resolveEffectiveSubagentModel(\n\t\t(params.model as string | undefined) ?? resolveTierModelOverride(params.tier),\n\t\tagentConfig.model,\n\t\tctx.model,\n\t\tavailableModels,\n\t\tcurrentProvider,\n\t\t{ scope: data.modelScope },\n\t);\n\tlet skillOverride: string[] | false | undefined = normalizeSkillInput(params.skill);\n\tconst rawOutput = params.output !== undefined ? params.output : agentConfig.output;\n\tlet effectiveOutput = normalizeSingleOutputOverride(rawOutput, agentConfig.output);\n\tconst effectiveOutputMode = params.outputMode ?? \"inline\";\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(currentMaxSubagentDepth, agentConfig.maxSubagentDepth);\n\n\tif (params.clarify === true && ctx.hasUI) {\n\t\tconst behavior = resolveStepBehavior(agentConfig, { output: effectiveOutput, skills: skillOverride });\n\t\tconst availableSkills = discoverAvailableSkills(effectiveCwd);\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui, theme,\n\t\t\t\t\t[agentConfig],\n\t\t\t\t\t[task],\n\t\t\t\t\ttask,\n\t\t\t\t\tundefined,\n\t\t\t\t\t[behavior],\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tcurrentProvider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t\t\"single\",\n\t\t\t\t),\n\t\t\t{ overlay: true, overlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" } },\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\treturn { content: [{ type: \"text\", text: \"Cancelled\" }], details: { mode: \"single\", results: [] } };\n\t\t}\n\n\t\ttask = result.templates[0]!;\n\t\tconst override = result.behaviorOverrides[0];\n\t\tif (override?.model !== undefined) modelOverride = resolveEffectiveSubagentModel(override.model, agentConfig.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope });\n\t\tif (override?.output !== undefined) effectiveOutput = normalizeSingleOutputOverride(override.output, agentConfig.output);\n\t\tif (override?.skills !== undefined) skillOverride = override.skills;\n\n\t\tif (result.runInBackground) {\n\t\t\tif (!isAsyncAvailable()) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst id = randomUUID();\n\t\t\tconst asyncCtx = {\n\t\t\t\tpi: deps.pi,\n\t\t\t\tcwd: ctx.cwd,\n\t\t\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcurrentModelProvider: ctx.model?.provider,\n\t\t\t\tcurrentModel: ctx.model,\n\t\t\t\tmodelScope: data.modelScope,\n\t\t\t};\n\t\t\treturn executeAsyncSingle(id, {\n\t\t\t\tagent: params.agent!,\n\t\t\t\ttask: shouldForkAgent(contextPolicy, params.agent!) ? wrapForkTask(task) : task,\n\t\t\t\tgoal: task,\n\t\t\t\tagentConfig,\n\t\t\t\tctx: asyncCtx,\n\t\t\t\tavailableModels,\n\t\t\t\tcwd: effectiveCwd,\n\t\t\t\tmaxOutput: params.maxOutput,\n\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\tartifactConfig,\n\t\t\t\tshareEnabled,\n\t\t\t\tsessionRoot,\n\t\t\t\tsessionFile: sessionFileForTask(params.agent!, 0, modelOverride),\n\t\t\t\tskills: skillOverride === false ? [] : skillOverride,\n\t\t\t\toutput: effectiveOutput,\n\t\t\t\toutputMode: effectiveOutputMode,\n\t\t\t\toutputBaseDir: resolveSingleRunOutputBaseDir(deps, artifactsDir, id),\n\t\t\t\tmodelOverride,\n\t\t\t\tthinkingOverride: thinkingOverrideForTask(params.agent!, 0, modelOverride),\n\t\t\t\tmaxSubagentDepth,\n\t\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\t\tcontrolConfig,\n\t\t\t\tcontrolIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\t\tchildIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,\n\t\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\t\tturnBudget: data.turnBudget,\n\t\t\t\ttoolBudget: effectiveToolBudget.toolBudget,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (shouldForkAgent(contextPolicy, params.agent!)) {\n\t\ttask = wrapForkTask(task);\n\t}\n\tconst cleanTask = task;\n\tconst outputPath = resolveSingleOutputPath(effectiveOutput, ctx.cwd, effectiveCwd, resolveSingleRunOutputBaseDir(deps, artifactsDir, runId));\n\tconst validationError = validateFileOnlyOutputMode(effectiveOutputMode, outputPath, `Single run (${params.agent})`);\n\tif (validationError) {\n\t\treturn { content: [{ type: \"text\", text: validationError }], isError: true, details: { mode: \"single\", results: [] } };\n\t}\n\ttask = injectSingleOutputInstruction(task, outputPath, agentConfig);\n\n\tlet effectiveSkills: string[] | undefined;\n\tif (skillOverride === false) {\n\t\teffectiveSkills = [];\n\t} else {\n\t\teffectiveSkills = skillOverride;\n\t}\n\tconst interruptController = new AbortController();\n\tconst foregroundControl = deps.state.foregroundControls.get(runId);\n\tif (foregroundControl) {\n\t\tforegroundControl.currentAgent = params.agent;\n\t\tforegroundControl.currentIndex = 0;\n\t\tforegroundControl.currentActivityState = undefined;\n\t\tforegroundControl.updatedAt = Date.now();\n\t\tforegroundControl.interrupt = () => {\n\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\tinterruptController.abort();\n\t\t\tforegroundControl.currentActivityState = undefined;\n\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\treturn true;\n\t\t};\n\t}\n\n\tconst forwardSingleUpdate = onUpdate\n\t\t? (update: AgentToolResult<Details>) => {\n\t\t\tif (foregroundControl) {\n\t\t\t\tconst firstProgress = update.details?.progress?.[0];\n\t\t\t\tforegroundControl.currentAgent = params.agent;\n\t\t\t\tforegroundControl.currentIndex = firstProgress?.index ?? 0;\n\t\t\t\tforegroundControl.currentActivityState = firstProgress?.activityState;\n\t\t\t\tforegroundControl.lastActivityAt = firstProgress?.lastActivityAt;\n\t\t\t\tforegroundControl.currentTool = firstProgress?.currentTool;\n\t\t\t\tforegroundControl.currentToolStartedAt = firstProgress?.currentToolStartedAt;\n\t\t\t\tforegroundControl.currentPath = firstProgress?.currentPath;\n\t\t\t\tforegroundControl.turnCount = firstProgress?.turnCount;\n\t\t\t\tforegroundControl.tokens = firstProgress?.tokens;\n\t\t\t\tforegroundControl.toolCount = firstProgress?.toolCount;\n\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t}\n\t\t\tonUpdate(update);\n\t\t}\n\t\t: undefined;\n\n\tconst deadlineAt = data.deadlineAt ?? (data.timeoutMs !== undefined ? Date.now() + data.timeoutMs : undefined);\n\tconst r = await runSync(ctx.cwd, agents, params.agent!, task, {\n\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\tcwd: effectiveCwd,\n\t\tsignal,\n\t\tinterruptSignal: interruptController.signal,\n\t\tallowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\tintercomEvents: deps.pi.events,\n\t\trunId,\n\t\tsessionDir: sessionDirForIndex(0),\n\t\tsessionFile: sessionFileForTask(params.agent!, 0, modelOverride),\n\t\tshare: shareEnabled,\n\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\tartifactConfig,\n\t\tmaxOutput: params.maxOutput,\n\t\toutputPath,\n\t\toutputMode: effectiveOutputMode,\n\t\tmaxSubagentDepth,\n\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\tonUpdate: forwardSingleUpdate,\n\t\tcontrolConfig,\n\t\tonControlEvent,\n\t\tintercomSessionName: childIntercomTarget,\n\t\torchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\tnestedRoute: foregroundControl?.nestedRoute,\n\t\tindex: 0,\n\t\tmodelOverride,\n\t\tthinkingOverride: thinkingOverrideForTask(params.agent!, 0, modelOverride),\n\t\tavailableModels,\n\t\tpreferredModelProvider: currentProvider,\n\t\tmodelScope: data.modelScope,\n\t\tskills: effectiveSkills,\n\t\tacceptance: params.acceptance,\n\t\tacceptanceContext: { mode: \"single\" },\n\t\tonDetachedExit: (result) => updateRememberedForegroundChild(deps.state, { runId, mode: \"single\", cwd: effectiveCwd, sessionId: data.parentSessionId, index: 0, result, events: deps.pi.events }),\n\t\ttimeoutMs: data.timeoutMs,\n\t\tdeadlineAt,\n\t\tturnBudget: data.turnBudget,\n\t\ttoolBudget: effectiveToolBudget.toolBudget,\n\t});\n\tif (foregroundControl?.currentIndex === 0) {\n\t\tforegroundControl.interrupt = undefined;\n\t\tforegroundControl.currentActivityState = r.progress?.activityState;\n\t\tforegroundControl.lastActivityAt = r.progress?.lastActivityAt;\n\t\tforegroundControl.currentTool = r.progress?.currentTool;\n\t\tforegroundControl.currentToolStartedAt = r.progress?.currentToolStartedAt;\n\t\tforegroundControl.currentPath = r.progress?.currentPath;\n\t\tforegroundControl.turnCount = r.progress?.turnCount;\n\t\tforegroundControl.tokens = r.progress?.tokens;\n\t\tforegroundControl.toolCount = r.progress?.toolCount;\n\t\tforegroundControl.updatedAt = Date.now();\n\t}\n\trecordRun(params.agent!, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);\n\n\tif (r.progress) allProgress.push(r.progress);\n\tif (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);\n\n\tconst fullOutput = getSingleResultOutput(r);\n\tconst finalizedOutput = finalizeSingleOutput({\n\t\tfullOutput,\n\t\ttruncatedOutput: r.truncation?.text,\n\t\toutputPath,\n\t\toutputMode: r.outputMode,\n\t\texitCode: r.exitCode,\n\t\tsavedPath: r.savedOutputPath,\n\t\toutputReference: r.outputReference,\n\t\tsaveError: r.outputSaveError,\n\t});\n\tif (foregroundControl) {\n\t\tupdateForegroundNestedProjection(foregroundControl);\n\t\tattachRootChildrenToSteps(runId, [r], foregroundControl.nestedChildren);\n\t}\n\tconst details = compactForegroundDetails({\n\t\tmode: \"single\",\n\t\trunId,\n\t\tresults: [r],\n\t\t...(data.turnBudget ? { turnBudget: data.turnBudget } : {}),\n\t\t...(effectiveToolBudget.toolBudget ? { toolBudget: effectiveToolBudget.toolBudget } : {}),\n\t\tprogress: params.includeProgress ? allProgress : undefined,\n\t\tartifacts: allArtifactPaths.length ? { dir: artifactsDir, files: allArtifactPaths } : undefined,\n\t\ttruncation: r.truncation,\n\t\ttotalChildUsage: sumResultsUsage([r]),\n\t\ttotalCost: sumResultsCost([r]),\n\t});\n\trememberForegroundRun(deps.state, { runId, mode: \"single\", cwd: effectiveCwd, sessionId: data.parentSessionId, results: details.results });\n\n\tif (!r.detached && !r.interrupted) {\n\t\tif (foregroundControl) updateForegroundNestedProjection(foregroundControl);\n\t\tconst intercomReceipt = await maybeBuildForegroundIntercomReceipt({\n\t\t\tpi: deps.pi,\n\t\t\tintercomBridge: data.intercomBridge,\n\t\t\trunId,\n\t\t\tmode: \"single\",\n\t\t\tdetails,\n\t\t\t...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),\n\t\t});\n\t\tif (intercomReceipt) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: intercomReceipt.text }],\n\t\t\t\tdetails: intercomReceipt.details,\n\t\t\t\t...(r.exitCode !== 0 ? { isError: true } : {}),\n\t\t\t};\n\t\t}\n\t}\n\n\tif (r.detached) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Detached for intercom coordination: ${params.agent}. Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\tdetails,\n\t\t};\n\t}\n\n\tif (r.interrupted) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run paused after interrupt (${params.agent}). Waiting for explicit next action.` }],\n\t\t\tdetails,\n\t\t};\n\t}\n\n\tif (r.exitCode !== 0)\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: formatFailedSingleRunOutput(r, finalizedOutput.displayOutput) }],\n\t\t\tdetails,\n\t\t\tisError: true,\n\t\t};\n\treturn {\n\t\tcontent: [{ type: \"text\", text: finalizedOutput.displayOutput || \"(no output)\" }],\n\t\tdetails,\n\t};\n}\n\nfunction inferExecutionMode(params: SubagentParamsLike): SubagentRunMode {\n\tif ((params.chain?.length ?? 0) > 0) return \"chain\";\n\tif ((params.tasks?.length ?? 0) > 0) return \"parallel\";\n\treturn \"single\";\n}\n\nfunction foregroundCapacityResult(params: SubagentParamsLike, inFlight: number, limit: number): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: `Foreground subagent capacity reached (${inFlight}/${limit} running). Wait for a child to finish, use ONE subagent call with tasks: [{agent, task}, …], or set async: true.`,\n\t\t}],\n\t\tisError: true,\n\t\tdetails: { mode: inferExecutionMode(params), results: [] },\n\t};\n}\n\nfunction omitExecutionModeActionAlias(params: SubagentParamsLike): SubagentParamsLike {\n\tconst action = params.action?.toLowerCase();\n\tif (action === \"single\" && (params.agent !== undefined || params.task !== undefined)) {\n\t\tconst rest = { ...params };\n\t\tdelete rest.action;\n\t\treturn rest;\n\t}\n\tif ((action === \"parallel\" || action === \"tasks\") && (params.tasks?.length ?? 0) > 0) {\n\t\tconst rest = { ...params };\n\t\tdelete rest.action;\n\t\treturn rest;\n\t}\n\treturn params;\n}\n\nexport function createSubagentExecutor(deps: ExecutorDeps): {\n\texecute: (\n\t\tid: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t) => Promise<AgentToolResult<Details>>;\n} {\n\tconst execute = async (\n\t\t_id: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t): Promise<AgentToolResult<Details>> => {\n\t\tdeps.state.baseCwd = ctx.cwd;\n\t\tdeps.state.foregroundRuns ??= new Map();\n\t\tdeps.state.foregroundControls ??= new Map();\n\t\tdeps.state.lastForegroundControlId ??= null;\n\t\tconst requestParams = omitExecutionModeActionAlias(params);\n\t\tconst requestCwd = resolveRequestedCwd(ctx.cwd, requestParams.cwd);\n\t\tconst paramsWithResolvedCwd = requestParams.cwd === undefined ? requestParams : { ...requestParams, cwd: requestCwd };\n\t\tconst action = paramsWithResolvedCwd.action;\n\t\tif (action) {\n\t\t\tif ((WATCHDOG_TOOL_ACTIONS as readonly string[]).includes(action)) {\n\t\t\t\tif (deps.allowMutatingManagementActions === false && MUTATING_MANAGEMENT_ACTIONS.has(action)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Action '${action}' is not available from child-safe subagent fanout mode.` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"management\" as const, results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn handleWatchdogToolAction(action, paramsWithResolvedCwd, ctx, deps.watchdog);\n\t\t\t}\n\t\t\tif (action === \"doctor\") {\n\t\t\t\tlet currentSessionFile: string | null = null;\n\t\t\t\tlet currentSessionId = deps.state.currentSessionId;\n\t\t\t\tlet sessionError: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tcurrentSessionFile = ctx.sessionManager.getSessionFile() ?? null;\n\t\t\t\t\tcurrentSessionId = ctx.sessionManager.getSessionId();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsessionError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n\t\t\t\t}\n\t\t\t\tlet orchestratorTarget: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\torchestratorTarget = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!sessionError) sessionError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: buildDoctorReport({\n\t\t\t\t\t\t\tcwd: requestCwd,\n\t\t\t\t\t\t\tconfig: deps.config,\n\t\t\t\t\t\t\tstate: deps.state,\n\t\t\t\t\t\t\tcontext: paramsWithResolvedCwd.context,\n\t\t\t\t\t\t\trequestedSessionDir: paramsWithResolvedCwd.sessionDir,\n\t\t\t\t\t\t\tcurrentSessionFile,\n\t\t\t\t\t\t\tcurrentSessionId,\n\t\t\t\t\t\t\torchestratorTarget,\n\t\t\t\t\t\t\tsessionError,\n\t\t\t\t\t\t\texpandTilde: deps.expandTilde,\n\t\t\t\t\t\t}),\n\t\t\t\t\t}],\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (action === \"status\") {\n\t\t\t\tdeps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;\n\t\t\t\tconst nestedScope = nestedResolutionScopeForExecutor(deps);\n\t\t\t\tconst sessionRoots = trustedSessionRootsForStatus(ctx, deps);\n\t\t\t\tif (paramsWithResolvedCwd.view === \"fleet\") {\n\t\t\t\t\treturn inspectSubagentStatus(paramsWithResolvedCwd, { state: deps.state, nested: nestedScope, sessionRoots });\n\t\t\t\t}\n\t\t\t\tif (targetRunId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst resolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedScope });\n\t\t\t\t\t\tif (resolved?.kind === \"foreground\") {\n\t\t\t\t\t\t\tconst foreground = getForegroundControl(deps.state, resolved.id);\n\t\t\t\t\t\t\tif (foreground) {\n\t\t\t\t\t\t\t\tif (paramsWithResolvedCwd.view === \"transcript\") {\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"Live foreground transcript is already visible in the expanded running subagent result. Persisted session transcript becomes inspectable after the foreground run completes when sessions are enabled.\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn foregroundStatusResult(foreground);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst foreground = getForegroundControl(deps.state, undefined);\n\t\t\t\t\tif (foreground && paramsWithResolvedCwd.view !== \"transcript\") return foregroundStatusResult(foreground);\n\t\t\t\t\tif (foreground && paramsWithResolvedCwd.view === \"transcript\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"Live foreground transcript is already visible in the expanded running subagent result. Pass an async run id to inspect a background transcript.\" }],\n\t\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn inspectSubagentStatus(paramsWithResolvedCwd, { state: deps.state, nested: nestedScope, sessionRoots });\n\t\t\t}\n\t\t\tif (action === \"resume\") {\n\t\t\t\treturn resumeAsyncRun({ params: paramsWithResolvedCwd, requestCwd, ctx, deps });\n\t\t\t}\n\t\t\tif (action === \"steer\") {\n\t\t\t\tdeps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);\n\t\t\t\tconst message = (paramsWithResolvedCwd.message ?? paramsWithResolvedCwd.task ?? \"\").trim();\n\t\t\t\tif (!message) return { content: [{ type: \"text\", text: \"action='steer' requires message.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;\n\t\t\t\tif (paramsWithResolvedCwd.dir) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst location = resolveAsyncRunLocation(paramsWithResolvedCwd, ASYNC_DIR, RESULTS_DIR);\n\t\t\t\t\t\tconst runId = location.resolvedId ?? targetRunId ?? path.basename(location.asyncDir ?? paramsWithResolvedCwd.dir);\n\t\t\t\t\t\treturn steerAsyncRun({ state: deps.state, runId, message, index: paramsWithResolvedCwd.index, kill: deps.kill, location, signal, recover: ({ absoluteDeadlineAt, ...limits }) => resumeAsyncRun({ params: { ...limits, action: \"resume\", id: runId, message }, requestCwd, ctx, deps, absoluteDeadlineAt }) });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!targetRunId) return { content: [{ type: \"text\", text: \"action='steer' requires id or dir.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tresolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn { content: [{ type: \"text\", text }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t}\n\t\t\t\tif (resolved?.kind === \"nested\") return steerNestedRun({ target: resolved, message, index: paramsWithResolvedCwd.index, signal });\n\t\t\t\tif (resolved?.kind === \"foreground\") return { content: [{ type: \"text\", text: \"action='steer' currently supports live async Pi child sessions only; use action='interrupt' or action='resume' for foreground runs.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tif (resolved?.kind !== \"async\") return { content: [{ type: \"text\", text: `No async run found for '${targetRunId}'.` }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\treturn steerAsyncRun({ state: deps.state, runId: resolved.id, message, index: paramsWithResolvedCwd.index, kill: deps.kill, location: resolved.location, signal, recover: ({ absoluteDeadlineAt, ...limits }) => resumeAsyncRun({ params: { ...limits, action: \"resume\", id: resolved!.id, message }, requestCwd, ctx, deps, absoluteDeadlineAt }) });\n\t\t\t}\n\t\t\tif (action === \"append-step\") {\n\t\t\t\treturn appendStepToAsyncChain({ params: paramsWithResolvedCwd, requestCwd, ctx, deps });\n\t\t\t}\n\t\t\tif (action === \"schedule\" || action === \"schedule-list\" || action === \"schedule-status\" || action === \"schedule-cancel\") {\n\t\t\t\tif (!deps.handleScheduledRunAction) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Action '${action}' is not available in this subagent context.` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn deps.handleScheduledRunAction(paramsWithResolvedCwd, ctx);\n\t\t\t}\n\t\t\tif (action === \"stop\") {\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;\n\t\t\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\t\t\tif (paramsWithResolvedCwd.dir) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst location = resolveAsyncRunLocation(paramsWithResolvedCwd, ASYNC_DIR, RESULTS_DIR);\n\t\t\t\t\t\treturn stopAsyncRun(deps.state, location.resolvedId ?? targetRunId ?? path.basename(location.asyncDir ?? paramsWithResolvedCwd.dir), deps.kill, location);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!targetRunId) return { content: [{ type: \"text\", text: \"action='stop' requires id or dir.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\ttry {\n\t\t\t\t\tresolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t}\n\t\t\t\tif (resolved?.kind === \"nested\") return { content: [{ type: \"text\", text: \"action='stop' supports current-session top-level async runs only.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tif (resolved?.kind === \"foreground\") return { content: [{ type: \"text\", text: \"action='stop' supports async runs only. Use action='interrupt' for foreground runs.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tconst stopResult = stopAsyncRun(\n\t\t\t\t\tdeps.state,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.id : targetRunId,\n\t\t\t\t\tdeps.kill,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.location : undefined,\n\t\t\t\t);\n\t\t\t\tif (stopResult) return stopResult;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"No stoppable async run found in this session.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (action === \"interrupt\") {\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;\n\t\t\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\t\t\tif (targetRunId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (resolved?.kind === \"nested\") return interruptNestedRun(resolved);\n\t\t\t\tconst foreground = getForegroundControl(deps.state, resolved?.kind === \"foreground\" ? resolved.id : targetRunId);\n\t\t\t\tif (foreground?.interrupt) {\n\t\t\t\t\tconst interrupted = foreground.interrupt();\n\t\t\t\t\tif (interrupted) {\n\t\t\t\t\t\tforeground.updatedAt = Date.now();\n\t\t\t\t\t\tforeground.currentActivityState = undefined;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Interrupt requested for foreground run ${foreground.runId}.` }],\n\t\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Foreground run ${foreground.runId} has no active child step to interrupt.` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst asyncInterruptResult = interruptAsyncRun(\n\t\t\t\t\tdeps.state,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.id : targetRunId,\n\t\t\t\t\tdeps.kill,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.location : undefined,\n\t\t\t\t);\n\t\t\t\tif (asyncInterruptResult) return asyncInterruptResult;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"No interrupt-capable run found in this session.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (!(SUBAGENT_ACTIONS as readonly string[]).includes(action)) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown action: ${action}. Valid: ${SUBAGENT_ACTIONS.join(\", \")}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (deps.allowMutatingManagementActions === false && MUTATING_MANAGEMENT_ACTIONS.has(action)) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Action '${action}' is not available from child-safe subagent fanout mode.` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn handleManagementAction(action, paramsWithResolvedCwd, {\n\t\t\t\t...ctx,\n\t\t\t\tcwd: requestCwd,\n\t\t\t\tconfig: deps.config,\n\t\t\t});\n\t\t}\n\n\t\tconst { blocked, depth, maxDepth } = checkSubagentDepth(deps.config.maxSubagentDepth);\n\t\tif (blocked) {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext:\n\t\t\t\t\t\t\t`Nested subagent call blocked (depth=${depth}, max=${maxDepth}). ` +\n\t\t\t\t\t\t\t\"You are running at the maximum subagent nesting depth. \" +\n\t\t\t\t\t\t\t\"Complete your current task directly without delegating to further subagents.\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t};\n\t\t}\n\n\t\tconst normalized = normalizeRepeatedParallelCounts(paramsWithResolvedCwd);\n\t\tif (normalized.error) return normalized.error;\n\t\tconst normalizedParams = normalized.params!;\n\n\t\tlet effectiveParams = applyForceTopLevelAsyncOverride(\n\t\t\tnormalizedParams,\n\t\t\tdepth,\n\t\t\tdeps.config.forceTopLevelAsync === true,\n\t\t);\n\t\tconst runToolBudget = resolveToolBudget(effectiveParams.toolBudget, \"toolBudget\");\n\t\tif (runToolBudget.error) return buildRequestedModeError(effectiveParams, runToolBudget.error);\n\t\tconst configToolBudget = resolveToolBudget(deps.config.toolBudget, \"config.toolBudget\");\n\t\tif (configToolBudget.error) return buildRequestedModeError(effectiveParams, configToolBudget.error);\n\n\t\tconst scope: AgentScope = resolveExecutionAgentScope(effectiveParams.agentScope);\n\t\tconst effectiveCwd = effectiveParams.cwd ?? ctx.cwd;\n\t\tconst parentSessionFile = ctx.sessionManager.getSessionFile() ?? null;\n\t\tdeps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);\n\t\tconst discovered = deps.discoverAgents(effectiveCwd, scope);\n\t\tconst discoveredAgents = discovered.agents;\n\t\tconst modelScope = discovered.modelScope;\n\t\teffectiveParams = applySingleAgentLaunchDefaults(effectiveParams, discoveredAgents);\n\t\tconst foregroundTimeout = resolveForegroundTimeout(effectiveParams);\n\t\tif (foregroundTimeout.error) return buildRequestedModeError(effectiveParams, foregroundTimeout.error);\n\t\tconst turnBudget = resolveTurnBudgetConfig(effectiveParams.turnBudget ?? deps.config.turnBudget);\n\t\tif (turnBudget.error) return buildRequestedModeError(effectiveParams, turnBudget.error);\n\t\tconst contextPolicy = resolveAgentDefaultContextPolicy(effectiveParams, discoveredAgents);\n\t\teffectiveParams = contextPolicy.params;\n\t\tconst sessionName = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());\n\t\tconst intercomBridge = resolveIntercomBridge({\n\t\t\tconfig: deps.config.intercomBridge,\n\t\t\tcontext: effectiveParams.context,\n\t\t\torchestratorTarget: sessionName,\n\t\t});\n\t\tconst agents = intercomBridge.active\n\t\t\t? discoveredAgents.map((agent) => applyIntercomBridgeToAgent(agent, intercomBridge))\n\t\t\t: discoveredAgents;\n\t\tconst runId = randomUUID().slice(0, 8);\n\t\tconst inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();\n\t\tconst nestedParentAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;\n\t\tconst nestedRoute = inheritedNestedRoute ?? createNestedRoute(runId);\n\t\tconst shareEnabled = effectiveParams.share === true;\n\t\tconst hasChain = (effectiveParams.chain?.length ?? 0) > 0;\n\t\tconst hasTasks = (effectiveParams.tasks?.length ?? 0) > 0;\n\t\tconst hasSingle = !hasChain && !hasTasks && Boolean(effectiveParams.agent);\n\t\tconst allowClarifyTaskPrompt = hasChain\n\t\t\t&& effectiveParams.clarify === true\n\t\t\t&& ctx.hasUI\n\t\t\t&& !(effectiveParams.chain?.some(isParallelStep) ?? false);\n\n\t\tconst validationError = validateExecutionInput(\n\t\t\teffectiveParams,\n\t\t\tagents,\n\t\t\thasChain,\n\t\t\thasTasks,\n\t\t\thasSingle,\n\t\t\tallowClarifyTaskPrompt,\n\t\t);\n\t\tif (validationError) return validationError;\n\n\t\tconst parentPermissionMode = snapshotParentPermissionMode(deps.state.currentSessionId);\n\t\tconst writeSpawnError = planModeWriteSpawnError(\n\t\t\tparentPermissionMode,\n\t\t\tcollectRequestedAgents(effectiveParams, agents),\n\t\t);\n\t\tif (writeSpawnError) return buildRequestedModeError(effectiveParams, writeSpawnError);\n\n\t\tlet forkSessionFileForIndex: (idx?: number) => string | undefined = () => undefined;\n\t\tlet forkThinkingOverrideForIndex: (idx?: number) => AgentConfig[\"thinking\"] | undefined = () => undefined;\n\t\tlet prepareForkThinking = (_agentName: string, _index: number, _modelOverride?: string): void => {};\n\t\tconst forkThinkingRequirements = new Map<number, boolean>();\n\t\tconst forkThinkingDowngrades = new Map<number, string>();\n\t\ttry {\n\t\t\tconst forkAvailableModels = contextPolicy.usesFork ? ctx.modelRegistry.getAvailable().map(toModelInfo) : [];\n\t\t\tprepareForkThinking = (agentName, index, modelOverride) => {\n\t\t\t\tconst agentConfig = agents.find((agent) => agent.name === agentName);\n\t\t\t\tconst primaryModel = resolveEffectiveSubagentModel(\n\t\t\t\t\tmodelOverride,\n\t\t\t\t\tagentConfig?.model,\n\t\t\t\t\tctx.model,\n\t\t\t\t\tforkAvailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t);\n\t\t\t\tconst candidates = buildModelCandidates(\n\t\t\t\t\tprimaryModel,\n\t\t\t\t\tagentConfig?.fallbackModels,\n\t\t\t\t\tforkAvailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t);\n\t\t\t\tforkThinkingRequirements.set(\n\t\t\t\t\tindex,\n\t\t\t\t\tcandidates.length === 0\n\t\t\t\t\t\t|| candidates.some((candidate) => forkedChildRequiresThinkingOff(candidate, forkAvailableModels, ctx.model?.provider)),\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst forkContextResolver = createForkContextResolver(ctx.sessionManager, contextPolicy.usesFork ? \"fork\" : undefined, {\n\t\t\t\tforceThinkingOffForIndex: (index) => forkThinkingRequirements.get(index) ?? true,\n\t\t\t});\n\t\t\tforkSessionFileForIndex = forkContextResolver.sessionFileForIndex;\n\t\t\tforkThinkingOverrideForIndex = forkContextResolver.thinkingOverrideForIndex;\n\t\t} catch (error) {\n\t\t\treturn toExecutionErrorResult(effectiveParams, error);\n\t\t}\n\t\tconst requestedAsync = effectiveParams.async ?? deps.asyncByDefault;\n\t\tconst backgroundRequestedWhileClarifying = (hasChain || hasTasks) && requestedAsync && effectiveParams.clarify === true;\n\t\tconst effectiveAsync = requestedAsync && effectiveParams.clarify !== true;\n\t\tconst controlConfig = resolveControlConfig(deps.config.control, effectiveParams.control);\n\n\t\tconst artifactConfig: ArtifactConfig = {\n\t\t\t...DEFAULT_ARTIFACT_CONFIG,\n\t\t\tenabled: effectiveParams.artifacts !== false,\n\t\t};\n\t\tconst artifactsDir = getArtifactsDir(parentSessionFile, effectiveCwd);\n\n\t\tlet sessionRoot: string;\n\t\tif (effectiveParams.sessionDir) {\n\t\t\tsessionRoot = path.resolve(deps.expandTilde(effectiveParams.sessionDir));\n\t\t} else {\n\t\t\tconst baseSessionRoot = deps.config.defaultSessionDir\n\t\t\t\t? path.resolve(deps.expandTilde(deps.config.defaultSessionDir))\n\t\t\t\t: deps.getSubagentSessionRoot(parentSessionFile);\n\t\t\tsessionRoot = path.join(baseSessionRoot, runId);\n\t\t}\n\t\ttry {\n\t\t\tfs.mkdirSync(sessionRoot, { recursive: true });\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\treturn toExecutionErrorResult(\n\t\t\t\teffectiveParams,\n\t\t\t\tnew Error(`Failed to create session directory '${sessionRoot}': ${message}`),\n\t\t\t);\n\t\t}\n\t\tconst sessionDirForIndex = (idx?: number) =>\n\t\t\tpath.join(sessionRoot, `run-${idx ?? 0}`);\n\t\tconst forkSessionFileForTask: ForkSessionFileForTask = (agentName, idx = 0, modelOverride) => {\n\t\t\tif (!shouldForkAgent(contextPolicy, agentName)) return undefined;\n\t\t\tprepareForkThinking(agentName, idx, modelOverride);\n\t\t\treturn forkSessionFileForIndex(idx);\n\t\t};\n\t\tconst forkThinkingOverrideForTask: ForkThinkingOverrideForTask = (agentName, idx = 0, modelOverride) => {\n\t\t\tif (!shouldForkAgent(contextPolicy, agentName)) return undefined;\n\t\t\tprepareForkThinking(agentName, idx, modelOverride);\n\t\t\tconst override = forkThinkingOverrideForIndex(idx);\n\t\t\tif (override === \"off\") forkThinkingDowngrades.set(idx, agentName);\n\t\t\treturn override;\n\t\t};\n\t\tconst childSessionFileForTask: ForkSessionFileForTask = (agentName, idx, modelOverride) =>\n\t\t\tforkSessionFileForTask(agentName, idx, modelOverride) ?? path.join(sessionDirForIndex(idx), \"session.jsonl\");\n\t\tconst childSessionFileForIndex = (idx?: number) =>\n\t\t\tpath.join(sessionDirForIndex(idx), \"session.jsonl\");\n\t\ttry {\n\t\t\tif (!(effectiveParams.clarify === true && ctx.hasUI)) {\n\t\t\t\tpreflightForkSessionsForStaticTasks(effectiveParams, contextPolicy, forkSessionFileForTask, deps.config.chain?.dynamicFanout?.maxItems);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn toExecutionErrorResult(effectiveParams, error);\n\t\t}\n\t\tconst chainBindingsError = validateExecutionChainBindings(effectiveParams, deps.config.chain?.dynamicFanout?.maxItems);\n\t\tif (chainBindingsError) return chainBindingsError;\n\n\t\tconst onUpdateWithContext = onUpdate\n\t\t\t? (r: AgentToolResult<Details>) => onUpdate(withForkContext(r, effectiveParams.context))\n\t\t\t: undefined;\n\n\t\tconst foregroundMode: \"single\" | \"parallel\" | \"chain\" = hasChain ? \"chain\" : hasTasks ? \"parallel\" : \"single\";\n\t\tconst spawnLimitError = reserveSubagentSpawns({\n\t\t\tstate: deps.state,\n\t\t\tconfig: deps.config,\n\t\t\tsessionId: deps.state.currentSessionId,\n\t\t\trequested: countRequestedSubagentSpawns(effectiveParams, deps.config),\n\t\t\tmode: foregroundMode,\n\t\t});\n\t\tif (spawnLimitError) return spawnLimitError;\n\n\t\tconst execData: ExecutionContextData = {\n\t\t\tparams: effectiveParams,\n\t\t\teffectiveCwd,\n\t\t\tctx,\n\t\t\tsignal,\n\t\t\tonUpdate: onUpdateWithContext,\n\t\t\tagents,\n\t\t\trunId,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tsessionDirForIndex,\n\t\t\tsessionFileForIndex: childSessionFileForIndex,\n\t\t\tsessionFileForTask: childSessionFileForTask,\n\t\t\tthinkingOverrideForTask: forkThinkingOverrideForTask,\n\t\t\tartifactConfig,\n\t\t\tartifactsDir,\n\t\t\tbackgroundRequestedWhileClarifying,\n\t\t\teffectiveAsync,\n\t\t\tcontrolConfig,\n\t\t\tintercomBridge,\n\t\t\tnestedRoute,\n\t\t\ttimeoutMs: foregroundTimeout.timeoutMs,\n\t\t\tturnBudget: turnBudget.turnBudget,\n\t\t\ttoolBudget: runToolBudget.toolBudget,\n\t\t\tconfigToolBudget: configToolBudget.toolBudget,\n\t\t\tcontextPolicy,\n\t\t\tmodelScope,\n\t\t\tparentSessionId: deps.state.currentSessionId,\n\t\t};\n\n\t\tconst foregroundControl = effectiveAsync\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\trunId,\n\t\t\t\tmode: foregroundMode,\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\tupdatedAt: Date.now(),\n\t\t\t\tcurrentAgent: undefined,\n\t\t\t\tcurrentIndex: undefined,\n\t\t\t\tcurrentActivityState: undefined,\n\t\t\t\tnestedRoute,\n\t\t\t\tinterrupt: undefined,\n\t\t\t};\n\t\tif (foregroundControl) {\n\t\t\tdeps.state.foregroundControls.set(runId, foregroundControl);\n\t\t\tdeps.state.lastForegroundControlId = runId;\n\t\t}\n\n\t\tconst writeNestedForegroundEvent = (type: \"subagent.nested.started\" | \"subagent.nested.completed\", result?: AgentToolResult<Details>): void => {\n\t\t\tif (!inheritedNestedRoute || !nestedParentAddress) return;\n\t\t\tconst now = Date.now();\n\t\t\tconst details = result?.details;\n\t\t\tconst state = type === \"subagent.nested.started\"\n\t\t\t\t? \"running\"\n\t\t\t\t: details?.results.some((child) => child.interrupted || child.detached)\n\t\t\t\t\t? \"paused\"\n\t\t\t\t\t: result?.isError || details?.results.some((child) => child.exitCode !== 0)\n\t\t\t\t\t\t? \"failed\"\n\t\t\t\t\t\t: \"complete\";\n\t\t\tconst errorText = result?.isError\n\t\t\t\t? result.content.find((item) => item.type === \"text\")?.text\n\t\t\t\t: undefined;\n\t\t\tconst agentsForSummary = hasTasks && effectiveParams.tasks\n\t\t\t\t? effectiveParams.tasks.map((task) => task.agent)\n\t\t\t\t: hasChain && effectiveParams.chain\n\t\t\t\t\t? effectiveParams.chain.flatMap((step) => isParallelStep(step) ? step.parallel.map((task) => task.agent) : [(step as SequentialStep).agent])\n\t\t\t\t\t: effectiveParams.agent ? [effectiveParams.agent] : [];\n\t\t\tconst leafIntercomTarget = intercomBridge.active && agentsForSummary[0]\n\t\t\t\t? resolveSubagentIntercomTarget(runId, agentsForSummary[0], 0)\n\t\t\t\t: undefined;\n\t\t\ttry {\n\t\t\t\twriteNestedEvent(inheritedNestedRoute, {\n\t\t\t\t\ttype,\n\t\t\t\t\tts: now,\n\t\t\t\t\tparentRunId: nestedParentAddress.parentRunId,\n\t\t\t\t\tparentStepIndex: nestedParentAddress.parentStepIndex,\n\t\t\t\t\tchild: {\n\t\t\t\t\t\tid: runId,\n\t\t\t\t\t\tparentRunId: nestedParentAddress.parentRunId,\n\t\t\t\t\t\tparentStepIndex: nestedParentAddress.parentStepIndex,\n\t\t\t\t\t\tdepth: nestedParentAddress.depth,\n\t\t\t\t\t\tpath: nestedParentAddress.path,\n\t\t\t\t\t\townerIntercomTarget: process.env.PI_SUBAGENT_INTERCOM_SESSION_NAME,\n\t\t\t\t\t\tleafIntercomTarget,\n\t\t\t\t\t\tintercomTarget: leafIntercomTarget,\n\t\t\t\t\t\townerState: state === \"running\" ? \"live\" : \"gone\",\n\t\t\t\t\t\tmode: foregroundMode,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\tagent: agentsForSummary[0],\n\t\t\t\t\t\tagents: agentsForSummary,\n\t\t\t\t\t\tstartedAt: foregroundControl?.startedAt ?? now,\n\t\t\t\t\t\t...(state !== \"running\" ? { endedAt: now } : {}),\n\t\t\t\t\t\tlastUpdate: now,\n\t\t\t\t\t\t...(details?.totalCost ? { totalCost: details.totalCost } : {}),\n\t\t\t\t\t\t...(errorText ? { error: errorText } : {}),\n\t\t\t\t\t\t...(details?.results.length ? { steps: details.results.map((child) => ({\n\t\t\t\t\t\t\tagent: child.agent,\n\t\t\t\t\t\t\tstatus: child.interrupted || child.detached ? \"paused\" : child.exitCode === 0 ? \"complete\" : \"failed\",\n\t\t\t\t\t\t\t...(child.sessionFile ? { sessionFile: child.sessionFile } : {}),\n\t\t\t\t\t\t\t...(child.error ? { error: child.error } : {}),\n\t\t\t\t\t\t})) } : {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to emit nested foreground status event:\", error);\n\t\t\t}\n\t\t};\n\n\t\tlet nestedForegroundStarted = false;\n\t\ttry {\n\t\t\tconst asyncResult = runAsyncPath(execData, deps);\n\t\t\tif (asyncResult) return withForkContext(withForkThinkingNotes(asyncResult, forkThinkingDowngrades), effectiveParams.context);\n\t\t\tif (foregroundControl) {\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.started\");\n\t\t\t\tnestedForegroundStarted = true;\n\t\t\t}\n\t\t\tif (hasChain && effectiveParams.chain) {\n\t\t\t\tconst result = await runChainPath(execData, deps);\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.completed\", result);\n\t\t\t\treturn withForkContext(withForkThinkingNotes(result, forkThinkingDowngrades), effectiveParams.context);\n\t\t\t}\n\t\t\tif (hasTasks && effectiveParams.tasks) {\n\t\t\t\tconst result = await runParallelPath(execData, deps);\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.completed\", result);\n\t\t\t\treturn withForkContext(withForkThinkingNotes(result, forkThinkingDowngrades), effectiveParams.context);\n\t\t\t}\n\t\t\tif (hasSingle) {\n\t\t\t\tconst result = await runSinglePath(execData, deps);\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.completed\", result);\n\t\t\t\treturn withForkContext(withForkThinkingNotes(result, forkThinkingDowngrades), effectiveParams.context);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorResult = withForkThinkingNotes(toExecutionErrorResult(effectiveParams, error), forkThinkingDowngrades);\n\t\t\tif (nestedForegroundStarted) writeNestedForegroundEvent(\"subagent.nested.completed\", errorResult);\n\t\t\treturn errorResult;\n\t\t} finally {\n\t\t\tif (foregroundControl) {\n\t\t\t\tclearPendingForegroundControlNotices(deps.state, runId);\n\t\t\t\tdeps.state.foregroundControls.delete(runId);\n\t\t\t\tif (deps.state.lastForegroundControlId === runId) {\n\t\t\t\t\tdeps.state.lastForegroundControlId = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn withForkContext({\n\t\t\tcontent: [{ type: \"text\", text: \"Invalid params\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t}, effectiveParams.context);\n\t};\n\n\tconst executeWithSingleDispatchGuard = async (\n\t\tid: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t): Promise<AgentToolResult<Details>> => {\n\t\tconst requestParams = omitExecutionModeActionAlias(params);\n\t\tif (requestParams.action) return execute(id, requestParams, signal, onUpdate, ctx);\n\t\tconst { depth } = checkSubagentDepth(deps.config.maxSubagentDepth);\n\t\tconst dispatchParams = applyForceTopLevelAsyncOverride(requestParams, depth, deps.config.forceTopLevelAsync === true);\n\t\tconst runsForeground = dispatchParams.clarify === true || (dispatchParams.async ?? deps.asyncByDefault) !== true;\n\t\tif (!runsForeground) return execute(id, requestParams, signal, onUpdate, ctx);\n\t\tconst limit = resolveTopLevelParallelConcurrency(undefined, deps.config.parallel?.concurrency);\n\t\tconst inFlight = deps.state.foregroundSubagentInFlight ?? 0;\n\t\tif (inFlight >= limit) return foregroundCapacityResult(requestParams, inFlight, limit);\n\t\tdeps.state.foregroundSubagentInFlight = inFlight + 1;\n\t\ttry {\n\t\t\treturn await execute(id, requestParams, signal, onUpdate, ctx);\n\t\t} finally {\n\t\t\tdeps.state.foregroundSubagentInFlight = Math.max(0, (deps.state.foregroundSubagentInFlight ?? 1) - 1);\n\t\t}\n\t};\n\n\treturn { execute: executeWithSingleDispatchGuard };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"subagent-executor.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAWtF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAKrE,OAAO,EASN,KAAK,SAAS,EAId,MAAM,0BAA0B,CAAC;AA8ClC,OAAO,EAGN,KAAK,eAAe,EAGpB,KAAK,aAAa,EAElB,KAAK,OAAO,EACZ,KAAK,eAAe,EAEpB,KAAK,eAAe,EAOpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAIrB,KAAK,aAAa,EAgBlB,MAAM,uBAAuB,CAAC;AAG/B,UAAU,SAAS;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IACpC,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,YAAY;IACrB,EAAE,EAAE,YAAY,CAAC;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wBAAwB,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IACpH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IACrE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;CAC7D;AA4lGD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG;IAC3D,OAAO,EAAE,CACR,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAC7D,GAAG,EAAE,gBAAgB,KACjB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;CACvC,CA+lBA","sourcesContent":["// @ts-nocheck\nimport { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr\";\nimport { snapshotParentPermissionMode } from \"../../../../../core/subagent-permission-inherit.ts\";\nimport { allocateChildId, normalizeChildSpec } from \"../../shared/child-spec.ts\";\nimport { getArtifactsDir, getProjectChainRunsDir } from \"../../shared/artifacts.ts\";\nimport { ChainClarifyComponent, type ChainClarifyResult } from \"./chain-clarify.ts\";\nimport { toModelInfo, type ModelInfo } from \"../../shared/model-info.ts\";\nimport { executeChain } from \"./chain-execution.ts\";\nimport { buildDoctorReport } from \"../../extension/doctor.ts\";\nimport { clearPendingForegroundControlNotices } from \"../../extension/control-notices.ts\";\nimport { runSync } from \"./execution.ts\";\nimport { handleWatchdogToolAction, WATCHDOG_TOOL_ACTIONS } from \"../../watchdog/tool-actions.ts\";\nimport type { MainWatchdogRuntime } from \"../../watchdog/runtime.ts\";\nimport { buildModelCandidates, resolveEffectiveSubagentModel, resolveModelCandidate, resolveTierModelOverride } from \"../shared/model-fallback.ts\";\nimport type { ModelScopeConfig } from \"../shared/model-scope.ts\";\nimport { aggregateParallelOutputs } from \"../shared/parallel-utils.ts\";\nimport { recordRun } from \"../shared/run-history.ts\";\nimport {\n\tbuildChainInstructions,\n\twriteInitialProgressFile,\n\tgetStepAgents,\n\tisParallelStep,\n\tisDynamicParallelStep,\n\tresolveStepBehavior,\n\tsuppressProgressForReadOnlyTask,\n\ttaskDisallowsFileUpdates,\n\ttype ChainStep,\n\ttype ResolvedStepBehavior,\n\ttype SequentialStep,\n\ttype StepOverrides,\n} from \"../../shared/settings.ts\";\nimport { discoverAvailableSkills, normalizeSkillInput } from \"../../agents/skills.ts\";\nimport { buildAsyncRunnerSteps, executeAsyncChain, executeAsyncSingle, formatAsyncStartedMessage, isAsyncAvailable } from \"../background/async-execution.ts\";\nimport type { ScheduledRunAction } from \"../background/scheduled-runs.ts\";\nimport { enqueueChainAppendRequest, readPendingChainAppendRequests, runnerStepOutputNames } from \"../background/chain-append.ts\";\nimport { ChainOutputValidationError, validateChainOutputBindingsWithContext } from \"../shared/chain-outputs.ts\";\nimport { validateExecutionAcceptance } from \"../shared/acceptance.ts\";\nimport { createForkContextResolver, forkedChildRequiresThinkingOff } from \"../../shared/fork-context.ts\";\nimport { lunrContextPolicy } from \"../../shared/lunr-child-context.ts\";\nimport { resolveCurrentSessionId } from \"../../shared/session-identity.ts\";\nimport { applyIntercomBridgeToAgent, INTERCOM_BRIDGE_MARKER, resolveIntercomBridge, resolveIntercomSessionTarget, resolveSubagentIntercomTarget, type IntercomBridgeState } from \"../../intercom/intercom-bridge.ts\";\nimport { formatControlIntercomMessage, formatControlNoticeMessage, resolveControlConfig, shouldNotifyControlEvent } from \"../shared/subagent-control.ts\";\nimport { resolveTurnBudgetConfig } from \"../shared/turn-budget.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\nimport { finalizeSingleOutput, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from \"../shared/single-output.ts\";\nimport { compactForegroundDetails, getSingleResultOutput, mapConcurrent, readStatus, resolveChildCwd, sumResultsCost, sumResultsUsage } from \"../../shared/utils.ts\";\nimport { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from \"../shared/parallel-utils.ts\";\nimport {\n\tattachNestedChildrenToResultChildren,\n\tbuildSubagentResultIntercomPayload,\n\tdeliverSubagentIntercomMessageEvent,\n\tdeliverSubagentResultIntercomEvent,\n\tformatSubagentResultReceipt,\n\tresolveSubagentResultStatus,\n\tstripDetailsOutputsForIntercomReceipt,\n} from \"../../intercom/result-intercom.ts\";\nimport { buildRevivedAsyncTask, interruptLiveAsyncResumeTarget, resolveAsyncResumeTarget, resolveAsyncRunLocation } from \"../background/async-resume.ts\";\nimport { deliverInterruptRequest, deliverStopRequest, requestAsyncSteer } from \"../background/control-channel.ts\";\nimport { waitForSteeringAction } from \"../background/steering.ts\";\nimport { steerAsyncRun } from \"./async-steering-action.ts\";\nimport { reconcileAsyncRun } from \"../background/stale-run-reconciler.ts\";\nimport { resolveAsyncRootResultPath } from \"../background/chain-root-attachment.ts\";\nimport { attachRootChildrenToSteps, createNestedRoute, readNestedControlResults, resolveInheritedNestedRouteFromEnv, resolveNestedAsyncDir, resolveNestedParentAddressFromEnv, updateForegroundNestedProjection, writeNestedControlRequest, writeNestedEvent, type NestedRunResolutionScope } from \"../shared/nested-events.ts\";\nimport { resolveSubagentRunId, type ResolvedSubagentRunId } from \"../background/run-id-resolver.ts\";\nimport { formatNestedRunStatusLines } from \"../shared/nested-render.ts\";\nimport { inspectSubagentStatus } from \"../background/run-status.ts\";\nimport { applyForceTopLevelAsyncOverride } from \"../background/top-level-async.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport {\n\ttype AgentProgress,\n\ttype AsyncStatus,\n\ttype AcceptanceInput,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype ControlConfig,\n\ttype ControlEvent,\n\ttype Details,\n\ttype ExtensionConfig,\n\ttype IntercomEventBus,\n\ttype MaxOutputConfig,\n\ttype NestedRouteInfo,\n\ttype NestedRunSummary,\n\ttype ResolvedControlConfig,\n\ttype ResolvedTurnBudget,\n\ttype ResolvedToolBudget,\n\ttype SingleResult,\n\ttype ToolBudgetConfig,\n\ttype TurnBudgetConfig,\n\ttype ChildSpec,\n\ttype ChildRuntimeConfig,\n\ttype SubagentRunMode,\n\ttype SubagentState,\n\tASYNC_DIR,\n\tDEFAULT_ARTIFACT_CONFIG,\n\tDEFAULT_FORK_PREAMBLE,\n\tRESULTS_DIR,\n\tSUBAGENT_ACTIONS,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tcheckSubagentDepth,\n\tresolveMaxSubagentSpawnsPerSession,\n\tresolveTopLevelParallelConcurrency,\n\tresolveTopLevelParallelMaxTasks,\n\tresolveChildMaxSubagentDepth,\n\tresolveCurrentMaxSubagentDepth,\n\twrapForkTask,\n} from \"../../shared/types.ts\";\n\nconst MUTATING_MANAGEMENT_ACTIONS = new Set([\"create\", \"update\", \"delete\", \"eject\", \"disable\", \"enable\", \"reset\", \"watchdog.configure\"]);\ninterface TaskParam {\n\tagent?: string;\n\ttask: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\tcwd?: string;\n\tcount?: number;\n\toutput?: string | boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\treads?: string[] | boolean;\n\tprogress?: boolean;\n\tmodel?: string;\n\tskill?: string | string[] | boolean;\n\tacceptance?: AcceptanceInput;\n\ttoolBudget?: ToolBudgetConfig;\n}\n\nexport interface SubagentParamsLike {\n\taction?: string;\n\tid?: string;\n\trunId?: string;\n\tdir?: string;\n\tindex?: number;\n\tview?: \"fleet\" | \"transcript\";\n\tlines?: number;\n\tagent?: string;\n\ttask?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\tmessage?: string;\n\tchain?: ChainStep[];\n\ttasks?: TaskParam[];\n\tconcurrency?: number;\n\tworktree?: boolean;\n\tcontext?: \"fresh\" | \"fork\";\n\tasync?: boolean;\n\tforegroundOnly?: boolean;\n\ttimeoutMs?: number;\n\tmaxRuntimeMs?: number;\n\tturnBudget?: TurnBudgetConfig;\n\ttoolBudget?: ToolBudgetConfig;\n\tclarify?: boolean;\n\tshare?: boolean;\n\tcontrol?: ControlConfig;\n\tsessionDir?: string;\n\tcwd?: string;\n\tmaxOutput?: MaxOutputConfig;\n\tartifacts?: boolean;\n\tincludeProgress?: boolean;\n\tmodel?: string;\n\ttier?: \"light\" | \"standard\" | \"heavy\";\n\tthinking?: string | false;\n\tscope?: string;\n\ttarget?: string;\n\tskill?: string | string[] | boolean;\n\toutput?: string | boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\tchainDir?: string;\n\tacceptance?: AcceptanceInput;\n\tschedule?: string;\n\tscheduleName?: string;\n}\n\ninterface ExecutorDeps {\n\tpi: ExtensionAPI;\n\tstate: SubagentState;\n\tconfig: ExtensionConfig;\n\tasyncByDefault: boolean;\n\twaitToolEnabled?: boolean;\n\thandleScheduledRunAction?: (params: SubagentParamsLike, ctx: ExtensionContext) => Promise<AgentToolResult<Details>>;\n\twatchdog?: MainWatchdogRuntime;\n\ttempArtifactsDir: string;\n\tgetSubagentSessionRoot: (parentSessionFile: string | null) => string;\n\texpandTilde: (p: string) => string;\n\tallowMutatingManagementActions?: boolean;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n}\n\ntype ForkSessionFileForTask = (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\ntype ForkThinkingOverrideForTask = (agentName: string, idx?: number, modelOverride?: string) => ChildRuntimeConfig[\"thinking\"] | undefined;\n\ninterface ExecutionContextData {\n\tparams: SubagentParamsLike;\n\teffectiveCwd: string;\n\tctx: ExtensionContext;\n\tsignal: AbortSignal;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tagents: ChildRuntimeConfig[];\n\trunId: string;\n\tshareEnabled: boolean;\n\tsessionRoot: string;\n\tsessionDirForIndex: (idx?: number) => string;\n\tsessionFileForIndex: (idx?: number) => string | undefined;\n\tsessionFileForTask: ForkSessionFileForTask;\n\tthinkingOverrideForTask: ForkThinkingOverrideForTask;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\tbackgroundRequestedWhileClarifying: boolean;\n\teffectiveAsync: boolean;\n\tcontrolConfig: ResolvedControlConfig;\n\tintercomBridge: IntercomBridgeState;\n\tnestedRoute?: NestedRouteInfo;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ResolvedToolBudget;\n\tcontextPolicy: AgentDefaultContextPolicy;\n\tmodelScope?: ModelScopeConfig;\n\tparentSessionId: string | null;\n}\n\nfunction resolveRequestedCwd(runtimeCwd: string, requestedCwd: string | undefined): string {\n\treturn requestedCwd ? path.resolve(runtimeCwd, requestedCwd) : runtimeCwd;\n}\n\nfunction getForegroundControl(state: SubagentState, runId: string | undefined) {\n\tif (runId) return state.foregroundControls.get(runId);\n\tif (state.lastForegroundControlId) {\n\t\tconst latest = state.foregroundControls.get(state.lastForegroundControlId);\n\t\tif (latest) return latest;\n\t}\n\tlet newest: (SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never) | undefined;\n\tfor (const control of state.foregroundControls.values()) {\n\t\tif (!newest || control.updatedAt > newest.updatedAt) newest = control;\n\t}\n\treturn newest;\n}\n\nfunction formatForegroundActivity(control: SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never): string | undefined {\n\tconst facts: string[] = [];\n\tif (control.currentTool && control.currentToolStartedAt) facts.push(`tool ${control.currentTool} for ${Math.floor(Math.max(0, Date.now() - control.currentToolStartedAt) / 1000)}s`);\n\telse if (control.currentTool) facts.push(`tool ${control.currentTool}`);\n\tif (control.currentPath) facts.push(`path ${control.currentPath}`);\n\tif (control.turnCount !== undefined) facts.push(`${control.turnCount} turns`);\n\tif (control.tokens !== undefined) facts.push(`${control.tokens} tokens`);\n\tif (control.toolCount !== undefined) facts.push(`${control.toolCount} tools`);\n\tif (!control.lastActivityAt) {\n\t\tif (control.currentActivityState === \"needs_attention\") return [\"needs attention\", ...facts].join(\" | \");\n\t\tif (control.currentActivityState === \"active_long_running\") return [\"active but long-running\", ...facts].join(\" | \");\n\t\treturn facts.length ? facts.join(\" | \") : undefined;\n\t}\n\tconst seconds = Math.floor(Math.max(0, Date.now() - control.lastActivityAt) / 1000);\n\tif (control.currentActivityState === \"needs_attention\") return [`no activity for ${seconds}s`, ...facts].join(\" | \");\n\tif (control.currentActivityState === \"active_long_running\") return [`active but long-running; last activity ${seconds}s ago`, ...facts].join(\" | \");\n\treturn [`active ${seconds}s ago`, ...facts].join(\" | \");\n}\n\nfunction nestedResolutionScopeForExecutor(deps: ExecutorDeps): NestedRunResolutionScope | undefined {\n\tif (deps.allowMutatingManagementActions !== false) return undefined;\n\tconst route = resolveInheritedNestedRouteFromEnv();\n\tconst address = route ? resolveNestedParentAddressFromEnv() : undefined;\n\treturn {\n\t\troutes: route ? [route] : [],\n\t\t...(address ? { descendantOf: { parentRunId: address.parentRunId, ...(address.parentStepIndex !== undefined ? { parentStepIndex: address.parentStepIndex } : {}) } } : {}),\n\t};\n}\n\nfunction trustedSessionRootsForStatus(ctx: ExtensionContext, deps: ExecutorDeps): string[] {\n\tconst roots = deps.config.defaultSessionDir ? [path.resolve(deps.expandTilde(deps.config.defaultSessionDir))] : [];\n\tconst parentSessionFile = ctx.sessionManager.getSessionFile() ?? null;\n\tif (parentSessionFile) roots.push(deps.getSubagentSessionRoot(parentSessionFile));\n\treturn [...new Set(roots)];\n}\n\nfunction reserveSubagentSpawns(input: { state: SubagentState; config: ExtensionConfig; sessionId: string | null; requested: number; mode: \"single\" | \"parallel\" | \"chain\" }): AgentToolResult<Details> | undefined {\n\tif (input.requested <= 0) return undefined;\n\tconst maxSpawns = resolveMaxSubagentSpawnsPerSession(input.config.maxSubagentSpawnsPerSession);\n\tif (maxSpawns === undefined) return undefined;\n\tif (input.state.subagentSpawns?.sessionId !== input.sessionId) {\n\t\tinput.state.subagentSpawns = { sessionId: input.sessionId, count: 0 };\n\t}\n\tconst used = input.state.subagentSpawns.count;\n\tif (used + input.requested > maxSpawns) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Subagent spawn limit reached for this session (${used}/${maxSpawns} used, ${input.requested} requested). Complete the work directly or start a new session.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: input.mode, results: [] },\n\t\t};\n\t}\n\tinput.state.subagentSpawns.count = used + input.requested;\n\treturn undefined;\n}\n\nfunction countRequestedSubagentSpawns(params: SubagentParamsLike, config: ExtensionConfig): number {\n\tif (params.tasks) return params.tasks.length;\n\tif (params.chain) {\n\t\treturn params.chain.reduce((total, step) => {\n\t\t\tif (isDynamicParallelStep(step)) return total + (step.expand.maxItems ?? config.chain?.dynamicFanout?.maxItems ?? 0);\n\t\t\treturn total + getStepAgents(step).length;\n\t\t}, 0);\n\t}\n\treturn params.agent ? 1 : 0;\n}\n\nfunction foregroundStatusResult(control: SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never): AgentToolResult<Details> {\n\tlet nestedWarning: string | undefined;\n\ttry {\n\t\tupdateForegroundNestedProjection(control);\n\t} catch (error) {\n\t\tnestedWarning = `Nested status unavailable: ${error instanceof Error ? error.message : String(error)}`;\n\t}\n\tconst activity = formatForegroundActivity(control);\n\tconst lines = [\n\t\t`Run: ${control.runId}`,\n\t\t\"State: running\",\n\t\t`Mode: ${control.mode}`,\n\t\tcontrol.currentAgent ? `Current: ${control.currentAgent}${control.currentIndex !== undefined ? ` step ${control.currentIndex + 1}` : \"\"}` : undefined,\n\t\tactivity ? `Activity: ${activity}` : undefined,\n\t].filter((line): line is string => Boolean(line));\n\tlines.push(...formatNestedRunStatusLines(control.nestedChildren, { indent: \"\", commandHints: true, maxLines: 20 }));\n\tif (nestedWarning) lines.push(`Warning: ${nestedWarning}`);\n\treturn { content: [{ type: \"text\", text: lines.join(\"\\n\") }], details: { mode: \"management\", results: [] } };\n}\n\nfunction trimRememberedForegroundRuns(state: SubagentState): void {\n\tif (!state.foregroundRuns) return;\n\twhile (state.foregroundRuns.size > 50) {\n\t\tconst oldestTerminal = [...state.foregroundRuns.values()]\n\t\t\t.filter((run) => !run.children.some((child) => child.status === \"detached\"))\n\t\t\t.sort((left, right) => left.updatedAt - right.updatedAt)[0];\n\t\tif (!oldestTerminal) break;\n\t\tstate.foregroundRuns.delete(oldestTerminal.runId);\n\t}\n}\n\nfunction rememberForegroundRun(state: SubagentState, input: { runId: string; mode: \"single\" | \"parallel\" | \"chain\"; cwd: string; sessionId: string | null; results: SingleResult[] }): void {\n\tstate.foregroundRuns ??= new Map();\n\tconst previous = state.foregroundRuns.get(input.runId);\n\tconst updatedAt = Date.now();\n\tstate.foregroundRuns.set(input.runId, {\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tcwd: input.cwd,\n\t\t...(input.sessionId ? { sessionId: input.sessionId } : {}),\n\t\tupdatedAt,\n\t\tchildren: input.results.map((result, index) => {\n\t\t\tconst child = {\n\t\t\t\tagent: result.agent,\n\t\t\t\tindex,\n\t\t\t\tstatus: resolveSubagentResultStatus({ exitCode: result.exitCode, interrupted: result.interrupted, detached: result.detached }),\n\t\t\t\tupdatedAt,\n\t\t\t\t...(result.exitCode !== undefined ? { exitCode: result.exitCode } : {}),\n\t\t\t\t...(result.error ? { error: result.error } : {}),\n\t\t\t\t...(result.finalOutput ? { finalOutput: result.finalOutput } : {}),\n\t\t\t\t...(result.outputMode ? { outputMode: result.outputMode } : {}),\n\t\t\t\t...(result.savedOutputPath ? { savedOutputPath: result.savedOutputPath } : {}),\n\t\t\t\t...(result.outputSaveError ? { outputSaveError: result.outputSaveError } : {}),\n\t\t\t\t...(result.sessionFile ? { sessionFile: result.sessionFile } : {}),\n\t\t\t\t...(result.artifactPaths ? { artifactPaths: result.artifactPaths } : {}),\n\t\t\t\t...(result.transcriptPath ? { transcriptPath: result.transcriptPath } : {}),\n\t\t\t\t...(result.transcriptError ? { transcriptError: result.transcriptError } : {}),\n\t\t\t\t...(result.detachedReason ? { detachedReason: result.detachedReason } : {}),\n\t\t\t\t...(result.acceptance ? { acceptance: result.acceptance } : {}),\n\t\t\t};\n\t\t\tconst recovered = previous?.children[index];\n\t\t\treturn child.status === \"detached\" && recovered && recovered.status !== \"detached\" ? recovered : child;\n\t\t}),\n\t});\n\ttrimRememberedForegroundRuns(state);\n}\n\nfunction updateRememberedForegroundChild(state: SubagentState, input: { runId: string; mode: \"single\" | \"parallel\" | \"chain\"; cwd: string; sessionId: string | null; index: number; result: SingleResult; events: IntercomEventBus }): void {\n\tstate.foregroundRuns ??= new Map();\n\tconst updatedAt = Date.now();\n\tlet run = state.foregroundRuns.get(input.runId);\n\tif (!run) {\n\t\trun = { runId: input.runId, mode: input.mode, cwd: input.cwd, ...(input.sessionId ? { sessionId: input.sessionId } : {}), updatedAt, children: [] };\n\t\tstate.foregroundRuns.set(input.runId, run);\n\t}\n\trun.updatedAt = updatedAt;\n\tconst child = run.children[input.index] ?? { agent: input.result.agent, index: input.index, status: \"detached\" as const };\n\trun.children[input.index] = {\n\t\t...child,\n\t\tagent: input.result.agent,\n\t\tindex: input.index,\n\t\tstatus: input.result.acceptance?.status === \"rejected\"\n\t\t\t? \"failed\"\n\t\t\t: resolveSubagentResultStatus({ exitCode: input.result.exitCode, interrupted: input.result.interrupted, detached: false }),\n\t\tupdatedAt,\n\t\t...(input.result.exitCode !== undefined ? { exitCode: input.result.exitCode } : {}),\n\t\t...(input.result.error ? { error: input.result.error } : {}),\n\t\t...(input.result.finalOutput ? { finalOutput: input.result.finalOutput } : {}),\n\t\toutputMode: input.result.outputMode,\n\t\tsavedOutputPath: input.result.savedOutputPath,\n\t\toutputSaveError: input.result.outputSaveError,\n\t\t...(input.result.sessionFile ? { sessionFile: input.result.sessionFile } : {}),\n\t\t...(input.result.artifactPaths ? { artifactPaths: input.result.artifactPaths } : {}),\n\t\t...(input.result.transcriptPath ? { transcriptPath: input.result.transcriptPath } : {}),\n\t\t...(input.result.transcriptError ? { transcriptError: input.result.transcriptError } : {}),\n\t\t...(input.result.detachedReason ? { detachedReason: input.result.detachedReason } : {}),\n\t\t...(input.result.acceptance ? { acceptance: input.result.acceptance } : {}),\n\t};\n\ttrimRememberedForegroundRuns(state);\n\tconst output = getSingleResultOutput(input.result).trim();\n\tconst success = input.result.exitCode === 0 && input.result.acceptance?.status !== \"rejected\";\n\tconst summary = !success && input.result.error\n\t\t? `${input.result.error}${output ? `\\n\\nOutput:\\n${output}` : \"\"}`\n\t\t: output || input.result.error || \"Detached child exited without final output.\";\n\tinput.events.emit(SUBAGENT_FOREGROUND_COMPLETE_EVENT, {\n\t\tid: `${input.runId}:${input.index}`,\n\t\trunId: input.runId,\n\t\tsource: \"foreground\",\n\t\tmode: input.mode,\n\t\tagent: input.result.agent,\n\t\tsuccess,\n\t\tsummary,\n\t\texitCode: input.result.exitCode,\n\t\tstate: success ? \"complete\" : \"failed\",\n\t\ttimestamp: updatedAt,\n\t\tcwd: input.cwd,\n\t\tsessionFile: input.result.sessionFile,\n\t\tsessionId: input.sessionId,\n\t\ttaskIndex: input.index,\n\t});\n}\n\nfunction resolveForegroundResumeTarget(params: SubagentParamsLike, state: SubagentState): { runId: string; mode: \"single\" | \"parallel\" | \"chain\"; state: \"complete\"; agent: string; index: number; intercomTarget: string; cwd: string; sessionFile: string } | undefined {\n\tconst requested = (params.id ?? params.runId)?.trim();\n\tif (!requested || !state.foregroundRuns?.size || !state.currentSessionId) return undefined;\n\tconst sessionRuns = [...state.foregroundRuns.values()].filter((run) => run.sessionId === state.currentSessionId);\n\tconst direct = sessionRuns.find((run) => run.runId === requested);\n\tconst matches = direct ? [direct] : sessionRuns.filter((run) => run.runId.startsWith(requested));\n\tif (matches.length === 0) return undefined;\n\tif (matches.length > 1) throw new Error(`Ambiguous foreground run id prefix '${requested}' matched: ${matches.map((run) => run.runId).join(\", \")}. Provide a longer id.`);\n\tconst run = matches[0]!;\n\tif (run.children.some((child) => child.status === \"detached\")) throw new Error(`Foreground run '${run.runId}' is detached for intercom coordination and cannot be revived safely while any child may still be live. Reply to the supervisor request first, then wait with subagent_wait({ id: \"${run.runId}\" }); use status to recover the result and do not launch a replacement while it remains detached.`);\n\tif (run.children.length > 1 && params.index === undefined) throw new Error(`Foreground run '${run.runId}' has ${run.children.length} children. Provide index to choose one.`);\n\tconst index = params.index ?? 0;\n\tif (!Number.isInteger(index)) throw new Error(`Foreground run '${run.runId}' index must be an integer.`);\n\tif (index < 0 || index >= run.children.length) throw new Error(`Foreground run '${run.runId}' has ${run.children.length} children. Index ${index} is out of range.`);\n\tconst child = run.children[index]!;\n\tif (!child.sessionFile) throw new Error(`Foreground run '${run.runId}' child ${index} does not have a persisted session file to resume from.`);\n\tif (path.extname(child.sessionFile) !== \".jsonl\") throw new Error(`Foreground run '${run.runId}' child ${index} session file must be a .jsonl file: ${child.sessionFile}`);\n\tconst sessionFile = path.resolve(child.sessionFile);\n\tif (!fs.existsSync(sessionFile)) throw new Error(`Foreground run '${run.runId}' child ${index} session file does not exist: ${child.sessionFile}`);\n\treturn { runId: run.runId, mode: run.mode, state: \"complete\", agent: child.agent, index, intercomTarget: resolveSubagentIntercomTarget(run.runId, child.agent, index), cwd: run.cwd, sessionFile };\n}\n\ntype AsyncResumeSourceTarget = ReturnType<typeof resolveAsyncResumeTarget> & { source: \"async\" };\ntype ForegroundResumeSourceTarget = NonNullable<ReturnType<typeof resolveForegroundResumeTarget>> & { kind: \"revive\"; source: \"foreground\" };\ntype NestedResumeSourceTarget = {\n\tkind: \"revive\";\n\tsource: \"nested\";\n\trunId: string;\n\tstate: \"complete\" | \"failed\" | \"paused\" | \"stopped\";\n\tagent: string;\n\tindex: number;\n\tintercomTarget: string;\n\tcwd?: string;\n\tsessionFile: string;\n};\ntype ResumeSourceTarget = AsyncResumeSourceTarget | ForegroundResumeSourceTarget | NestedResumeSourceTarget;\n\nfunction isAsyncRunNotFound(error: unknown): boolean {\n\treturn error instanceof Error && error.message.startsWith(\"Async run not found.\");\n}\n\nfunction isResumeAmbiguity(error: unknown): boolean {\n\treturn error instanceof Error && /Ambiguous .*run id prefix/.test(error.message);\n}\n\nfunction resumeTargetExact(target: { runId: string } | undefined, requested: string): boolean {\n\treturn target?.runId === requested;\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction isExactResumeError(error: unknown, source: \"async\" | \"foreground\", requested: string): boolean {\n\tif (!(error instanceof Error) || !requested) return false;\n\treturn new RegExp(`\\\\b${source} run '${escapeRegExp(requested)}'`, \"i\").test(error.message);\n}\n\nfunction resolveResumeTarget(params: SubagentParamsLike, state: SubagentState, options: { asyncRequireSessionFile?: boolean } = {}): ResumeSourceTarget {\n\tconst requested = (params.id ?? params.runId)?.trim() ?? \"\";\n\tlet foregroundTarget: ForegroundResumeSourceTarget | undefined;\n\tlet foregroundError: unknown;\n\tlet asyncTarget: AsyncResumeSourceTarget | undefined;\n\tlet asyncError: unknown;\n\n\ttry {\n\t\tconst target = resolveForegroundResumeTarget(params, state);\n\t\tif (target) foregroundTarget = { kind: \"revive\", source: \"foreground\", ...target };\n\t} catch (error) {\n\t\tforegroundError = error;\n\t}\n\ttry {\n\t\tasyncTarget = { source: \"async\", ...resolveAsyncResumeTarget(params, {}, { requireSessionFile: options.asyncRequireSessionFile }) };\n\t} catch (error) {\n\t\tasyncError = error;\n\t}\n\n\tif (foregroundTarget && asyncTarget) {\n\t\tconst foregroundExact = resumeTargetExact(foregroundTarget, requested);\n\t\tconst asyncExact = resumeTargetExact(asyncTarget, requested);\n\t\tif (foregroundExact && !asyncExact) return foregroundTarget;\n\t\tif (asyncExact && !foregroundExact) return asyncTarget;\n\t\tthrow new Error(`Resume id '${requested}' is ambiguous between foreground run '${foregroundTarget.runId}' and async run '${asyncTarget.runId}'. Provide a full run id.`);\n\t}\n\tif (foregroundTarget) {\n\t\tif (isExactResumeError(asyncError, \"async\", requested)) throw asyncError;\n\t\tif (isResumeAmbiguity(asyncError) && !resumeTargetExact(foregroundTarget, requested)) throw asyncError;\n\t\treturn foregroundTarget;\n\t}\n\tif (asyncTarget) {\n\t\tif (isExactResumeError(foregroundError, \"foreground\", requested)) throw foregroundError;\n\t\tif (isResumeAmbiguity(foregroundError) && !resumeTargetExact(asyncTarget, requested)) throw foregroundError;\n\t\treturn asyncTarget;\n\t}\n\tif (foregroundError && !isAsyncRunNotFound(asyncError)) throw foregroundError;\n\tif (foregroundError) throw foregroundError;\n\tif (asyncError) throw asyncError;\n\tthrow new Error(\"Run not found. Provide id or runId.\");\n}\n\nfunction getAsyncInterruptTarget(\n\tstate: SubagentState,\n\trunId: string | undefined,\n\tlocation?: { asyncDir: string | null; resolvedId?: string },\n\toptions: { fallbackToNewest?: boolean } = {},\n): { asyncId: string; asyncDir: string } | undefined {\n\tif (location?.asyncDir) {\n\t\treturn {\n\t\t\tasyncId: location.resolvedId ?? runId ?? path.basename(location.asyncDir),\n\t\t\tasyncDir: location.asyncDir,\n\t\t};\n\t}\n\tif (runId) {\n\t\tconst direct = state.asyncJobs.get(runId);\n\t\tif (direct) return { asyncId: direct.asyncId, asyncDir: direct.asyncDir };\n\t\tif (options.fallbackToNewest === false) return undefined;\n\t}\n\tlet newest: { asyncId: string; asyncDir: string; updatedAt: number } | undefined;\n\tfor (const job of state.asyncJobs.values()) {\n\t\tif (job.status !== \"running\") continue;\n\t\tif (!newest || (job.updatedAt ?? 0) > newest.updatedAt) {\n\t\t\tnewest = { asyncId: job.asyncId, asyncDir: job.asyncDir, updatedAt: job.updatedAt ?? 0 };\n\t\t}\n\t}\n\treturn newest ? { asyncId: newest.asyncId, asyncDir: newest.asyncDir } : undefined;\n}\n\nfunction emitControlNotification(input: {\n\tpi: ExtensionAPI;\n\tcontrolConfig: ResolvedControlConfig;\n\tintercomBridge: IntercomBridgeState;\n\tevent: ControlEvent;\n}): void {\n\tif (!shouldNotifyControlEvent(input.controlConfig, input.event)) return;\n\tconst childIntercomTarget = input.intercomBridge.active\n\t\t? resolveSubagentIntercomTarget(input.event.runId, input.event.agent, input.event.index)\n\t\t: undefined;\n\tconst payload = {\n\t\tevent: input.event,\n\t\tsource: \"foreground\" as const,\n\t\tchildIntercomTarget,\n\t\tnoticeText: formatControlNoticeMessage(input.event, childIntercomTarget),\n\t};\n\tif (input.controlConfig.notifyChannels.includes(\"event\")) {\n\t\tinput.pi.events.emit(SUBAGENT_CONTROL_EVENT, payload);\n\t}\n\tif (input.event.type !== \"active_long_running\" && input.controlConfig.notifyChannels.includes(\"intercom\") && input.intercomBridge.active && input.intercomBridge.orchestratorTarget) {\n\t\tinput.pi.events.emit(SUBAGENT_CONTROL_INTERCOM_EVENT, {\n\t\t\t...payload,\n\t\t\tto: input.intercomBridge.orchestratorTarget,\n\t\t\tmessage: formatControlIntercomMessage(input.event, childIntercomTarget),\n\t\t});\n\t}\n}\n\nfunction interruptAsyncRun(\n\tstate: SubagentState,\n\trunId: string | undefined,\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean,\n\tlocation?: { asyncDir: string | null; resolvedId?: string },\n): AgentToolResult<Details> | null {\n\tconst target = getAsyncInterruptTarget(state, runId, location);\n\tif (!target) return null;\n\tconst status = reconcileAsyncRun(target.asyncDir, { kill }).status;\n\tif (!status || status.state !== \"running\" || typeof status.pid !== \"number\") {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No running async run with an interrupt-capable pid was found for '${runId ?? \"current\"}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\ttry {\n\t\tdeliverInterruptRequest({ asyncDir: target.asyncDir, pid: status.pid, kill, source: \"interrupt-action\" });\n\t\tconst tracked = state.asyncJobs.get(target.asyncId);\n\t\tif (tracked) {\n\t\t\ttracked.activityState = undefined;\n\t\t\ttracked.updatedAt = Date.now();\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Interrupt requested for async run ${target.asyncId}.` }],\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Failed to interrupt async run ${target.asyncId}: ${message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n}\n\nfunction stopAsyncRun(\n\tstate: SubagentState,\n\trunId: string | undefined,\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean,\n\tlocation?: { asyncDir: string | null; resolvedId?: string },\n): AgentToolResult<Details> | null {\n\tconst target = getAsyncInterruptTarget(state, runId, location, { fallbackToNewest: false });\n\tif (!target) return null;\n\tconst status = reconcileAsyncRun(target.asyncDir, { kill }).status;\n\tif (state.currentSessionId && status?.sessionId !== state.currentSessionId) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Async run '${target.asyncId}' was not found in the active session.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (!status || (status.state !== \"running\" && status.state !== \"queued\")) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No running or queued async run was found for '${runId ?? \"current\"}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\ttry {\n\t\tdeliverStopRequest({ asyncDir: target.asyncDir, pid: typeof status.pid === \"number\" ? status.pid : undefined, kill, source: \"stop-action\" });\n\t\tconst tracked = state.asyncJobs.get(target.asyncId);\n\t\tif (tracked) {\n\t\t\ttracked.activityState = undefined;\n\t\t\ttracked.updatedAt = Date.now();\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Stop requested for async run ${target.asyncId}.` }],\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Failed to stop async run ${target.asyncId}: ${message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n}\n\nfunction duplicateNames(names: string[]): string[] {\n\tconst seen = new Set<string>();\n\tconst duplicates = new Set<string>();\n\tfor (const name of names) {\n\t\tif (seen.has(name)) duplicates.add(name);\n\t\telse seen.add(name);\n\t}\n\treturn [...duplicates];\n}\n\nfunction appendStepToAsyncChain(input: {\n\tparams: SubagentParamsLike;\n\trequestCwd: string;\n\tctx: ExtensionContext;\n\tdeps: ExecutorDeps;\n}): AgentToolResult<Details> {\n\tconst targetRunId = input.params.id ?? input.params.runId;\n\tif (!targetRunId) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"action='append-step' requires id.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (!input.params.chain || input.params.chain.length !== 1) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"action='append-step' requires chain with exactly one step.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst acceptanceErrors = validateExecutionAcceptance(input.params);\n\tif (acceptanceErrors.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step: ${acceptanceErrors.join(\" \")}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tlet resolved: ResolvedSubagentRunId | undefined;\n\ttry {\n\t\tresolved = resolveSubagentRunId(targetRunId, { state: input.deps.state, nested: nestedResolutionScopeForExecutor(input.deps) });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tif (!resolved) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No async chain run found for '${targetRunId}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (resolved.kind !== \"async\" || !resolved.location.asyncDir) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' is not an append-capable async chain run.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst status = readStatus(resolved.location.asyncDir);\n\tif (!status) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `No async run status found for '${resolved.id}'.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (status.mode !== \"chain\") {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' is ${status.mode}; only active chain runs accept appended steps.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tif (status.state !== \"running\") {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' is ${status.state}; only running chain runs accept appended steps.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst stillInProgress = (status.steps ?? []).some((step) => step.status === \"running\" || step.status === \"pending\") || (status.pendingAppends ?? 0) > 0;\n\tif (!stillInProgress) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run '${resolved.id}' has no running or pending chain steps left; append-step must target an in-progress chain.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst pendingAppendRequests = readPendingChainAppendRequests(resolved.location.asyncDir);\n\tconst reservedOutputNames = new Set<string>([\n\t\t...Object.keys(status.outputs ?? {}),\n\t\t...(status.steps ?? []).map((step) => step.outputName).filter((name): name is string => Boolean(name)),\n\t\t...pendingAppendRequests.flatMap((request) => runnerStepOutputNames(request.steps)),\n\t]);\n\ttry {\n\t\tvalidateChainOutputBindingsWithContext(input.params.chain, { maxItems: input.deps.config.chain?.dynamicFanout?.maxItems }, {\n\t\t\tpriorOutputNames: reservedOutputNames,\n\t\t\tstartStepIndex: status.chainStepCount ?? status.steps?.length ?? 0,\n\t\t});\n\t} catch (error) {\n\t\tif (!(error instanceof ChainOutputValidationError)) throw error;\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step to run '${resolved.id}': ${error.message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tlet appendParams: SubagentParamsLike;\n\tconst appendChildRunId = `${resolved.id}-append-${randomUUID().slice(0, 8)}`;\n\ttry {\n\t\tappendParams = internalizePromptDrivenChildren(input.params, {\n\t\t\trunId: appendChildRunId,\n\t\t\tparentMode: snapshotParentPermissionMode(input.deps.state.currentSessionId),\n\t\t\tdynamicFanoutMaxItems: input.deps.config.chain?.dynamicFanout?.maxItems,\n\t\t}).params;\n\t} catch (error) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: error instanceof Error ? error.message : String(error) }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst contextPolicy = resolveExplicitContextPolicy(appendParams);\n\tconst chainSkillInput = normalizeSkillInput(appendParams.skill);\n\tconst chainSkills = chainSkillInput === false ? [] : (chainSkillInput ?? []);\n\tconst asyncCtx = {\n\t\tpi: input.deps.pi,\n\t\tcwd: input.ctx.cwd,\n\t\tcurrentSessionId: resolveCurrentSessionId(input.ctx.sessionManager),\n\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\tcurrentModelProvider: input.ctx.model?.provider,\n\t\tcurrentModel: input.ctx.model,\n\t\tmodelScope: undefined,\n\t};\n\tconst built = buildAsyncRunnerSteps(resolved.id, {\n\t\tchain: wrapChainTasksForFork(appendParams.chain!, contextPolicy),\n\t\ttask: appendParams.task,\n\t\tresultMode: \"chain\",\n\t\tctx: asyncCtx,\n\t\tavailableModels: input.ctx.modelRegistry.getAvailable().map(toModelInfo),\n\t\tcwd: status.cwd ?? input.requestCwd,\n\t\tchainSkills,\n\t\tdynamicFanoutMaxItems: input.deps.config.chain?.dynamicFanout?.maxItems,\n\t\tmaxSubagentDepth: resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth),\n\t\twaitToolEnabled: input.deps.waitToolEnabled,\n\t\tasyncDir: resolved.location.asyncDir,\n\t\tchildIdRunId: appendChildRunId,\n\t\tvalidateOutputBindings: false,\n\t});\n\tif (\"error\" in built) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: built.error }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst appendedOutputNames = runnerStepOutputNames(built.steps);\n\tconst duplicateAppendedOutputs = duplicateNames(appendedOutputNames);\n\tif (duplicateAppendedOutputs.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step to run '${resolved.id}': duplicate output name in appended step: ${duplicateAppendedOutputs.join(\", \")}.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst pendingOutputNames = new Set(pendingAppendRequests.flatMap((request) => runnerStepOutputNames(request.steps)));\n\tconst pendingDuplicateOutputs = appendedOutputNames.filter((name) => pendingOutputNames.has(name));\n\tif (pendingDuplicateOutputs.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot append step to run '${resolved.id}': output name already belongs to a pending append: ${pendingDuplicateOutputs.join(\", \")}.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\ttry {\n\t\tconst result = enqueueChainAppendRequest({\n\t\t\tasyncDir: resolved.location.asyncDir,\n\t\t\trunId: resolved.id,\n\t\t\tsteps: built.steps,\n\t\t});\n\t\tconst stepText = built.steps.length === 1 ? \"step\" : \"steps\";\n\t\treturn {\n\t\t\tcontent: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: `Append queued for chain run ${resolved.id}: ${built.steps.length} ${stepText}. It becomes eligible after the chain's already-queued steps finish. Pending appends: ${result.pendingCount}.`,\n\t\t\t}],\n\t\t\tdetails: { mode: \"management\", results: [], asyncId: resolved.id, asyncDir: resolved.location.asyncDir },\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Failed to append step to chain run ${resolved.id}: ${message}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n}\n\nfunction nestedRunSessionFile(run: NestedRunSummary): string | undefined {\n\treturn run.sessionFile ?? (run.steps?.length === 1 ? run.steps[0]?.sessionFile : undefined);\n}\n\nfunction nestedRunAgent(run: NestedRunSummary): string | undefined {\n\treturn run.agent ?? run.agents?.[0] ?? (run.steps?.length === 1 ? run.steps[0]?.agent : undefined);\n}\n\nfunction pathWithin(base: string, candidate: string): boolean {\n\tconst resolvedBase = path.resolve(base);\n\tconst resolvedCandidate = path.resolve(candidate);\n\treturn resolvedCandidate === resolvedBase || resolvedCandidate.startsWith(`${resolvedBase}${path.sep}`);\n}\n\nfunction validateNestedSessionFile(run: NestedRunSummary, trustedSessionRoots: string[]): string {\n\tconst sessionFile = nestedRunSessionFile(run);\n\tif (!sessionFile) throw new Error(`Nested run '${run.id}' does not have a persisted session file to resume from.`);\n\tif (path.extname(sessionFile) !== \".jsonl\") throw new Error(`Nested run '${run.id}' session file must be a .jsonl file: ${sessionFile}`);\n\tconst resolved = path.resolve(sessionFile);\n\tif (!path.isAbsolute(sessionFile)) throw new Error(`Nested run '${run.id}' session file must be absolute: ${sessionFile}`);\n\tif (!fs.existsSync(resolved)) throw new Error(`Nested run '${run.id}' session file does not exist: ${sessionFile}`);\n\tconst stat = fs.lstatSync(resolved);\n\tif (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`Nested run '${run.id}' session file is not a regular file: ${sessionFile}`);\n\tconst realSessionFile = fs.realpathSync(resolved);\n\tconst trustedRoots = trustedSessionRoots\n\t\t.filter((root) => fs.existsSync(root))\n\t\t.map((root) => fs.realpathSync(root));\n\tif (!trustedRoots.some((root) => pathWithin(root, realSessionFile))) {\n\t\tthrow new Error(`Nested run '${run.id}' session file is outside trusted nested session roots: ${sessionFile}`);\n\t}\n\tif (!realSessionFile.split(path.sep).includes(run.id)) {\n\t\tthrow new Error(`Nested run '${run.id}' session file is not under that nested run's session directory: ${sessionFile}`);\n\t}\n\treturn realSessionFile;\n}\n\nfunction resolveNestedResumeTarget(match: ResolvedSubagentRunId & { kind: \"nested\" }, trustedSessionRoots: string[]): NestedResumeSourceTarget {\n\tconst run = match.match.run;\n\tif (run.state === \"running\" || run.state === \"queued\") throw new Error(`Nested run '${run.id}' is live; route the follow-up to the owner process instead.`);\n\tconst agent = nestedRunAgent(run);\n\tif (!agent) throw new Error(`Could not determine child agent for nested run '${run.id}'.`);\n\tconst state = run.state === \"complete\" || run.state === \"failed\" || run.state === \"paused\" || run.state === \"stopped\" ? run.state : \"failed\";\n\tconst asyncDir = resolveNestedAsyncDir(match.match.rootRunId, run);\n\treturn {\n\t\tkind: \"revive\",\n\t\tsource: \"nested\",\n\t\trunId: run.id,\n\t\tstate,\n\t\tagent,\n\t\tindex: 0,\n\t\tintercomTarget: resolveSubagentIntercomTarget(run.id, agent, 0),\n\t\tcwd: asyncDir ? path.dirname(asyncDir) : undefined,\n\t\tsessionFile: validateNestedSessionFile(run, trustedSessionRoots),\n\t};\n}\n\nasync function waitForNestedControlResult(target: ResolvedSubagentRunId & { kind: \"nested\" }, requestId: string, timeoutMs = 1_000) {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tconst result = readNestedControlResults(target.match.route).find((candidate) => candidate.requestId === requestId && candidate.targetRunId === target.match.run.id);\n\t\tif (result) return result;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 50));\n\t}\n\treturn undefined;\n}\n\nasync function sendNestedControlRequest(target: ResolvedSubagentRunId & { kind: \"nested\" }, action: \"interrupt\" | \"resume\", message?: string) {\n\tconst requestId = randomUUID();\n\twriteNestedControlRequest(target.match.route, {\n\t\tts: Date.now(),\n\t\trequestId,\n\t\ttargetRunId: target.match.run.id,\n\t\taction,\n\t\t...(message ? { message } : {}),\n\t});\n\treturn waitForNestedControlResult(target, requestId);\n}\n\nfunction directNestedAsyncInterrupt(target: ResolvedSubagentRunId & { kind: \"nested\" }): AgentToolResult<Details> | undefined {\n\tconst run = target.match.run;\n\tconst asyncDir = resolveNestedAsyncDir(target.match.rootRunId, run);\n\tif (!asyncDir) return undefined;\n\tconst status = reconcileAsyncRun(asyncDir, { resultsDir: path.join(RESULTS_DIR, \"nested\", target.match.rootRunId) }).status;\n\tconst pid = typeof status?.pid === \"number\" && status.pid > 0 ? status.pid : run.pid;\n\tif (!status || status.state !== \"running\" || typeof pid !== \"number\" || pid <= 0) return undefined;\n\ttry {\n\t\tdeliverInterruptRequest({ asyncDir, pid, source: \"nested-interrupt\" });\n\t\treturn { content: [{ type: \"text\", text: `Interrupt requested for nested async run ${run.id}.` }], details: { mode: \"management\", results: [] } };\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { content: [{ type: \"text\", text: `Failed to interrupt nested async run ${run.id}: ${message}` }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n}\n\nasync function directNestedAsyncSteer(input: { target: ResolvedSubagentRunId & { kind: \"nested\" }; message: string; index?: number; signal?: AbortSignal }): Promise<AgentToolResult<Details> | undefined> {\n\tconst run = input.target.match.run;\n\tconst asyncDir = resolveNestedAsyncDir(input.target.match.rootRunId, run);\n\tif (!asyncDir) return undefined;\n\tconst status = reconcileAsyncRun(asyncDir, { resultsDir: path.join(RESULTS_DIR, \"nested\", input.target.match.rootRunId) }).status;\n\tif (!status || (status.state !== \"running\" && status.state !== \"queued\")) return undefined;\n\tconst steps = status.steps ?? [];\n\tif (input.index !== undefined) {\n\t\tif (input.index < 0 || input.index >= steps.length) return { content: [{ type: \"text\", text: `Nested async run ${run.id} has ${steps.length} children. Index ${input.index} is out of range.` }], isError: true, details: { mode: \"management\", results: [] } };\n\t\tconst step = steps[input.index];\n\t\tif (step && step.status !== \"running\" && step.status !== \"pending\") return { content: [{ type: \"text\", text: `Nested async run ${run.id} child ${input.index} is ${step.status} and cannot be steered.` }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tconst runningIndexes = steps\n\t\t.map((step, index) => step.status === \"running\" ? index : undefined)\n\t\t.filter((index): index is number => index !== undefined);\n\tconst effectiveTargetIndex = input.index ?? (status.mode === \"single\" && runningIndexes.length === 0 && steps[0]?.status === \"pending\" ? 0 : undefined);\n\tconst targetIndexes = effectiveTargetIndex !== undefined ? [effectiveTargetIndex] : runningIndexes;\n\tif (targetIndexes.length === 0) return { content: [{ type: \"text\", text: `Nested async run ${run.id} has no running child to steer.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tconst requestId = randomUUID();\n\ttry {\n\t\trequestAsyncSteer(asyncDir, {\n\t\t\tmessage: input.message,\n\t\t\t...(effectiveTargetIndex !== undefined ? { targetIndex: effectiveTargetIndex } : { targetIndexes }),\n\t\t\tsource: \"nested-steer\",\n\t\t\tid: requestId,\n\t\t});\n\t} catch (error) {\n\t\treturn { content: [{ type: \"text\", text: `Failed to queue steering for nested async run ${run.id}: ${error instanceof Error ? error.message : String(error)}` }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tconst targets = targetIndexes.map((index) => ({ index, state: steps[index]?.status === \"pending\" ? \"scheduled\" as const : \"pending\" as const }));\n\tif (targets.every((target) => target.state === \"scheduled\")) {\n\t\tconst scheduled = { requestId, state: \"scheduled\" as const, sourceRunId: run.id, targets };\n\t\treturn { content: [{ type: \"text\", text: `Steering scheduled for nested async run ${run.id} (request ${requestId}).` }], details: { mode: \"management\", results: [], steering: scheduled } };\n\t}\n\tconst waited = await waitForSteeringAction({ asyncDir, sourceRunId: run.id, requestId, timeoutMs: 3_000, signal: input.signal });\n\tconst result = waited ?? { requestId, state: \"pending\" as const, sourceRunId: run.id, targets };\n\tconst stateText = result.state === \"delivered\" ? \"delivered\" : result.state === \"failed\" ? \"failed\" : result.state === \"partial\" ? \"partial\" : \"pending\";\n\treturn { content: [{ type: \"text\", text: `Steering ${stateText} for nested async run ${run.id} (request ${requestId}).` }], ...(result.state === \"failed\" || result.state === \"partial\" ? { isError: true } : {}), details: { mode: \"management\", results: [], steering: result } };\n}\n\nasync function interruptNestedRun(target: ResolvedSubagentRunId & { kind: \"nested\" }): Promise<AgentToolResult<Details>> {\n\tconst run = target.match.run;\n\tif (run.state === \"complete\") return { content: [{ type: \"text\", text: `Nested run ${run.id} is already complete and cannot be interrupted.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tif (run.state === \"failed\") return { content: [{ type: \"text\", text: `Nested run ${run.id} has failed and cannot be interrupted.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tif (run.state === \"paused\") return { content: [{ type: \"text\", text: `Nested run ${run.id} is already paused.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tconst result = await sendNestedControlRequest(target, \"interrupt\");\n\tif (result) return { content: [{ type: \"text\", text: result.message }], isError: result.ok ? undefined : true, details: { mode: \"management\", results: [] } };\n\tconst direct = directNestedAsyncInterrupt(target);\n\tif (direct) return direct;\n\treturn { content: [{ type: \"text\", text: `Nested run ${run.id} owner is not reachable and no safe direct async interrupt fallback is available.` }], isError: true, details: { mode: \"management\", results: [] } };\n}\n\nasync function resumeLiveNestedRun(input: { target: ResolvedSubagentRunId & { kind: \"nested\" }; message: string }): Promise<AgentToolResult<Details>> {\n\tconst run = input.target.match.run;\n\tconst result = await sendNestedControlRequest(input.target, \"resume\", input.message);\n\tif (result) return { content: [{ type: \"text\", text: result.message }], isError: result.ok ? undefined : true, details: { mode: \"management\", results: [] } };\n\treturn { content: [{ type: \"text\", text: `Nested run ${run.id} appears live but its owner route is not reachable. Wait for completion, then retry action='resume'.` }], isError: true, details: { mode: \"management\", results: [] } };\n}\n\nasync function steerNestedRun(input: { target: ResolvedSubagentRunId & { kind: \"nested\" }; message: string; index?: number; signal?: AbortSignal }): Promise<AgentToolResult<Details>> {\n\tconst run = input.target.match.run;\n\tif (run.state !== \"running\" && run.state !== \"queued\") return { content: [{ type: \"text\", text: `Nested run ${run.id} is ${run.state} and cannot be steered.` }], isError: true, details: { mode: \"management\", results: [] } };\n\tconst direct = await directNestedAsyncSteer(input);\n\tif (direct) return direct;\n\treturn { content: [{ type: \"text\", text: `Nested run ${run.id} is not a live async Pi child session with a steering inbox. action='steer' cannot target foreground nested runs.` }], isError: true, details: { mode: \"management\", results: [] } };\n}\n\nasync function resumeAsyncRun(input: {\n\tparams: SubagentParamsLike;\n\trequestCwd: string;\n\tctx: ExtensionContext;\n\tdeps: ExecutorDeps;\n\tabsoluteDeadlineAt?: number;\n}): Promise<AgentToolResult<Details>> {\n\tconst followUp = (input.params.message ?? input.params.task ?? \"\").trim();\n\tconst attachChain = (input.params.chain?.length ?? 0) > 0 ? input.params.chain as ChainStep[] : undefined;\n\tif (!followUp && !attachChain) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"action='resume' requires message.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tconst acceptanceErrors = validateExecutionAcceptance(input.params);\n\tif (acceptanceErrors.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Cannot resume: ${acceptanceErrors.join(\" \")}` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\tinput.deps.state.currentSessionId = resolveCurrentSessionId(input.ctx.sessionManager);\n\n\tlet target: ResumeSourceTarget;\n\tconst parentSessionFile = input.ctx.sessionManager.getSessionFile() ?? null;\n\ttry {\n\t\tconst requestedId = input.params.id ?? input.params.runId;\n\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\ttry {\n\t\t\tresolved = requestedId ? resolveSubagentRunId(requestedId, { state: input.deps.state, nested: nestedResolutionScopeForExecutor(input.deps) }) : undefined;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"\";\n\t\t\tconst asyncMatches = message.match(/async:/g)?.length ?? 0;\n\t\t\tif (!isResumeAmbiguity(error) || !message.includes(\"foreground:\") || asyncMatches !== 1) throw error;\n\t\t}\n\t\tif (resolved?.kind === \"nested\") {\n\t\t\tif (attachChain) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Attaching a running subagent as a chain root is currently available for top-level async runs only.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (resolved.match.run.state === \"running\" || resolved.match.run.state === \"queued\") {\n\t\t\t\treturn resumeLiveNestedRun({ target: resolved, message: followUp });\n\t\t\t}\n\t\t\tconst trustedSessionRoots = [\n\t\t\t\t...(input.deps.config.defaultSessionDir ? [path.resolve(input.deps.expandTilde(input.deps.config.defaultSessionDir))] : []),\n\t\t\t\t...(parentSessionFile ? [input.deps.getSubagentSessionRoot(parentSessionFile)] : []),\n\t\t\t];\n\t\t\ttarget = resolveNestedResumeTarget(resolved, trustedSessionRoots);\n\t\t} else {\n\t\t\ttarget = resolveResumeTarget(input.params, input.deps.state, { asyncRequireSessionFile: !attachChain });\n\t\t}\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\n\tif (target.kind === \"live\" && !attachChain) {\n\t\tconst interrupt = interruptLiveAsyncResumeTarget({\n\t\t\ttarget,\n\t\t\tstate: input.deps.state,\n\t\t\tkill: input.deps.kill,\n\t\t\tresultsDir: RESULTS_DIR,\n\t\t});\n\t\tif (!interrupt.ok) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: interrupt.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t};\n\t\t}\n\t\tconst delivered = await deliverSubagentIntercomMessageEvent(\n\t\t\tinput.deps.pi.events,\n\t\t\ttarget.intercomTarget,\n\t\t\t`Follow-up for async run ${target.runId} (${target.agent}):\\n\\n${followUp}`,\n\t\t\t500,\n\t\t\t{ source: \"async-resume\", runId: target.runId, agent: target.agent, index: target.index },\n\t\t);\n\t\tif (delivered) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: [`Interrupted live async child, then delivered follow-up.`, `Run: ${target.runId}`, `Intercom target: ${target.intercomTarget}`].join(\"\\n\") }],\n\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: [`Async child appears live but its intercom target is not registered.`, `Run: ${target.runId}`, `Intercom target: ${target.intercomTarget}`, `Wait for completion, then retry action='resume'.`].join(\"\\n\") }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tconst { blocked, depth, maxDepth } = checkSubagentDepth(input.deps.config.maxSubagentDepth);\n\tif (blocked) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Nested subagent resume blocked (depth=${depth}, max=${maxDepth}). Complete the follow-up directly instead.` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t};\n\t}\n\n\tinput.deps.state.currentSessionId = resolveCurrentSessionId(input.ctx.sessionManager);\n\tconst effectiveCwd = target.cwd ?? input.requestCwd;\n\tconst modelScope = undefined;\n\tconst sessionName = resolveIntercomSessionTarget(input.deps.pi.getSessionName(), input.ctx.sessionManager.getSessionId());\n\tconst intercomBridge = resolveIntercomBridge({\n\t\tconfig: input.deps.config.intercomBridge,\n\t\tcontext: input.params.context,\n\t\torchestratorTarget: sessionName,\n\t});\n\tconst recoveryDescriptor = \"recoveryDescriptor\" in target ? target.recoveryDescriptor : undefined;\n\n\tif (attachChain) {\n\t\tif (target.source !== \"async\") {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Attaching a running subagent as a chain root is currently available for async runs only.\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t};\n\t\t}\n\t\tif (!isAsyncAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Async mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\", results: [] },\n\t\t\t};\n\t\t}\n\t\tconst runId = randomUUID().slice(0, 8);\n\t\tconst artifactConfig: ArtifactConfig = { ...DEFAULT_ARTIFACT_CONFIG, enabled: input.params.artifacts !== false };\n\t\tconst availableModels = input.ctx.modelRegistry.getAvailable().map(toModelInfo);\n\t\tconst contextPolicy = resolveExplicitContextPolicy(input.params);\n\t\tconst workflowTask = (input.params.task ?? followUp) || undefined;\n\t\tconst goal = resolveAsyncEventGoal(workflowTask, attachChain);\n\t\tconst chain = wrapChainTasksForFork(attachChain, contextPolicy);\n\t\tconst normalized = normalizeSkillInput(input.params.skill);\n\t\tconst result = executeAsyncChain(runId, {\n\t\t\tchain,\n\t\t\ttask: workflowTask,\n\t\t\tgoal,\n\t\t\tattachRoot: {\n\t\t\t\trunId: target.runId,\n\t\t\t\tasyncDir: target.asyncDir ?? path.join(ASYNC_DIR, target.runId),\n\t\t\t\tresultPath: resolveAsyncRootResultPath(RESULTS_DIR, target.runId),\n\t\t\t\tindex: target.index,\n\t\t\t\tagent: target.agent,\n\t\t\t\tlabel: `Attached ${target.runId}`,\n\t\t\t},\n\t\t\tctx: {\n\t\t\t\tpi: input.deps.pi,\n\t\t\t\tcwd: input.requestCwd,\n\t\t\t\tcurrentSessionId: input.deps.state.currentSessionId,\n\t\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcurrentModelProvider: input.ctx.model?.provider,\n\t\t\t\tcurrentModel: input.ctx.model,\n\t\t\t\tmodelScope,\n\t\t\t},\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: input.params.maxOutput,\n\t\t\tartifactsDir: getArtifactsDir(parentSessionFile, effectiveCwd),\n\t\t\tartifactConfig,\n\t\t\tshareEnabled: input.params.share === true,\n\t\t\tsessionRoot: input.deps.getSubagentSessionRoot(parentSessionFile),\n\t\t\tchainSkills: normalized === false ? [] : (normalized ?? []),\n\t\t\tdynamicFanoutMaxItems: input.deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\tmaxSubagentDepth: resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth),\n\t\t\twaitToolEnabled: input.deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: input.deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: input.deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: input.deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig: resolveControlConfig(input.deps.config.control, input.params.control),\n\t\t\tcontrolIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,\n\t\t\tchildIntercomTarget: intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(runId, agent, index) : undefined,\n\t\t\tglobalConcurrencyLimit: input.deps.config.globalConcurrencyLimit,\n\t\t});\n\t\tif (result.isError) return result;\n\t\tconst attachedId = result.details.asyncId ?? runId;\n\t\tconst lines = [\n\t\t\t`Attached async subagent ${target.runId} as the first step of a new chain.`,\n\t\t\t`Chain run: ${attachedId}`,\n\t\t\t`Root: ${target.agent} (step ${target.index + 1})`,\n\t\t\tresult.details.asyncDir ? `Async dir: ${result.details.asyncDir}` : undefined,\n\t\t\t`Status if needed: subagent({ action: \"status\", id: \"${attachedId}\" })`,\n\t\t].filter((line): line is string => Boolean(line));\n\t\treturn { content: [{ type: \"text\", text: formatAsyncStartedMessage(lines.join(\"\\n\")) }], details: result.details };\n\t}\n\n\tconst runId = randomUUID().slice(0, 8);\n\tconst artifactConfig: ArtifactConfig = recoveryDescriptor?.artifactConfig ?? { ...DEFAULT_ARTIFACT_CONFIG, enabled: input.params.artifacts !== false };\n\tconst artifactsDir = recoveryDescriptor?.artifactsDir ?? getArtifactsDir(parentSessionFile, effectiveCwd);\n\tconst availableModels = input.ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tlet recoverySpec: ChildSpec;\n\ttry {\n\t\trecoverySpec = normalizeChildSpec({\n\t\t\ttask: buildRevivedAsyncTask(target, followUp),\n\t\t\tdescription: recoveryDescriptor?.description ?? target.description ?? target.agent,\n\t\t\tpermissions: recoveryDescriptor?.permissions ?? target.permissions ?? \"read-only\",\n\t\t\tmodel: input.params.model ?? recoveryDescriptor?.model ?? target.model,\n\t\t\tskill: recoveryDescriptor?.skills,\n\t\t\tcwd: effectiveCwd,\n\t\t\toutput: recoveryDescriptor?.outputPath,\n\t\t\toutputMode: recoveryDescriptor?.outputMode,\n\t\t\tacceptance: input.params.acceptance ?? recoveryDescriptor?.acceptance,\n\t\t\ttoolBudget: recoveryDescriptor?.initialToolBudget,\n\t\t}, {\n\t\t\tparentMode: snapshotParentPermissionMode(input.deps.state.currentSessionId),\n\t\t\trunId,\n\t\t\tindex: 0,\n\t\t\tchildId: recoveryDescriptor?.childId ?? target.childId ?? `${runId}-0`,\n\t\t});\n\t} catch (error) {\n\t\treturn { content: [{ type: \"text\", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: \"management\", results: [] } };\n\t}\n\tconst result = executeAsyncSingle(runId, {\n\t\tspec: recoverySpec,\n\t\tgoal: followUp,\n\t\tctx: {\n\t\t\tpi: input.deps.pi,\n\t\t\tcwd: input.requestCwd,\n\t\t\tcurrentSessionId: input.deps.state.currentSessionId,\n\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\tcurrentModelProvider: input.ctx.model?.provider,\n\t\t\tcurrentModel: input.ctx.model,\n\t\t\tmodelScope,\n\t\t},\n\t\tcwd: effectiveCwd,\n\t\tmaxOutput: input.params.maxOutput ?? recoveryDescriptor?.maxOutput,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tshareEnabled: recoveryDescriptor?.share ?? input.params.share === true,\n\t\tsessionRoot: input.deps.getSubagentSessionRoot(parentSessionFile),\n\t\t...(recoveryDescriptor?.sessionDir ? { sessionDir: recoveryDescriptor.sessionDir } : {}),\n\t\tsessionFile: target.sessionFile,\n\t\trevivalLease: {\n\t\t\tsessionFile: target.sessionFile,\n\t\t\trunId,\n\t\t\tsourceRunId: target.runId,\n\t\t\t...(input.deps.state.currentSessionId ? { parentSessionId: input.deps.state.currentSessionId } : {}),\n\t\t},\n\t\tmodelOverride: input.params.model ?? recoveryDescriptor?.model ?? target.model,\n\t\tthinkingOverride: input.params.model ? undefined : recoveryDescriptor?.thinking ?? target.thinking,\n\t\toutputBaseDir: resolveSingleRunOutputBaseDir(input.deps, artifactsDir, runId),\n\t\tmaxSubagentDepth: recoveryDescriptor?.maxSubagentDepth ?? resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth),\n\t\twaitToolEnabled: input.deps.waitToolEnabled,\n\t\tworktreeSetupHook: input.deps.config.worktreeSetupHook,\n\t\tworktreeSetupHookTimeoutMs: input.deps.config.worktreeSetupHookTimeoutMs,\n\t\tworktreeBaseDir: input.deps.config.worktreeBaseDir,\n\t\tcontrolConfig: recoveryDescriptor?.controlConfig ?? resolveControlConfig(input.deps.config.control, input.params.control),\n\t\tcontrolIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,\n\t\tchildIntercomTarget: intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(runId, agent, index) : undefined,\n\t\tavailableModels,\n\t\toutput: recoveryDescriptor?.outputPath,\n\t\toutputMode: recoveryDescriptor?.outputMode,\n\t\t...(recoveryDescriptor?.skills ? { skills: [...recoveryDescriptor.skills] } : {}),\n\t\t...(recoveryDescriptor?.acceptance !== undefined && input.params.acceptance === undefined ? { acceptance: recoveryDescriptor.acceptance } : {}),\n\t\t...(input.params.timeoutMs !== undefined ? { timeoutMs: input.params.timeoutMs } : {}),\n\t\t...(input.absoluteDeadlineAt !== undefined ? { absoluteDeadlineAt: input.absoluteDeadlineAt } : {}),\n\t\t...(input.params.turnBudget !== undefined ? { turnBudget: input.params.turnBudget } : {}),\n\t\t...(input.params.toolBudget !== undefined ? { toolBudget: input.params.toolBudget } : {}),\n\t});\n\tif (result.isError) return result;\n\n\tconst revivedId = result.details.asyncId ?? runId;\n\tconst revivedTarget = intercomBridge.active ? resolveSubagentIntercomTarget(revivedId, target.agent, 0) : undefined;\n\tconst sourceLabel = target.source;\n\tconst lines = [\n\t\t`Revived ${sourceLabel} subagent from ${target.runId}.`,\n\t\t`Revived run: ${revivedId}`,\n\t\t`Agent: ${target.agent}`,\n\t\t`Session: ${target.sessionFile}`,\n\t\tresult.details.asyncDir ? `Async dir: ${result.details.asyncDir}` : undefined,\n\t\trevivedTarget ? `Intercom target: ${revivedTarget} (if registered)` : undefined,\n\t\t`Status if needed: subagent({ action: \"status\", id: \"${revivedId}\" })`,\n\t].filter((line): line is string => Boolean(line));\n\treturn { content: [{ type: \"text\", text: formatAsyncStartedMessage(lines.join(\"\\n\")) }], details: result.details };\n}\n\nfunction resultSummaryForIntercom(result: SingleResult): string {\n\tconst output = getSingleResultOutput(result);\n\tif (result.exitCode !== 0 && result.error) {\n\t\treturn output ? `${result.error}\\n\\nOutput:\\n${output}` : result.error;\n\t}\n\treturn output || result.error || \"(no output)\";\n}\n\nfunction formatFailedSingleRunOutput(result: SingleResult, displayOutput: string): string {\n\tconst error = result.error || \"Failed\";\n\tconst output = displayOutput.trim();\n\tconst lines = [error];\n\tif (output && output !== error.trim()) {\n\t\tlines.push(\"\", \"Output:\", output);\n\t}\n\tif (result.artifactPaths?.outputPath) {\n\t\tlines.push(\"\", `Output artifact: ${result.artifactPaths.outputPath}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction createForegroundControlNotifier(data: Pick<ExecutionContextData, \"controlConfig\" | \"intercomBridge\">, deps: Pick<ExecutorDeps, \"pi\">): (event: ControlEvent) => void {\n\treturn (event) => emitControlNotification({\n\t\tpi: deps.pi,\n\t\tcontrolConfig: data.controlConfig,\n\t\tintercomBridge: data.intercomBridge,\n\t\tevent,\n\t});\n}\n\nasync function emitForegroundResultIntercom(input: {\n\tpi: ExtensionAPI;\n\tintercomBridge: IntercomBridgeState;\n\trunId: string;\n\tmode: SubagentRunMode;\n\tresults: SingleResult[];\n\tchainSteps?: number;\n\tnestedChildren?: NestedRunSummary[];\n}): Promise<ReturnType<typeof buildSubagentResultIntercomPayload> | null> {\n\tif (!input.intercomBridge.active || !input.intercomBridge.orchestratorTarget) return null;\n\tconst children = input.results.flatMap((result, index) => result.detached ? [] : [{\n\t\tagent: result.agent,\n\t\tstatus: resolveSubagentResultStatus({\n\t\t\texitCode: result.exitCode,\n\t\t\tinterrupted: result.interrupted,\n\t\t\tdetached: result.detached,\n\t\t}),\n\t\tsummary: resultSummaryForIntercom(result),\n\t\tindex,\n\t\tartifactPath: result.artifactPaths?.outputPath,\n\t\tsessionPath: result.sessionFile,\n\t\tintercomTarget: resolveSubagentIntercomTarget(input.runId, result.agent, index),\n\t}]);\n\tif (children.length === 0) return null;\n\tconst payload = buildSubagentResultIntercomPayload({\n\t\tto: input.intercomBridge.orchestratorTarget,\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tsource: \"foreground\",\n\t\tchildren: attachNestedChildrenToResultChildren(input.runId, children, input.nestedChildren),\n\t\t...(typeof input.chainSteps === \"number\" ? { chainSteps: input.chainSteps } : {}),\n\t});\n\tconst delivered = await deliverSubagentResultIntercomEvent(input.pi.events, payload);\n\tif (!delivered) return null;\n\treturn payload;\n}\n\nasync function maybeBuildForegroundIntercomReceipt(input: {\n\tpi: ExtensionAPI;\n\tintercomBridge: IntercomBridgeState;\n\trunId: string;\n\tmode: SubagentRunMode;\n\tdetails: Details;\n\tnestedChildren?: NestedRunSummary[];\n}): Promise<{ text: string; details: Details } | null> {\n\tconst payload = await emitForegroundResultIntercom({\n\t\tpi: input.pi,\n\t\tintercomBridge: input.intercomBridge,\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tresults: input.details.results,\n\t\t...(typeof input.details.totalSteps === \"number\" ? { chainSteps: input.details.totalSteps } : {}),\n\t\t...(input.nestedChildren?.length ? { nestedChildren: input.nestedChildren } : {}),\n\t});\n\tif (!payload) return null;\n\treturn {\n\t\ttext: formatSubagentResultReceipt({ mode: input.mode, runId: input.runId, payload }),\n\t\tdetails: stripDetailsOutputsForIntercomReceipt(input.details),\n\t};\n}\n\nfunction validateExecutionInput(\n\tparams: SubagentParamsLike,\n\thasChain: boolean,\n\thasTasks: boolean,\n\thasSingle: boolean,\n\tallowClarifyTaskPrompt: boolean,\n): AgentToolResult<Details> | null {\n\tif (Number(hasChain) + Number(hasTasks) + Number(hasSingle) !== 1) {\n\t\treturn {\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: \"Provide exactly one mode: { task, description, permissions? }, { tasks: [...] }, or { chain: [...] }.\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t};\n\t}\n\n\tconst acceptanceErrors = validateExecutionAcceptance(params);\n\tif (acceptanceErrors.length > 0) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: acceptanceErrors.join(\" \") }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: getRequestedModeLabel(params), results: [] },\n\t\t};\n\t}\n\n\tif (hasSingle && !params.description) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"description is required and must be a concise single-line label (max 80 characters).\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t};\n\t}\n\n\tif (hasTasks && params.tasks) {\n\t\tfor (let i = 0; i < params.tasks.length; i++) {\n\t\t\tconst task = params.tasks[i]!;\n\t\t\tif (!task.description) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `description is required (task ${i + 1})` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasChain && params.chain) {\n\t\tif (params.chain.length === 0) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Chain must have at least one step\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tconst firstStep = params.chain[0] as ChainStep;\n\t\tif (isParallelStep(firstStep)) {\n\t\t\tconst missingTaskIndex = firstStep.parallel.findIndex((t) => !t.task);\n\t\t\tif (missingTaskIndex !== -1) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `First parallel step: task ${missingTaskIndex + 1} must have a task (no previous output to reference)` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (isDynamicParallelStep(firstStep)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"First step in chain cannot be dynamic fanout; expand.from requires a prior structured named output\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t} else if (!(firstStep as SequentialStep).task && !params.task && !allowClarifyTaskPrompt) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"First step in chain must have a task\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tfor (let i = 0; i < params.chain.length; i++) {\n\t\t\tconst step = params.chain[i] as ChainStep;\n\t\t\tif (!isParallelStep(step) && !isDynamicParallelStep(step) && !(step as SequentialStep).description) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `description is required (step ${i + 1})` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (isParallelStep(step)) {\n\t\t\t\tconst missing = step.parallel.findIndex((t) => !t.description);\n\t\t\t\tif (missing !== -1) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `description is required (step ${i + 1}, parallel task ${missing + 1})` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (isParallelStep(step) && step.parallel.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Parallel step ${i + 1} must have at least one task` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction validateExecutionChainBindings(params: SubagentParamsLike, dynamicFanoutMaxItems?: number): AgentToolResult<Details> | null {\n\tif ((params.chain?.length ?? 0) === 0) return null;\n\ttry {\n\t\tvalidateChainOutputBindingsWithContext(params.chain as ChainStep[], { maxItems: dynamicFanoutMaxItems });\n\t} catch (error) {\n\t\tif (error instanceof ChainOutputValidationError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: error.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\treturn null;\n}\n\nfunction getRequestedModeLabel(params: SubagentParamsLike): Details[\"mode\"] {\n\tif ((params.chain?.length ?? 0) > 0) return \"chain\";\n\tif ((params.tasks?.length ?? 0) > 0) return \"parallel\";\n\tif (params.task) return \"single\";\n\treturn \"single\";\n}\n\ninterface AgentDefaultContextPolicy {\n\tparams: SubagentParamsLike;\n\tcontextForAgent(agentName: string): \"fresh\" | \"fork\";\n\tusesFork: boolean;\n}\n\nfunction resolveAgentDefaultContextPolicy(params: SubagentParamsLike): AgentDefaultContextPolicy {\n\t// lunr: hide fork from the model; force every child to fresh. Fork internals stay.\n\treturn lunrContextPolicy(params);\n}\n\nfunction resolveExplicitContextPolicy(params: SubagentParamsLike): AgentDefaultContextPolicy {\n\t// lunr: `context: \"fork\"` from the model is coerced to fresh.\n\treturn lunrContextPolicy(params);\n}\n\nfunction shouldForkAgent(contextPolicy: AgentDefaultContextPolicy, agentName: string): boolean {\n\treturn contextPolicy.contextForAgent(agentName) === \"fork\";\n}\n\nfunction buildRequestedModeError(params: SubagentParamsLike, message: string): AgentToolResult<Details> {\n\treturn withForkContext(\n\t\t{\n\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: getRequestedModeLabel(params), results: [] },\n\t\t},\n\t\tparams.context,\n\t);\n}\n\nfunction runtimeConfigFromChildSpec(spec: ChildSpec): ChildRuntimeConfig {\n\treturn {\n\t\tname: spec.childId,\n\t\tdescription: spec.description,\n\t\tmodel: spec.model,\n\t\tthinking: undefined,\n\t\tsystemPromptMode: \"append\",\n\t\tinheritProjectContext: true,\n\t\tinheritSkills: false,\n\t\tacceptanceRole: spec.effectivePermissions === \"read-only\" ? \"read-only\" : \"writer\",\n\t\tsystemPrompt: \"\",\n\t\tskills: spec.skill === false ? [] : normalizeSkillInput(spec.skill) || undefined,\n\t\toutput: typeof spec.output === \"string\" ? spec.output : undefined,\n\t\ttoolBudget: spec.toolBudget,\n\t};\n}\n\nfunction internalizePromptDrivenChildren(\n\tparams: SubagentParamsLike,\n\toptions: { runId: string; parentMode?: string; dynamicFanoutMaxItems?: number },\n): { params: SubagentParamsLike; agents: ChildRuntimeConfig[] } {\n\tconst agents: ChildRuntimeConfig[] = [];\n\tlet flatIndex = 0;\n\tconst normalize = (input: TaskParam | SequentialStep, defaultTask?: string): { input: typeof input; spec: ChildSpec } => {\n\t\tconst spec = normalizeChildSpec(input, {\n\t\t\tparentMode: options.parentMode,\n\t\t\trunId: options.runId,\n\t\t\tindex: flatIndex,\n\t\t\tdefaultTask,\n\t\t});\n\t\tagents.push(runtimeConfigFromChildSpec(spec));\n\t\treturn { input: { ...input, agent: spec.childId }, spec };\n\t};\n\n\tif ((params.tasks?.length ?? 0) > 0) {\n\t\tconst tasks = params.tasks!.map((task) => {\n\t\t\tconst normalized = normalize(task);\n\t\t\tflatIndex++;\n\t\t\treturn normalized.input as TaskParam;\n\t\t});\n\t\treturn { params: { ...params, tasks }, agents };\n\t}\n\n\tif ((params.chain?.length ?? 0) > 0) {\n\t\tconst chain = params.chain!.map((step) => {\n\t\t\tif (isParallelStep(step)) {\n\t\t\t\tconst parallel = step.parallel.map((task) => {\n\t\t\t\t\tconst normalized = normalize(task, flatIndex === 0 ? params.task : \"{previous}\");\n\t\t\t\t\tflatIndex++;\n\t\t\t\t\treturn normalized.input;\n\t\t\t\t});\n\t\t\t\treturn { ...step, parallel };\n\t\t\t}\n\t\t\tif (isDynamicParallelStep(step)) {\n\t\t\t\tconst normalized = normalize(step.parallel, \"{previous}\");\n\t\t\t\tconst reserved = step.expand.maxItems ?? options.dynamicFanoutMaxItems ?? 1;\n\t\t\t\tflatIndex += Math.max(1, reserved);\n\t\t\t\treturn { ...step, parallel: normalized.input };\n\t\t\t}\n\t\t\tconst normalized = normalize(step as SequentialStep, flatIndex === 0 ? params.task : \"{previous}\");\n\t\t\tflatIndex++;\n\t\t\treturn normalized.input;\n\t\t});\n\t\treturn { params: { ...params, chain }, agents };\n\t}\n\n\tconst normalized = normalize({\n\t\tagent: params.agent,\n\t\ttask: params.task ?? \"\",\n\t\tdescription: params.description,\n\t\tpermissions: params.permissions,\n\t\tcwd: params.cwd,\n\t\tmodel: params.model,\n\t\ttier: params.tier,\n\t\tskill: params.skill,\n\t\toutput: params.output,\n\t\toutputMode: params.outputMode,\n\t\tacceptance: params.acceptance,\n\t\ttoolBudget: params.toolBudget,\n\t});\n\treturn {\n\t\tparams: { ...params, agent: normalized.spec.childId },\n\t\tagents,\n\t};\n}\n\nfunction resolveForegroundTimeout(params: SubagentParamsLike): { timeoutMs?: number; error?: string } {\n\tconst rawTimeout = params.timeoutMs;\n\tconst rawMaxRuntime = params.maxRuntimeMs;\n\tif (rawTimeout === undefined && rawMaxRuntime === undefined) return {};\n\tfor (const [name, value] of [[\"timeoutMs\", rawTimeout], [\"maxRuntimeMs\", rawMaxRuntime]] as const) {\n\t\tif (value === undefined) continue;\n\t\tif (typeof value !== \"number\" || !Number.isInteger(value) || value <= 0) {\n\t\t\treturn { error: `${name} must be a positive integer.` };\n\t\t}\n\t}\n\tif (rawTimeout !== undefined && rawMaxRuntime !== undefined && rawTimeout !== rawMaxRuntime) {\n\t\treturn { error: \"timeoutMs and maxRuntimeMs are aliases; provide only one value or use the same value for both.\" };\n\t}\n\treturn { timeoutMs: rawTimeout ?? rawMaxRuntime };\n}\n\nfunction resolveToolBudget(raw: unknown, label = \"toolBudget\"): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tconst resolved = validateToolBudgetConfig(raw, label);\n\treturn { toolBudget: resolved.budget, error: resolved.error };\n}\n\nfunction resolveEffectiveToolBudget(input: { stepBudget?: ToolBudgetConfig; runBudget?: ResolvedToolBudget; agentBudget?: ToolBudgetConfig; configBudget?: ToolBudgetConfig }): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tif (input.stepBudget !== undefined) return resolveToolBudget(input.stepBudget, \"toolBudget\");\n\tif (input.runBudget !== undefined) return { toolBudget: input.runBudget };\n\tif (input.agentBudget !== undefined) return resolveToolBudget(input.agentBudget, \"agent.toolBudget\");\n\treturn resolveToolBudget(input.configBudget, \"config.toolBudget\");\n}\n\nfunction expandTopLevelTaskCounts(tasks: TaskParam[]): { tasks?: TaskParam[]; error?: string } {\n\tconst expanded: TaskParam[] = [];\n\tfor (let taskIndex = 0; taskIndex < tasks.length; taskIndex++) {\n\t\tconst task = tasks[taskIndex]!;\n\t\tconst rawCount = (task as TaskParam & { count?: unknown }).count;\n\t\tif (rawCount !== undefined && (typeof rawCount !== \"number\" || !Number.isInteger(rawCount) || rawCount < 1)) {\n\t\t\treturn { error: `tasks[${taskIndex}].count must be an integer >= 1` };\n\t\t}\n\t\tconst { count, ...concreteTask } = task;\n\t\tfor (let repeat = 0; repeat < (rawCount ?? 1); repeat++) {\n\t\t\texpanded.push({ ...concreteTask });\n\t\t}\n\t}\n\treturn { tasks: expanded };\n}\n\nfunction expandChainParallelCounts(chain: ChainStep[]): { chain?: ChainStep[]; error?: string } {\n\tconst expandedChain: ChainStep[] = [];\n\tfor (let stepIndex = 0; stepIndex < chain.length; stepIndex++) {\n\t\tconst step = chain[stepIndex]!;\n\t\tif (!isParallelStep(step)) {\n\t\t\texpandedChain.push(step);\n\t\t\tcontinue;\n\t\t}\n\t\tconst expandedParallel = [];\n\t\tfor (let taskIndex = 0; taskIndex < step.parallel.length; taskIndex++) {\n\t\t\tconst task = step.parallel[taskIndex]!;\n\t\t\tconst rawCount = (task as typeof task & { count?: unknown }).count;\n\t\t\tif (rawCount !== undefined && (typeof rawCount !== \"number\" || !Number.isInteger(rawCount) || rawCount < 1)) {\n\t\t\t\treturn { error: `chain[${stepIndex}].parallel[${taskIndex}].count must be an integer >= 1` };\n\t\t\t}\n\t\t\tconst { count, ...concreteTask } = task;\n\t\t\tfor (let repeat = 0; repeat < (rawCount ?? 1); repeat++) {\n\t\t\t\texpandedParallel.push({ ...concreteTask });\n\t\t\t}\n\t\t}\n\t\texpandedChain.push({ ...step, parallel: expandedParallel });\n\t}\n\treturn { chain: expandedChain };\n}\n\nfunction normalizeRepeatedParallelCounts(params: SubagentParamsLike): { params?: SubagentParamsLike; error?: AgentToolResult<Details> } {\n\tif (params.tasks) {\n\t\tconst expandedTasks = expandTopLevelTaskCounts(params.tasks);\n\t\tif (expandedTasks.error) {\n\t\t\treturn { error: buildRequestedModeError(params, expandedTasks.error) };\n\t\t}\n\t\treturn { params: { ...params, tasks: expandedTasks.tasks } };\n\t}\n\tif (params.chain) {\n\t\tconst expandedChain = expandChainParallelCounts(params.chain);\n\t\tif (expandedChain.error) {\n\t\t\treturn { error: buildRequestedModeError(params, expandedChain.error) };\n\t\t}\n\t\treturn { params: { ...params, chain: expandedChain.chain } };\n\t}\n\treturn { params };\n}\n\nfunction withForkContext(\n\tresult: AgentToolResult<Details>,\n\tcontext: SubagentParamsLike[\"context\"],\n): AgentToolResult<Details> {\n\tif (context !== \"fork\" || !result.details) return result;\n\treturn {\n\t\t...result,\n\t\tdetails: {\n\t\t\t...result.details,\n\t\t\tcontext: \"fork\",\n\t\t},\n\t};\n}\n\nfunction withForkThinkingNotes(\n\tresult: AgentToolResult<Details>,\n\tdowngrades: Map<number, string>,\n): AgentToolResult<Details> {\n\tif (downgrades.size === 0) return result;\n\tconst children = [...downgrades.entries()]\n\t\t.sort(([a], [b]) => a - b)\n\t\t.map(([index, agent]) => `${agent} (child ${index})`)\n\t\t.join(\", \");\n\tconst note = `Note: fork context forced thinking off for ${children}. The forked transcript contained signed Anthropic thinking blocks that were sanitized, and Anthropic children cannot resume such a transcript with thinking enabled. Use context: \"fresh\" when an Anthropic child needs thinking.`;\n\treturn { ...result, content: [...result.content, { type: \"text\", text: note }] };\n}\n\nfunction toExecutionErrorResult(params: SubagentParamsLike, error: unknown): AgentToolResult<Details> {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn withForkContext(\n\t\t{\n\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: getRequestedModeLabel(params), results: [] },\n\t\t},\n\t\tparams.context,\n\t);\n}\n\nfunction collectChainSessionFiles(\n\tchain: ChainStep[],\n\tsessionFileForTask: ForkSessionFileForTask,\n\tdynamicFanoutMaxItems?: number,\n): (string | undefined)[] {\n\tconst sessionFiles: (string | undefined)[] = [];\n\tlet flatIndex = 0;\n\tfor (const step of chain) {\n\t\tif (isParallelStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tsessionFiles.push(sessionFileForTask(task.agent, flatIndex, task.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\tconst maxItems = step.expand.maxItems ?? dynamicFanoutMaxItems ?? 0;\n\t\t\tfor (let itemIndex = 0; itemIndex < maxItems; itemIndex++) {\n\t\t\t\tsessionFiles.push(sessionFileForTask(step.parallel.agent, flatIndex, step.parallel.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\tsessionFiles.push(sessionFileForTask(sequential.agent, flatIndex, sequential.model));\n\t\tflatIndex++;\n\t}\n\treturn sessionFiles;\n}\n\nfunction collectChainThinkingOverrides(\n\tchain: ChainStep[],\n\tthinkingOverrideForTask: ForkThinkingOverrideForTask,\n\tdynamicFanoutMaxItems?: number,\n): (ChildRuntimeConfig[\"thinking\"] | undefined)[] {\n\tconst thinkingOverrides: (ChildRuntimeConfig[\"thinking\"] | undefined)[] = [];\n\tlet flatIndex = 0;\n\tfor (const step of chain) {\n\t\tif (isParallelStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tthinkingOverrides.push(thinkingOverrideForTask(task.agent, flatIndex, task.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\tconst maxItems = step.expand.maxItems ?? dynamicFanoutMaxItems ?? 0;\n\t\t\tfor (let itemIndex = 0; itemIndex < maxItems; itemIndex++) {\n\t\t\t\tthinkingOverrides.push(thinkingOverrideForTask(step.parallel.agent, flatIndex, step.parallel.model));\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\tthinkingOverrides.push(thinkingOverrideForTask(sequential.agent, flatIndex, sequential.model));\n\t\tflatIndex++;\n\t}\n\treturn thinkingOverrides;\n}\n\nfunction firstChainAgent(chain: ChainStep[]): string | undefined {\n\tconst first = chain[0];\n\tif (!first) return undefined;\n\tif (isParallelStep(first)) return first.parallel[0]?.agent;\n\tif (isDynamicParallelStep(first)) return first.parallel.agent;\n\treturn (first as SequentialStep).agent;\n}\n\nfunction firstRawChainTask(chain: ChainStep[]): string | undefined {\n\tconst first = chain[0];\n\tif (!first) return undefined;\n\tif (isParallelStep(first)) return first.parallel[0]?.task;\n\tif (isDynamicParallelStep(first)) return first.parallel.task;\n\treturn (first as SequentialStep).task;\n}\n\nfunction resolveAsyncEventGoal(workflowTask: string | undefined, rawChain: ChainStep[], unwrapForkFallback = false): string {\n\tif (workflowTask?.trim()) return workflowTask;\n\tconst fallback = firstRawChainTask(rawChain) || \"\";\n\tif (!unwrapForkFallback) return fallback;\n\tconst forkPrefix = `${DEFAULT_FORK_PREAMBLE}\\n\\nTask:\\n`;\n\treturn fallback.startsWith(forkPrefix) ? fallback.slice(forkPrefix.length) : fallback;\n}\n\nfunction wrapChainTasksForFork(chain: ChainStep[], contextPolicy: AgentDefaultContextPolicy): ChainStep[] {\n\treturn chain.map((step, stepIndex) => {\n\t\tif (isParallelStep(step)) {\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tparallel: step.parallel.map((task) => ({\n\t\t\t\t\t...task,\n\t\t\t\t\ttask: shouldForkAgent(contextPolicy, task.agent)\n\t\t\t\t\t\t? wrapForkTask(task.task ?? \"{previous}\")\n\t\t\t\t\t\t: task.task,\n\t\t\t\t})),\n\t\t\t};\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tparallel: {\n\t\t\t\t\t...step.parallel,\n\t\t\t\t\ttask: shouldForkAgent(contextPolicy, step.parallel.agent)\n\t\t\t\t\t\t? wrapForkTask(step.parallel.task ?? \"{previous}\")\n\t\t\t\t\t\t: step.parallel.task,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\treturn {\n\t\t\t...sequential,\n\t\t\ttask: shouldForkAgent(contextPolicy, sequential.agent)\n\t\t\t\t? wrapForkTask(sequential.task ?? (stepIndex === 0 ? \"{task}\" : \"{previous}\"))\n\t\t\t\t: sequential.task,\n\t\t};\n\t});\n}\n\nfunction preflightForkSessionsForStaticTasks(\n\tparams: SubagentParamsLike,\n\tcontextPolicy: AgentDefaultContextPolicy,\n\tsessionFileForTask: ForkSessionFileForTask,\n\tdynamicFanoutMaxItems?: number,\n): void {\n\tif (!contextPolicy.usesFork) return;\n\tif (params.agent) {\n\t\tif (shouldForkAgent(contextPolicy, params.agent)) sessionFileForTask(params.agent, 0, params.model);\n\t\treturn;\n\t}\n\tif (params.tasks) {\n\t\tparams.tasks.forEach((task, index) => {\n\t\t\tif (shouldForkAgent(contextPolicy, task.agent)) sessionFileForTask(task.agent, index, task.model);\n\t\t});\n\t\treturn;\n\t}\n\tif (!params.chain?.length) return;\n\tlet flatIndex = 0;\n\tfor (const step of params.chain) {\n\t\tif (isParallelStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tif (shouldForkAgent(contextPolicy, task.agent)) sessionFileForTask(task.agent, flatIndex, task.model);\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (isDynamicParallelStep(step)) {\n\t\t\tconst maxItems = step.expand.maxItems ?? dynamicFanoutMaxItems ?? 0;\n\t\t\tif (shouldForkAgent(contextPolicy, step.parallel.agent)) {\n\t\t\t\tfor (let itemIndex = 0; itemIndex < maxItems; itemIndex++) sessionFileForTask(step.parallel.agent, flatIndex + itemIndex, step.parallel.model);\n\t\t\t}\n\t\t\tflatIndex += maxItems;\n\t\t\tcontinue;\n\t\t}\n\t\tconst sequential = step as SequentialStep;\n\t\tif (shouldForkAgent(contextPolicy, sequential.agent)) sessionFileForTask(sequential.agent, flatIndex, sequential.model);\n\t\tflatIndex++;\n\t}\n}\n\nfunction runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentToolResult<Details> | null {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tshareEnabled,\n\t\tsessionRoot,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactConfig,\n\t\tartifactsDir,\n\t\teffectiveAsync,\n\t\tcontrolConfig,\n\t\tintercomBridge,\n\t\tnestedRoute,\n\t\tcontextPolicy,\n\t} = data;\n\tconst hasChain = (params.chain?.length ?? 0) > 0;\n\tconst hasTasks = (params.tasks?.length ?? 0) > 0;\n\tconst hasSingle = !hasChain && !hasTasks && Boolean(params.agent);\n\tif (!effectiveAsync) return null;\n\n\tif (hasChain && params.chain) {\n\t\tconst chainWorktreeTaskCwdError = buildChainWorktreeTaskCwdError(params.chain as ChainStep[], effectiveCwd);\n\t\tif (chainWorktreeTaskCwdError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: chainWorktreeTaskCwdError }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t}\n\n\tif (hasTasks && params.tasks) {\n\t\tconst maxParallelTasks = resolveTopLevelParallelMaxTasks(deps.config.parallel?.maxTasks);\n\t\tif (params.tasks.length > maxParallelTasks) {\n\t\t\treturn buildParallelModeError(`Max ${maxParallelTasks} tasks`);\n\t\t}\n\t\tif (params.worktree) {\n\t\t\tconst worktreeTaskCwdError = buildParallelWorktreeTaskCwdError(params.tasks, effectiveCwd);\n\t\t\tif (worktreeTaskCwdError) return buildParallelModeError(worktreeTaskCwdError);\n\t\t}\n\t}\n\n\tif (!isAsyncAvailable()) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: \"Async mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t};\n\t}\n\tconst id = randomUUID();\n\tconst asyncCtx = {\n\t\tpi: deps.pi,\n\t\tcwd: ctx.cwd,\n\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\tcurrentModelProvider: ctx.model?.provider,\n\t\tcurrentModel: ctx.model,\n\t\tmodelScope: data.modelScope,\n\t};\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst currentProvider = ctx.model?.provider;\n\tconst controlIntercomTarget = intercomBridge.active ? intercomBridge.orchestratorTarget : undefined;\n\tconst childIntercomTarget = intercomBridge.active ? (agent: string, index: number) => resolveSubagentIntercomTarget(id, agent, index) : undefined;\n\n\tif (hasTasks && params.tasks) {\n\t\tconst skillOverrides = params.tasks.map((task) => normalizeSkillInput(task.skill));\n\t\tconst parallelTasks = params.tasks.map((task, index) => ({\n\t\t\tagent: task.agent,\n\t\t\ttask: shouldForkAgent(contextPolicy, task.agent) ? wrapForkTask(task.task) : task.task,\n\t\t\tcwd: task.cwd,\n\t\t\t...(task.model !== undefined ? { model: task.model } : {}),\n\t\t\t...(skillOverrides[index] !== undefined ? { skill: skillOverrides[index] } : {}),\n\t\t\t...(task.output !== undefined && task.output !== true ? { output: task.output } : {}),\n\t\t\t...(task.outputMode !== undefined ? { outputMode: task.outputMode } : {}),\n\t\t\t...(task.reads !== undefined && task.reads !== true ? { reads: task.reads } : {}),\n\t\t\t...(task.progress !== undefined ? { progress: task.progress } : {}),\n\t\t\t...(task.toolBudget !== undefined ? { toolBudget: task.toolBudget } : {}),\n\t\t\t...(task.acceptance !== undefined ? { acceptance: task.acceptance } : {}),\n\t\t}));\n\t\treturn executeAsyncChain(id, {\n\t\t\tchain: [{\n\t\t\t\tparallel: parallelTasks,\n\t\t\t\tconcurrency: resolveTopLevelParallelConcurrency(params.concurrency, deps.config.parallel?.concurrency),\n\t\t\t\tworktree: params.worktree,\n\t\t\t}],\n\t\t\tresultMode: \"parallel\",\n\t\t\tgoal: params.tasks[0]?.task ?? \"\",\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tchainSkills: [],\n\t\t\tsessionFilesByFlatIndex: params.tasks.map((task, index) => sessionFileForTask(task.agent, index, task.model)),\n\t\t\tthinkingOverridesByFlatIndex: params.tasks.map((task, index) => thinkingOverrideForTask(task.agent, index, task.model)),\n\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget,\n\t\t\tchildIntercomTarget,\n\t\t\tnestedRoute,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t});\n\t}\n\n\tif (hasChain && params.chain) {\n\t\tconst normalized = normalizeSkillInput(params.skill);\n\t\tconst chainSkills = normalized === false ? [] : (normalized ?? []);\n\t\tconst rawChain = params.chain as ChainStep[];\n\t\tconst chain = wrapChainTasksForFork(rawChain, contextPolicy);\n\t\treturn executeAsyncChain(id, {\n\t\t\tchain,\n\t\t\ttask: params.task,\n\t\t\tgoal: resolveAsyncEventGoal(params.task, rawChain),\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tchainSkills,\n\t\t\tsessionFilesByFlatIndex: collectChainSessionFiles(chain, sessionFileForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tthinkingOverridesByFlatIndex: collectChainThinkingOverrides(chain, thinkingOverrideForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget,\n\t\t\tchildIntercomTarget,\n\t\t\tnestedRoute,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t});\n\t}\n\n\tif (hasSingle) {\n\t\tconst a = agents.find((x) => x.name === params.agent);\n\t\tif (!a) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${params.agent}` }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tconst rawOutput = params.output !== undefined ? params.output : a.output;\n\t\tconst effectiveOutput = normalizeSingleOutputOverride(rawOutput, a.output);\n\t\tconst effectiveOutputMode = params.outputMode ?? \"inline\";\n\t\tconst normalizedSkills = normalizeSkillInput(params.skill);\n\t\tconst skills = normalizedSkills === false ? [] : normalizedSkills;\n\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(currentMaxSubagentDepth, a.maxSubagentDepth);\n\t\t// lunr: model tiers — explicit model wins; otherwise resolve params.tier via the tier bridge.\n\t\tconst modelOverride = resolveEffectiveSubagentModel((params.model as string | undefined) ?? resolveTierModelOverride(params.tier), a.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope });\n\t\tconst spec = normalizeChildSpec({\n\t\t\ttask: shouldForkAgent(contextPolicy, params.agent!) ? wrapForkTask(params.task ?? \"\") : (params.task ?? \"\"),\n\t\t\tdescription: params.description,\n\t\t\tpermissions: params.permissions,\n\t\t\tmodel: modelOverride,\n\t\t\ttier: params.tier,\n\t\t\tskill: params.skill,\n\t\t\tcwd: effectiveCwd,\n\t\t\toutput: effectiveOutput,\n\t\t\toutputMode: effectiveOutputMode,\n\t\t\tacceptance: params.acceptance,\n\t\t\ttoolBudget: params.toolBudget,\n\t\t}, {\n\t\t\tparentMode: snapshotParentPermissionMode(deps.state.currentSessionId),\n\t\t\trunId: id,\n\t\t\tindex: 0,\n\t\t\tchildId: params.agent,\n\t\t});\n\t\treturn executeAsyncSingle(id, {\n\t\t\tspec,\n\t\t\tgoal: params.task ?? \"\",\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels,\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tsessionFile: sessionFileForTask(params.agent!, 0, modelOverride),\n\t\t\tskills,\n\t\t\toutput: effectiveOutput,\n\t\t\toutputMode: effectiveOutputMode,\n\t\t\toutputBaseDir: resolveSingleRunOutputBaseDir(deps, artifactsDir, id),\n\t\t\tmodelOverride,\n\t\t\tthinkingOverride: thinkingOverrideForTask(params.agent!, 0, modelOverride),\n\t\t\tmaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget,\n\t\t\tchildIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(agent, index) : undefined,\n\t\t\tnestedRoute,\n\t\t\tacceptance: params.acceptance,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t});\n\t}\n\n\treturn null;\n}\n\nasync function runChainPath(data: ExecutionContextData, deps: ExecutorDeps): Promise<AgentToolResult<Details>> {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tonUpdate,\n\t\tsessionRoot,\n\t\tcontrolConfig,\n\t\tcontextPolicy,\n\t} = data;\n\tconst onControlEvent = createForegroundControlNotifier(data, deps);\n\tconst childIntercomTarget = data.intercomBridge.active ? resolveSubagentIntercomTarget : undefined;\n\tconst foregroundControl = deps.state.foregroundControls.get(runId);\n\tconst normalized = normalizeSkillInput(params.skill);\n\tconst chainSkills = normalized === false ? [] : (normalized ?? []);\n\tconst chain = wrapChainTasksForFork(params.chain as ChainStep[], contextPolicy);\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst chainResult = await executeChain({\n\t\tchain,\n\t\ttask: params.task,\n\t\tagents,\n\t\tctx,\n\t\tmodelScope: data.modelScope,\n\t\tintercomEvents: deps.pi.events,\n\t\tsignal,\n\t\trunId,\n\t\tcwd: effectiveCwd,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tincludeProgress: params.includeProgress,\n\t\tclarify: params.clarify,\n\t\tonUpdate,\n\t\tonControlEvent,\n\t\tcontrolConfig,\n\t\tchildIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(runId, agent, index) : undefined,\n\t\torchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\tforegroundControl,\n\t\tnestedRoute: foregroundControl?.nestedRoute,\n\t\tchainSkills,\n\t\tchainDir: params.chainDir ?? getProjectChainRunsDir(effectiveCwd),\n\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\ttimeoutMs: data.timeoutMs,\n\t\tdeadlineAt: data.deadlineAt,\n\t\tturnBudget: data.turnBudget,\n\t\tonDetachedExit: (index, result) => updateRememberedForegroundChild(deps.state, { runId, mode: \"chain\", cwd: effectiveCwd, sessionId: data.parentSessionId, index, result, events: deps.pi.events }),\n\t\ttoolBudget: data.toolBudget,\n\t\tconfigToolBudget: data.configToolBudget,\n\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t});\n\n\tif (chainResult.requestedAsync) {\n\t\tif (!isAsyncAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"chain\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tconst id = randomUUID();\n\t\tconst asyncCtx = {\n\t\t\tpi: deps.pi,\n\t\t\tcwd: ctx.cwd,\n\t\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\tcurrentModelProvider: ctx.model?.provider,\n\t\t\tcurrentModel: ctx.model,\n\t\t\tmodelScope: data.modelScope,\n\t\t};\n\t\tconst rawAsyncChain = chainResult.requestedAsync.chain;\n\t\tconst asyncChain = wrapChainTasksForFork(rawAsyncChain, contextPolicy);\n\t\tconst firstAgent = firstChainAgent(rawAsyncChain);\n\t\treturn executeAsyncChain(id, {\n\t\t\tchain: asyncChain,\n\t\t\ttask: params.task,\n\t\t\tgoal: resolveAsyncEventGoal(params.task, rawAsyncChain, firstAgent ? shouldForkAgent(contextPolicy, firstAgent) : false),\n\t\t\tctx: asyncCtx,\n\t\t\tavailableModels: ctx.modelRegistry.getAvailable().map(toModelInfo),\n\t\t\tcwd: effectiveCwd,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\tartifactConfig,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tchainSkills: chainResult.requestedAsync.chainSkills,\n\t\t\tsessionFilesByFlatIndex: collectChainSessionFiles(asyncChain, sessionFileForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tthinkingOverridesByFlatIndex: collectChainThinkingOverrides(asyncChain, thinkingOverrideForTask, deps.config.chain?.dynamicFanout?.maxItems),\n\t\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\tcontrolConfig,\n\t\t\tcontrolIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\tchildIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,\n\t\t\tnestedRoute: data.nestedRoute,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudget: data.toolBudget,\n\t\t\tconfigToolBudget: data.configToolBudget,\n\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t});\n\t}\n\n\tconst rawChainDetails = chainResult.details ? { ...chainResult.details, runId } : undefined;\n\tif (foregroundControl && rawChainDetails) {\n\t\tupdateForegroundNestedProjection(foregroundControl);\n\t\tattachRootChildrenToSteps(runId, rawChainDetails.results, foregroundControl.nestedChildren);\n\t\trawChainDetails.totalCost = sumResultsCost(rawChainDetails.results);\n\t}\n\tconst chainDetails = rawChainDetails ? compactForegroundDetails(rawChainDetails) : undefined;\n\tif (chainDetails) rememberForegroundRun(deps.state, { runId, mode: \"chain\", cwd: effectiveCwd, sessionId: data.parentSessionId, results: chainDetails.results });\n\tconst intercomReceipt = chainDetails && !chainDetails.results.some((result) => result.interrupted || result.detached)\n\t\t? await maybeBuildForegroundIntercomReceipt({\n\t\t\tpi: deps.pi,\n\t\t\tintercomBridge: data.intercomBridge,\n\t\t\trunId,\n\t\t\tmode: \"chain\",\n\t\t\tdetails: chainDetails,\n\t\t\t...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),\n\t\t})\n\t\t: null;\n\tif (intercomReceipt) {\n\t\treturn {\n\t\t\t...chainResult,\n\t\t\tcontent: [{ type: \"text\", text: intercomReceipt.text }],\n\t\t\tdetails: intercomReceipt.details,\n\t\t};\n\t}\n\n\treturn chainDetails ? { ...chainResult, details: chainDetails } : chainResult;\n}\n\ninterface ForegroundParallelRunInput {\n\ttasks: TaskParam[];\n\ttaskTexts: string[];\n\tagents: ChildRuntimeConfig[];\n\tctx: ExtensionContext;\n\tstate: SubagentState;\n\tintercomEvents: IntercomEventBus;\n\tparentSessionId: string | null;\n\tsignal: AbortSignal;\n\trunId: string;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex: (idx?: number) => string | undefined;\n\tsessionFileForTask: ForkSessionFileForTask;\n\tthinkingOverrideForTask: ForkThinkingOverrideForTask;\n\tshareEnabled: boolean;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\toutputBaseDir: string;\n\tmaxOutput?: MaxOutputConfig;\n\tparamsCwd: string;\n\tprogressDir: string;\n\tmaxSubagentDepths: number[];\n\twaitToolEnabled?: boolean;\n\tavailableModels: ModelInfo[];\n\tmodelScope?: ModelScopeConfig;\n\tmodelOverrides: (string | undefined)[];\n\tbehaviors: Array<ReturnType<typeof resolveStepBehavior>>;\n\tfirstProgressIndex: number;\n\tcontrolConfig: ResolvedControlConfig;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: SubagentState[\"foregroundControls\"] extends Map<string, infer T> ? T : never;\n\tconcurrencyLimit: number;\n\tglobalSemaphore?: Semaphore;\n\tliveResults: (SingleResult | undefined)[];\n\tliveProgress: (AgentProgress | undefined)[];\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tworktreeSetup?: WorktreeSetup;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\ttoolBudgets: (ResolvedToolBudget | undefined)[];\n}\n\nfunction buildParallelModeError(message: string): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tisError: true,\n\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t};\n}\n\nfunction createParallelWorktreeSetup(\n\tenabled: boolean | undefined,\n\tcwd: string,\n\trunId: string,\n\ttasks: TaskParam[],\n\tsetupHook: ExtensionConfig[\"worktreeSetupHook\"],\n\tsetupHookTimeoutMs: ExtensionConfig[\"worktreeSetupHookTimeoutMs\"],\n\tbaseDir: ExtensionConfig[\"worktreeBaseDir\"],\n): { setup?: WorktreeSetup; errorResult?: AgentToolResult<Details> } {\n\tif (!enabled) return {};\n\ttry {\n\t\treturn {\n\t\t\tsetup: createWorktrees(cwd, runId, tasks.length, {\n\t\t\t\tagents: tasks.map((task) => task.agent),\n\t\t\t\tsetupHook: setupHook\n\t\t\t\t\t? { hookPath: setupHook, timeoutMs: setupHookTimeoutMs }\n\t\t\t\t\t: undefined,\n\t\t\t\tbaseDir,\n\t\t\t}),\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { errorResult: buildParallelModeError(message) };\n\t}\n}\n\nfunction buildParallelWorktreeTaskCwdError(\n\ttasks: ReadonlyArray<{ agent: string; cwd?: string }>,\n\tsharedCwd: string,\n): string | undefined {\n\tconst conflict = findWorktreeTaskCwdConflict(tasks, sharedCwd);\n\tif (!conflict) return undefined;\n\treturn formatWorktreeTaskCwdConflict(conflict, sharedCwd);\n}\n\nfunction resolveSingleRunOutputBaseDir(deps: ExecutorDeps, artifactsDir: string, runId: string): string {\n\treturn deps.config.singleRunOutputBaseDir\n\t\t? path.resolve(deps.expandTilde(deps.config.singleRunOutputBaseDir))\n\t\t: path.join(artifactsDir, \"outputs\", runId);\n}\n\nfunction buildChainWorktreeTaskCwdError(chain: ChainStep[], sharedCwd: string): string | undefined {\n\tfor (let stepIndex = 0; stepIndex < chain.length; stepIndex++) {\n\t\tconst step = chain[stepIndex]!;\n\t\tif (!isParallelStep(step) || !step.worktree) continue;\n\t\tconst stepCwd = resolveChildCwd(sharedCwd, step.cwd);\n\t\tconst conflict = findWorktreeTaskCwdConflict(step.parallel, stepCwd);\n\t\tif (!conflict) continue;\n\t\tconst detail = formatWorktreeTaskCwdConflict(conflict, stepCwd);\n\t\treturn `parallel chain step ${stepIndex + 1}: ${detail}`;\n\t}\n\treturn undefined;\n}\n\nfunction resolveParallelTaskCwd(\n\ttask: TaskParam,\n\tparamsCwd: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\tindex: number,\n): string {\n\tif (worktreeSetup) return worktreeSetup.worktrees[index]!.agentCwd;\n\treturn resolveChildCwd(paramsCwd, task.cwd);\n}\n\nfunction buildParallelWorktreeSuffix(\n\tworktreeSetup: WorktreeSetup | undefined,\n\tartifactsDir: string,\n\ttasks: TaskParam[],\n): string {\n\tif (!worktreeSetup) return \"\";\n\tconst diffsDir = path.join(artifactsDir, \"worktree-diffs\");\n\tconst diffs = diffWorktrees(worktreeSetup, tasks.map((task) => task.agent), diffsDir);\n\treturn formatWorktreeDiffSummary(diffs);\n}\n\nfunction findDuplicateParallelOutputPath(input: {\n\ttasks: TaskParam[];\n\tbehaviors: ResolvedStepBehavior[];\n\tparamsCwd: string;\n\tctxCwd: string;\n\toutputBaseDir: string;\n\tworktreeSetup?: WorktreeSetup;\n}): string | undefined {\n\tconst seen = new Map<string, { index: number; agent: string }>();\n\tfor (let index = 0; index < input.tasks.length; index++) {\n\t\tconst behavior = input.behaviors[index];\n\t\tif (!behavior?.output) continue;\n\t\tconst task = input.tasks[index]!;\n\t\tconst taskCwd = resolveParallelTaskCwd(task, input.paramsCwd, input.worktreeSetup, index);\n\t\tconst outputPath = resolveSingleOutputPath(behavior.output, input.ctxCwd, taskCwd, input.outputBaseDir);\n\t\tif (!outputPath) continue;\n\t\tconst previous = seen.get(outputPath);\n\t\tif (previous) {\n\t\t\treturn `Parallel tasks ${previous.index + 1} (${previous.agent}) and ${index + 1} (${task.agent}) resolve output to the same path: ${outputPath}. Use distinct output paths.`;\n\t\t}\n\t\tseen.set(outputPath, { index, agent: task.agent });\n\t}\n\treturn undefined;\n}\n\nasync function runForegroundParallelTasks(input: ForegroundParallelRunInput): Promise<SingleResult[]> {\n\t// Pre-warm fork session files sequentially before concurrent dispatch to avoid\n\t// races where multiple workers simultaneously try to branch the same parent session.\n\tfor (let i = 0; i < input.tasks.length; i++) {\n\t\tinput.sessionFileForTask(input.tasks[i]!.agent, i, input.modelOverrides[i]);\n\t}\n\treturn mapConcurrent(input.tasks, input.concurrencyLimit, async (task, index) => {\n\t\tconst behavior = input.behaviors[index];\n\t\tconst effectiveSkills = behavior?.skills;\n\t\tconst taskCwd = resolveParallelTaskCwd(task, input.paramsCwd, input.worktreeSetup, index);\n\t\tconst readInstructions = behavior\n\t\t\t? buildChainInstructions({ ...behavior, output: false, progress: false }, taskCwd, false)\n\t\t\t: { prefix: \"\", suffix: \"\" };\n\t\tconst progressInstructions = behavior\n\t\t\t? buildChainInstructions({ ...behavior, output: false, reads: false }, input.progressDir, index === input.firstProgressIndex)\n\t\t\t: { prefix: \"\", suffix: \"\" };\n\t\tconst outputPath = resolveSingleOutputPath(behavior?.output, input.ctx.cwd, taskCwd, input.outputBaseDir);\n\t\tconst agentConfig = input.agents.find((agent) => agent.name === task.agent);\n\t\tconst taskText = injectSingleOutputInstruction(\n\t\t\t`${readInstructions.prefix}${input.taskTexts[index]!}${progressInstructions.suffix}`,\n\t\t\toutputPath,\n\t\t\tagentConfig,\n\t\t);\n\t\tconst interruptController = new AbortController();\n\t\tif (input.foregroundControl) {\n\t\t\tinput.foregroundControl.currentAgent = task.description || task.agent;\n\t\t\tinput.foregroundControl.currentChildId = task.agent;\n\t\t\tinput.foregroundControl.currentIndex = index;\n\t\t\tinput.foregroundControl.currentActivityState = undefined;\n\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\tinput.foregroundControl.interrupt = () => {\n\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\tinterruptController.abort();\n\t\t\t\tinput.foregroundControl!.currentActivityState = undefined;\n\t\t\t\tinput.foregroundControl!.updatedAt = Date.now();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\t\treturn runSync(input.ctx.cwd, normalizeChildSpec({\n\t\t\ttask: taskText,\n\t\t\tdescription: task.description,\n\t\t\tpermissions: task.permissions,\n\t\t\tmodel: input.modelOverrides[index] ?? task.model,\n\t\t\tskill: task.skill,\n\t\t\tcwd: taskCwd,\n\t\t\toutput: task.output,\n\t\t\toutputMode: task.outputMode,\n\t\t\tacceptance: task.acceptance,\n\t\t\ttoolBudget: task.toolBudget,\n\t\t}, { parentMode: snapshotParentPermissionMode(input.ctx.sessionManager.getSessionId() ?? undefined), runId: input.runId, index }), {\n\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\tcwd: taskCwd,\n\t\t\tsignal: input.signal,\n\t\t\tinterruptSignal: interruptController.signal,\n\t\t\tallowIntercomDetach: agentConfig?.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\tintercomEvents: input.intercomEvents,\n\t\t\trunId: input.runId,\n\t\t\tindex,\n\t\t\tsessionDir: input.sessionDirForIndex(index),\n\t\t\tsessionFile: input.sessionFileForTask(task.agent, index, input.modelOverrides[index]),\n\t\t\tshare: input.shareEnabled,\n\t\t\tartifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,\n\t\t\tartifactConfig: input.artifactConfig,\n\t\t\tmaxOutput: input.maxOutput,\n\t\t\toutputPath,\n\t\t\toutputMode: behavior?.outputMode,\n\t\t\tmaxSubagentDepth: input.maxSubagentDepths[index],\n\t\t\twaitToolEnabled: input.waitToolEnabled,\n\t\t\tcontrolConfig: input.controlConfig,\n\t\t\tonControlEvent: input.onControlEvent,\n\t\t\tonDetachedExit: (result) => updateRememberedForegroundChild(input.state, { runId: input.runId, mode: \"parallel\", cwd: taskCwd, sessionId: input.parentSessionId, index, result, events: input.intercomEvents }),\n\t\t\tintercomSessionName: input.childIntercomTarget?.(task.agent, index),\n\t\t\torchestratorIntercomTarget: input.orchestratorIntercomTarget,\n\t\t\tnestedRoute: input.foregroundControl?.nestedRoute,\n\t\t\tmodelOverride: input.modelOverrides[index],\n\t\t\tthinkingOverride: input.thinkingOverrideForTask(task.agent, index, input.modelOverrides[index]),\n\t\t\tavailableModels: input.availableModels,\n\t\t\tpreferredModelProvider: input.ctx.model?.provider,\n\t\t\tmodelScope: input.modelScope,\n\t\t\tskills: effectiveSkills === false ? [] : effectiveSkills,\n\t\t\tacceptance: task.acceptance,\n\t\t\tacceptanceContext: { mode: \"parallel\" },\n\t\t\ttimeoutMs: input.timeoutMs,\n\t\t\tdeadlineAt: input.deadlineAt,\n\t\t\tturnBudget: input.turnBudget,\n\t\t\ttoolBudget: input.toolBudgets[index],\n\t\t\tonUpdate: input.onUpdate\n\t\t\t\t? (progressUpdate) => {\n\t\t\t\t\tconst stepResults = progressUpdate.details?.results || [];\n\t\t\t\t\tconst stepProgress = progressUpdate.details?.progress || [];\n\t\t\t\t\tif (input.foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\tconst current = stepProgress[0];\n\t\t\t\t\t\tinput.foregroundControl.currentAgent = task.description || task.agent;\n\t\t\t\t\t\tinput.foregroundControl.currentChildId = task.agent;\n\t\t\t\t\t\tinput.foregroundControl.currentIndex = index;\n\t\t\t\t\t\tinput.foregroundControl.currentActivityState = current?.activityState;\n\t\t\t\t\t\tinput.foregroundControl.lastActivityAt = current?.lastActivityAt;\n\t\t\t\t\t\tinput.foregroundControl.currentTool = current?.currentTool;\n\t\t\t\t\t\tinput.foregroundControl.currentToolStartedAt = current?.currentToolStartedAt;\n\t\t\t\t\t\tinput.foregroundControl.currentPath = current?.currentPath;\n\t\t\t\t\t\tinput.foregroundControl.turnCount = current?.turnCount;\n\t\t\t\t\t\tinput.foregroundControl.tokens = current?.tokens;\n\t\t\t\t\t\tinput.foregroundControl.toolCount = current?.toolCount;\n\t\t\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t\tif (stepResults.length > 0) input.liveResults[index] = stepResults[0];\n\t\t\t\t\tif (stepProgress.length > 0) input.liveProgress[index] = stepProgress[0];\n\t\t\t\t\tconst mergedResults = input.liveResults.filter((result): result is SingleResult => result !== undefined);\n\t\t\t\t\tconst mergedProgress = input.liveProgress.filter((progress): progress is AgentProgress => progress !== undefined);\n\t\t\t\t\tinput.onUpdate?.({\n\t\t\t\t\t\tcontent: progressUpdate.content,\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\tmode: \"parallel\",\n\t\t\t\t\t\t\tresults: mergedResults,\n\t\t\t\t\t\t\tprogress: mergedProgress,\n\t\t\t\t\t\t\tcontrolEvents: progressUpdate.details?.controlEvents,\n\t\t\t\t\t\t\ttotalSteps: input.tasks.length,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t}).finally(() => {\n\t\t\tif (input.foregroundControl?.currentIndex === index) {\n\t\t\t\tinput.foregroundControl.interrupt = undefined;\n\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t}\n\t\t});\n\t}, input.globalSemaphore);\n}\n\nasync function runParallelPath(data: ExecutionContextData, deps: ExecutorDeps): Promise<AgentToolResult<Details>> {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tshareEnabled,\n\t\tartifactConfig,\n\t\tartifactsDir,\n\t\tbackgroundRequestedWhileClarifying,\n\t\tonUpdate,\n\t\tsessionRoot,\n\t\tcontrolConfig,\n\t\tcontextPolicy,\n\t} = data;\n\tconst onControlEvent = createForegroundControlNotifier(data, deps);\n\tconst childIntercomTarget = data.intercomBridge.active ? resolveSubagentIntercomTarget : undefined;\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\tconst tasks = params.tasks!;\n\tconst maxParallelTasks = resolveTopLevelParallelMaxTasks(deps.config.parallel?.maxTasks);\n\tconst parallelConcurrency = resolveTopLevelParallelConcurrency(params.concurrency, deps.config.parallel?.concurrency);\n\n\tif (tasks.length > maxParallelTasks)\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Max ${maxParallelTasks} tasks` }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t};\n\n\tconst agentConfigs: ChildRuntimeConfig[] = [];\n\tfor (const t of tasks) {\n\t\tconst config = agents.find((a) => a.name === t.agent);\n\t\tif (!config) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${t.agent}` }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t\t};\n\t\t}\n\t\tagentConfigs.push(config);\n\t}\n\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst maxSubagentDepths = agentConfigs.map((config) =>\n\t\tresolveChildMaxSubagentDepth(currentMaxSubagentDepth, config.maxSubagentDepth),\n\t);\n\tconst toolBudgets: (ResolvedToolBudget | undefined)[] = [];\n\tfor (let index = 0; index < tasks.length; index++) {\n\t\tconst resolved = resolveEffectiveToolBudget({ stepBudget: tasks[index]?.toolBudget, runBudget: data.toolBudget, agentBudget: agentConfigs[index]?.toolBudget, configBudget: data.configToolBudget });\n\t\tif (resolved.error) return buildParallelModeError(resolved.error);\n\t\ttoolBudgets.push(resolved.toolBudget);\n\t}\n\n\tif (params.worktree) {\n\t\tconst worktreeTaskCwdError = buildParallelWorktreeTaskCwdError(tasks, effectiveCwd);\n\t\tif (worktreeTaskCwdError) return buildParallelModeError(worktreeTaskCwdError);\n\t}\n\n\tconst currentProvider = ctx.model?.provider;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tlet taskTexts = tasks.map((t) => t.task);\n\tconst skillOverrides: (string[] | false | undefined)[] = tasks.map((t) =>\n\t\tnormalizeSkillInput(t.skill),\n\t);\n\tconst behaviorOverrides: StepOverrides[] = tasks.map((task, index) => ({\n\t\t...(task.output !== undefined && task.output !== true ? { output: task.output } : {}),\n\t\t...(task.outputMode !== undefined ? { outputMode: task.outputMode } : {}),\n\t\t...(task.reads !== undefined && task.reads !== true ? { reads: task.reads } : {}),\n\t\t...(task.progress !== undefined ? { progress: task.progress } : {}),\n\t\t...(skillOverrides[index] !== undefined ? { skills: skillOverrides[index] } : {}),\n\t\t...(task.model !== undefined ? { model: task.model } : {}),\n\t}));\n\tconst modelOverrides: (string | undefined)[] = tasks.map((task, i) =>\n\t\t// lunr: model tiers — explicit per-task model wins; otherwise resolve task.tier via the tier bridge.\n\t\tresolveEffectiveSubagentModel(behaviorOverrides[i]?.model ?? resolveTierModelOverride(task.tier), agentConfigs[i]?.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope }),\n\t);\n\n\tif (params.clarify === true && ctx.hasUI) {\n\t\tconst behaviors = agentConfigs.map((_c, i) =>\n\t\t\tresolveStepBehavior(behaviorOverrides[i]!),\n\t\t);\n\t\tconst availableSkills = discoverAvailableSkills(effectiveCwd);\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui, theme,\n\t\t\t\t\tagentConfigs,\n\t\t\t\t\ttaskTexts,\n\t\t\t\t\t\"\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tbehaviors,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tcurrentProvider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t\t\"parallel\",\n\t\t\t\t),\n\t\t\t{ overlay: true, overlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" } },\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\treturn { content: [{ type: \"text\", text: \"Cancelled\" }], details: { mode: \"parallel\", results: [] } };\n\t\t}\n\n\t\ttaskTexts = result.templates;\n\t\tfor (let i = 0; i < result.behaviorOverrides.length; i++) {\n\t\t\tconst override = result.behaviorOverrides[i];\n\t\t\tif (override?.model !== undefined) {\n\t\t\t\tmodelOverrides[i] = resolveEffectiveSubagentModel(override.model, agentConfigs[i]?.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope });\n\t\t\t\tbehaviorOverrides[i]!.model = override.model;\n\t\t\t}\n\t\t\tif (override?.output !== undefined) behaviorOverrides[i]!.output = override.output;\n\t\t\tif (override?.reads !== undefined) behaviorOverrides[i]!.reads = override.reads;\n\t\t\tif (override?.progress !== undefined) behaviorOverrides[i]!.progress = override.progress;\n\t\t\tif (override?.skills !== undefined) {\n\t\t\t\tskillOverrides[i] = override.skills;\n\t\t\t\tbehaviorOverrides[i]!.skills = override.skills;\n\t\t\t}\n\t\t}\n\n\t\tif (result.runInBackground) {\n\t\t\tif (!isAsyncAvailable()) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"parallel\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst id = randomUUID();\n\t\t\tconst asyncCtx = {\n\t\t\t\tpi: deps.pi,\n\t\t\t\tcwd: ctx.cwd,\n\t\t\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcurrentModelProvider: ctx.model?.provider,\n\t\t\t\tcurrentModel: ctx.model,\n\t\t\t\tmodelScope: data.modelScope,\n\t\t\t};\n\t\t\tconst parallelTasks = tasks.map((t, i) => {\n\t\t\t\tconst taskText = shouldForkAgent(contextPolicy, t.agent) ? wrapForkTask(taskTexts[i]!) : taskTexts[i]!;\n\t\t\t\tconst progress = taskDisallowsFileUpdates(taskText) ? false : behaviorOverrides[i]?.progress;\n\t\t\t\treturn {\n\t\t\t\t\tagent: t.agent,\n\t\t\t\t\ttask: taskText,\n\t\t\t\t\tcwd: t.cwd,\n\t\t\t\t\t...(behaviorOverrides[i]?.model !== undefined ? { model: behaviorOverrides[i]!.model } : {}),\n\t\t\t\t\t...(skillOverrides[i] !== undefined ? { skill: skillOverrides[i] } : {}),\n\t\t\t\t\t...(behaviorOverrides[i]?.output !== undefined ? { output: behaviorOverrides[i]!.output } : {}),\n\t\t\t\t\t...(behaviorOverrides[i]?.outputMode !== undefined ? { outputMode: behaviorOverrides[i]!.outputMode } : {}),\n\t\t\t\t\t...(behaviorOverrides[i]?.reads !== undefined ? { reads: behaviorOverrides[i]!.reads } : {}),\n\t\t\t\t\t...(progress !== undefined ? { progress } : {}),\n\t\t\t\t\t...(t.toolBudget !== undefined ? { toolBudget: t.toolBudget } : {}),\n\t\t\t\t\t...(t.acceptance !== undefined ? { acceptance: t.acceptance } : {}),\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn executeAsyncChain(id, {\n\t\t\t\tchain: [{ parallel: parallelTasks, concurrency: parallelConcurrency, worktree: params.worktree }],\n\t\t\t\tresultMode: \"parallel\",\n\t\t\t\tgoal: taskTexts[0] ?? \"\",\n\t\t\t\tctx: asyncCtx,\n\t\t\t\tavailableModels,\n\t\t\t\tcwd: effectiveCwd,\n\t\t\t\tmaxOutput: params.maxOutput,\n\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\tartifactConfig,\n\t\t\t\tshareEnabled,\n\t\t\t\tsessionRoot,\n\t\t\t\tchainSkills: [],\n\t\t\t\tsessionFilesByFlatIndex: tasks.map((task, index) => sessionFileForTask(task.agent, index, modelOverrides[index])),\n\t\t\t\tthinkingOverridesByFlatIndex: tasks.map((task, index) => thinkingOverrideForTask(task.agent, index, modelOverrides[index])),\n\t\t\t\tmaxSubagentDepth: currentMaxSubagentDepth,\n\t\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\t\tcontrolConfig,\n\t\t\t\tcontrolIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\t\tchildIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,\n\t\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\t\tturnBudget: data.turnBudget,\n\t\t\t\tglobalConcurrencyLimit: deps.config.globalConcurrencyLimit,\n\t\t\t});\n\t\t}\n\t}\n\n\tconst behaviors = agentConfigs.map((_config, index) => suppressProgressForReadOnlyTask(resolveStepBehavior(behaviorOverrides[index]!), taskTexts[index]));\n\tconst firstProgressIndex = behaviors.findIndex((behavior) => behavior.progress);\n\tconst liveResults: (SingleResult | undefined)[] = new Array(tasks.length).fill(undefined);\n\tconst liveProgress: (AgentProgress | undefined)[] = new Array(tasks.length).fill(undefined);\n\tconst foregroundControl = deps.state.foregroundControls.get(runId);\n\tconst { setup: worktreeSetup, errorResult } = createParallelWorktreeSetup(\n\t\tparams.worktree,\n\t\teffectiveCwd,\n\t\trunId,\n\t\ttasks,\n\t\tdeps.config.worktreeSetupHook,\n\t\tdeps.config.worktreeSetupHookTimeoutMs,\n\t\tdeps.config.worktreeBaseDir,\n\t);\n\tif (errorResult) return errorResult;\n\n\ttry {\n\t\tconst outputBaseDir = path.join(artifactsDir, \"outputs\", runId);\n\t\tconst duplicateOutputError = findDuplicateParallelOutputPath({\n\t\t\ttasks,\n\t\t\tbehaviors,\n\t\t\tparamsCwd: effectiveCwd,\n\t\t\tctxCwd: ctx.cwd,\n\t\t\toutputBaseDir,\n\t\t\tworktreeSetup,\n\t\t});\n\t\tif (duplicateOutputError) return buildParallelModeError(duplicateOutputError);\n\t\tfor (let index = 0; index < tasks.length; index++) {\n\t\t\tconst taskCwd = resolveParallelTaskCwd(tasks[index]!, effectiveCwd, worktreeSetup, index);\n\t\t\tconst outputPath = resolveSingleOutputPath(behaviors[index]?.output, ctx.cwd, taskCwd, outputBaseDir);\n\t\t\tconst validationError = validateFileOnlyOutputMode(behaviors[index]?.outputMode, outputPath, `Parallel task ${index + 1} (${tasks[index]!.agent})`);\n\t\t\tif (validationError) return buildParallelModeError(validationError);\n\t\t}\n\n\t\tconst parallelProgressPrecreated = firstProgressIndex !== -1;\n\t\tconst parallelProgressDir = path.join(artifactsDir, \"progress\", runId);\n\t\tif (parallelProgressPrecreated) writeInitialProgressFile(parallelProgressDir);\n\n\t\tfor (let i = 0; i < taskTexts.length; i++) {\n\t\t\tif (shouldForkAgent(contextPolicy, tasks[i]!.agent)) taskTexts[i] = wrapForkTask(taskTexts[i]!);\n\t\t}\n\n\t\tconst deadlineAt = data.deadlineAt ?? (data.timeoutMs !== undefined ? Date.now() + data.timeoutMs : undefined);\n\t\tconst results = await runForegroundParallelTasks({\n\t\t\ttasks,\n\t\t\ttaskTexts,\n\t\t\tagents,\n\t\t\tctx,\n\t\t\tstate: deps.state,\n\t\t\tintercomEvents: deps.pi.events,\n\t\t\tparentSessionId: data.parentSessionId,\n\t\t\tsignal,\n\t\t\trunId,\n\t\t\tsessionDirForIndex,\n\t\t\tsessionFileForIndex,\n\t\t\tsessionFileForTask,\n\t\t\tthinkingOverrideForTask,\n\t\t\tshareEnabled,\n\t\t\tartifactConfig,\n\t\t\tartifactsDir,\n\t\t\toutputBaseDir,\n\t\t\tmaxOutput: params.maxOutput,\n\t\t\tparamsCwd: effectiveCwd,\n\t\t\tprogressDir: parallelProgressDir,\n\t\t\tavailableModels,\n\t\t\tmodelScope: data.modelScope,\n\t\t\tmodelOverrides,\n\t\t\tbehaviors,\n\t\t\tfirstProgressIndex: parallelProgressPrecreated ? -1 : firstProgressIndex,\n\t\t\tcontrolConfig,\n\t\t\tonControlEvent,\n\t\t\tchildIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(runId, agent, index) : undefined,\n\t\t\torchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\tforegroundControl,\n\t\t\tconcurrencyLimit: parallelConcurrency,\n\t\t\tglobalSemaphore: new Semaphore(deps.config.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT),\n\t\t\tmaxSubagentDepths,\n\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\tliveResults,\n\t\t\tliveProgress,\n\t\t\tonUpdate,\n\t\t\tworktreeSetup,\n\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\tdeadlineAt,\n\t\t\tturnBudget: data.turnBudget,\n\t\t\ttoolBudgets,\n\t\t});\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst run = results[i]!;\n\t\t\trecordRun(run.agent, taskTexts[i]!, run.exitCode, run.progressSummary?.durationMs ?? 0);\n\t\t}\n\n\t\tfor (const result of results) {\n\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t}\n\n\t\tif (foregroundControl) {\n\t\t\tupdateForegroundNestedProjection(foregroundControl);\n\t\t\tattachRootChildrenToSteps(runId, results, foregroundControl.nestedChildren);\n\t\t}\n\t\tconst interrupted = results.find((result) => result.interrupted);\n\t\tconst details = compactForegroundDetails({\n\t\t\tmode: \"parallel\",\n\t\t\trunId,\n\t\t\tresults,\n\t\t\tprogress: params.includeProgress ? allProgress : undefined,\n\t\t\tartifacts: allArtifactPaths.length ? { dir: artifactsDir, files: allArtifactPaths } : undefined,\n\t\t\ttotalChildUsage: sumResultsUsage(results),\n\t\t\ttotalCost: sumResultsCost(results),\n\t\t});\n\t\trememberForegroundRun(deps.state, { runId, mode: \"parallel\", cwd: effectiveCwd, sessionId: data.parentSessionId, results: details.results });\n\t\tif (interrupted) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Parallel run paused after interrupt (${interrupted.agent}). Waiting for explicit next action.` }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t}\n\t\tconst detachedIndex = results.findIndex((result) => result.detached);\n\t\tconst detached = detachedIndex >= 0 ? results[detachedIndex] : undefined;\n\t\tif (detached) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Parallel run detached for intercom coordination (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t}\n\n\t\tif (foregroundControl) updateForegroundNestedProjection(foregroundControl);\n\t\tconst intercomReceipt = await maybeBuildForegroundIntercomReceipt({\n\t\t\tpi: deps.pi,\n\t\t\tintercomBridge: data.intercomBridge,\n\t\t\trunId,\n\t\t\tmode: \"parallel\",\n\t\t\tdetails,\n\t\t\t...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),\n\t\t});\n\t\tif (intercomReceipt) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: intercomReceipt.text }],\n\t\t\t\tdetails: intercomReceipt.details,\n\t\t\t};\n\t\t}\n\n\t\tconst worktreeSuffix = buildParallelWorktreeSuffix(worktreeSetup, artifactsDir, tasks);\n\t\tconst ok = results.filter((result) => result.exitCode === 0).length;\n\t\tconst downgradeNote = backgroundRequestedWhileClarifying ? \" (background requested, but clarify kept this run foreground)\" : \"\";\n\t\tconst aggregatedOutput = aggregateParallelOutputs(\n\t\t\tresults.map((result) => ({\n\t\t\t\tagent: result.agent,\n\t\t\t\toutput: result.truncation?.text || getSingleResultOutput(result),\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\terror: result.error,\n\t\t\t\ttimedOut: result.timedOut,\n\t\t\t})),\n\t\t\t(i, agent) => `=== Task ${i + 1}: ${agent} ===`,\n\t\t);\n\n\t\tconst summary = `${ok}/${results.length} succeeded${downgradeNote}`;\n\t\tconst fullContent = worktreeSuffix\n\t\t\t? `${summary}\\n\\n${aggregatedOutput}\\n\\n${worktreeSuffix}`\n\t\t\t: `${summary}\\n\\n${aggregatedOutput}`;\n\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: fullContent }],\n\t\t\tdetails,\n\t\t};\n\t} finally {\n\t\tif (worktreeSetup) cleanupWorktrees(worktreeSetup);\n\t}\n}\n\nasync function runSinglePath(data: ExecutionContextData, deps: ExecutorDeps): Promise<AgentToolResult<Details>> {\n\tconst {\n\t\tparams,\n\t\teffectiveCwd,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tsessionDirForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tshareEnabled,\n\t\tartifactConfig,\n\t\tartifactsDir,\n\t\tonUpdate,\n\t\tsessionRoot,\n\t\tcontrolConfig,\n\t\tcontextPolicy,\n\t} = data;\n\tconst onControlEvent = createForegroundControlNotifier(data, deps);\n\tlet spec: ChildSpec;\n\ttry {\n\t\tspec = normalizeChildSpec({\n\t\t\ttask: params.task,\n\t\t\tdescription: params.description,\n\t\t\tpermissions: params.permissions,\n\t\t\tmodel: params.model,\n\t\t\ttier: params.tier,\n\t\t\tskill: params.skill,\n\t\t\tcwd: effectiveCwd,\n\t\t\toutput: params.output,\n\t\t\toutputMode: params.outputMode,\n\t\t\tacceptance: params.acceptance,\n\t\t\ttoolBudget: params.toolBudget,\n\t\t}, { parentMode: snapshotParentPermissionMode(deps.state.currentSessionId), runId, index: 0 });\n\t} catch (error) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: error instanceof Error ? error.message : String(error) }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\", results: [] },\n\t\t};\n\t}\n\tconst childIntercomTarget = data.intercomBridge.active ? resolveSubagentIntercomTarget(runId, spec.childId, 0) : undefined;\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\tconst agentConfig = {\n\t\tname: spec.childId,\n\t\tdescription: spec.description,\n\t\tmodel: spec.model,\n\t\toutput: typeof spec.output === \"string\" ? spec.output : undefined,\n\t\ttoolBudget: spec.toolBudget,\n\t\tskills: spec.skill === false ? [] : undefined,\n\t\tsystemPrompt: \"\",\n\t\tsystemPromptMode: \"append\" as const,\n\t\tinheritProjectContext: true,\n\t\tinheritSkills: false,\n\t};\n\tconst effectiveToolBudget = resolveEffectiveToolBudget({ runBudget: data.toolBudget, agentBudget: spec.toolBudget, configBudget: data.configToolBudget });\n\tif (effectiveToolBudget.error) return toExecutionErrorResult(params, new Error(effectiveToolBudget.error));\n\n\tconst currentProvider = ctx.model?.provider;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tlet task = params.task ?? \"\";\n\t// lunr: model tiers — explicit model wins; otherwise resolve params.tier via the tier bridge.\n\tlet modelOverride: string | undefined = resolveEffectiveSubagentModel(\n\t\t(params.model as string | undefined) ?? resolveTierModelOverride(params.tier),\n\t\tagentConfig.model,\n\t\tctx.model,\n\t\tavailableModels,\n\t\tcurrentProvider,\n\t\t{ scope: data.modelScope },\n\t);\n\tlet skillOverride: string[] | false | undefined = normalizeSkillInput(params.skill);\n\tconst rawOutput = params.output !== undefined ? params.output : agentConfig.output;\n\tlet effectiveOutput = normalizeSingleOutputOverride(rawOutput, agentConfig.output);\n\tconst effectiveOutputMode = params.outputMode ?? \"inline\";\n\tconst currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);\n\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(currentMaxSubagentDepth, agentConfig.maxSubagentDepth);\n\n\tif (params.clarify === true && ctx.hasUI) {\n\t\tconst behavior = resolveStepBehavior({ output: effectiveOutput, skills: skillOverride });\n\t\tconst availableSkills = discoverAvailableSkills(effectiveCwd);\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui, theme,\n\t\t\t\t\t[agentConfig],\n\t\t\t\t\t[task],\n\t\t\t\t\ttask,\n\t\t\t\t\tundefined,\n\t\t\t\t\t[behavior],\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tcurrentProvider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t\t\"single\",\n\t\t\t\t),\n\t\t\t{ overlay: true, overlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" } },\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\treturn { content: [{ type: \"text\", text: \"Cancelled\" }], details: { mode: \"single\", results: [] } };\n\t\t}\n\n\t\ttask = result.templates[0]!;\n\t\tconst override = result.behaviorOverrides[0];\n\t\tif (override?.model !== undefined) modelOverride = resolveEffectiveSubagentModel(override.model, agentConfig.model, ctx.model, availableModels, currentProvider, { scope: data.modelScope });\n\t\tif (override?.output !== undefined) effectiveOutput = normalizeSingleOutputOverride(override.output, agentConfig.output);\n\t\tif (override?.skills !== undefined) skillOverride = override.skills;\n\n\t\tif (result.runInBackground) {\n\t\t\tif (!isAsyncAvailable()) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the pi-subagents package dependencies are installed.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst id = randomUUID();\n\t\t\tconst asyncCtx = {\n\t\t\t\tpi: deps.pi,\n\t\t\t\tcwd: ctx.cwd,\n\t\t\t\tcurrentSessionId: deps.state.currentSessionId!,\n\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcurrentModelProvider: ctx.model?.provider,\n\t\t\t\tcurrentModel: ctx.model,\n\t\t\t\tmodelScope: data.modelScope,\n\t\t\t};\n\t\t\treturn executeAsyncSingle(id, {\n\t\t\t\tspec: { ...spec, task: shouldForkAgent(contextPolicy, params.agent!) ? wrapForkTask(task) : task },\n\t\t\t\tgoal: task,\n\t\t\t\tctx: asyncCtx,\n\t\t\t\tavailableModels,\n\t\t\t\tcwd: effectiveCwd,\n\t\t\t\tmaxOutput: params.maxOutput,\n\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\tartifactConfig,\n\t\t\t\tshareEnabled,\n\t\t\t\tsessionRoot,\n\t\t\t\tsessionFile: sessionFileForTask(spec.childId, 0, modelOverride),\n\t\t\t\tskills: skillOverride === false ? [] : skillOverride,\n\t\t\t\toutput: effectiveOutput,\n\t\t\t\toutputMode: effectiveOutputMode,\n\t\t\t\toutputBaseDir: resolveSingleRunOutputBaseDir(deps, artifactsDir, id),\n\t\t\t\tmodelOverride,\n\t\t\t\tthinkingOverride: thinkingOverrideForTask(params.agent!, 0, modelOverride),\n\t\t\t\tmaxSubagentDepth,\n\t\t\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\t\t\tworktreeSetupHook: deps.config.worktreeSetupHook,\n\t\t\t\tworktreeSetupHookTimeoutMs: deps.config.worktreeSetupHookTimeoutMs,\n\t\t\t\tworktreeBaseDir: deps.config.worktreeBaseDir,\n\t\t\t\tcontrolConfig,\n\t\t\t\tcontrolIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\t\t\tchildIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,\n\t\t\t\ttimeoutMs: data.timeoutMs,\n\t\t\t\tturnBudget: data.turnBudget,\n\t\t\t\ttoolBudget: effectiveToolBudget.toolBudget,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (shouldForkAgent(contextPolicy, params.agent!)) {\n\t\ttask = wrapForkTask(task);\n\t}\n\tconst cleanTask = task;\n\tconst outputPath = resolveSingleOutputPath(effectiveOutput, ctx.cwd, effectiveCwd, resolveSingleRunOutputBaseDir(deps, artifactsDir, runId));\n\tconst validationError = validateFileOnlyOutputMode(effectiveOutputMode, outputPath, `Single run (${params.agent})`);\n\tif (validationError) {\n\t\treturn { content: [{ type: \"text\", text: validationError }], isError: true, details: { mode: \"single\", results: [] } };\n\t}\n\ttask = injectSingleOutputInstruction(task, outputPath, agentConfig);\n\n\tlet effectiveSkills: string[] | undefined;\n\tif (skillOverride === false) {\n\t\teffectiveSkills = [];\n\t} else {\n\t\teffectiveSkills = skillOverride;\n\t}\n\tconst interruptController = new AbortController();\n\tconst foregroundControl = deps.state.foregroundControls.get(runId);\n\tif (foregroundControl) {\n\t\tforegroundControl.currentAgent = params.description || params.agent;\n\t\tforegroundControl.currentChildId = params.agent;\n\t\tforegroundControl.currentIndex = 0;\n\t\tforegroundControl.currentActivityState = undefined;\n\t\tforegroundControl.updatedAt = Date.now();\n\t\tforegroundControl.interrupt = () => {\n\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\tinterruptController.abort();\n\t\t\tforegroundControl.currentActivityState = undefined;\n\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\treturn true;\n\t\t};\n\t}\n\n\tconst forwardSingleUpdate = onUpdate\n\t\t? (update: AgentToolResult<Details>) => {\n\t\t\tif (foregroundControl) {\n\t\t\t\tconst firstProgress = update.details?.progress?.[0];\n\t\t\t\tforegroundControl.currentAgent = params.description || params.agent;\n\t\t\t\tforegroundControl.currentChildId = params.agent;\n\t\t\t\tforegroundControl.currentIndex = firstProgress?.index ?? 0;\n\t\t\t\tforegroundControl.currentActivityState = firstProgress?.activityState;\n\t\t\t\tforegroundControl.lastActivityAt = firstProgress?.lastActivityAt;\n\t\t\t\tforegroundControl.currentTool = firstProgress?.currentTool;\n\t\t\t\tforegroundControl.currentToolStartedAt = firstProgress?.currentToolStartedAt;\n\t\t\t\tforegroundControl.currentPath = firstProgress?.currentPath;\n\t\t\t\tforegroundControl.turnCount = firstProgress?.turnCount;\n\t\t\t\tforegroundControl.tokens = firstProgress?.tokens;\n\t\t\t\tforegroundControl.toolCount = firstProgress?.toolCount;\n\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t}\n\t\t\tonUpdate(update);\n\t\t}\n\t\t: undefined;\n\n\tconst deadlineAt = data.deadlineAt ?? (data.timeoutMs !== undefined ? Date.now() + data.timeoutMs : undefined);\n\tconst r = await runSync(ctx.cwd, { ...spec, task }, {\n\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\tcwd: effectiveCwd,\n\t\tsignal,\n\t\tinterruptSignal: interruptController.signal,\n\t\tallowIntercomDetach: data.intercomBridge.active,\n\t\tintercomEvents: deps.pi.events,\n\t\trunId,\n\t\tsessionDir: sessionDirForIndex(0),\n\t\tsessionFile: sessionFileForTask(spec.childId, 0, modelOverride),\n\t\tshare: shareEnabled,\n\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\tartifactConfig,\n\t\tmaxOutput: params.maxOutput,\n\t\toutputPath,\n\t\toutputMode: effectiveOutputMode,\n\t\tmaxSubagentDepth,\n\t\twaitToolEnabled: deps.waitToolEnabled,\n\t\tonUpdate: forwardSingleUpdate,\n\t\tcontrolConfig,\n\t\tonControlEvent,\n\t\tintercomSessionName: childIntercomTarget,\n\t\torchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,\n\t\tnestedRoute: foregroundControl?.nestedRoute,\n\t\tindex: 0,\n\t\tmodelOverride,\n\t\tthinkingOverride: thinkingOverrideForTask(params.agent!, 0, modelOverride),\n\t\tavailableModels,\n\t\tpreferredModelProvider: currentProvider,\n\t\tmodelScope: data.modelScope,\n\t\tskills: effectiveSkills,\n\t\tacceptance: params.acceptance,\n\t\tacceptanceContext: { mode: \"single\" },\n\t\tonDetachedExit: (result) => updateRememberedForegroundChild(deps.state, { runId, mode: \"single\", cwd: effectiveCwd, sessionId: data.parentSessionId, index: 0, result, events: deps.pi.events }),\n\t\ttimeoutMs: data.timeoutMs,\n\t\tdeadlineAt,\n\t\tturnBudget: data.turnBudget,\n\t\ttoolBudget: effectiveToolBudget.toolBudget,\n\t});\n\tif (foregroundControl?.currentIndex === 0) {\n\t\tforegroundControl.interrupt = undefined;\n\t\tforegroundControl.currentActivityState = r.progress?.activityState;\n\t\tforegroundControl.lastActivityAt = r.progress?.lastActivityAt;\n\t\tforegroundControl.currentTool = r.progress?.currentTool;\n\t\tforegroundControl.currentToolStartedAt = r.progress?.currentToolStartedAt;\n\t\tforegroundControl.currentPath = r.progress?.currentPath;\n\t\tforegroundControl.turnCount = r.progress?.turnCount;\n\t\tforegroundControl.tokens = r.progress?.tokens;\n\t\tforegroundControl.toolCount = r.progress?.toolCount;\n\t\tforegroundControl.updatedAt = Date.now();\n\t}\n\trecordRun(params.agent!, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);\n\n\tif (r.progress) allProgress.push(r.progress);\n\tif (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);\n\n\tconst fullOutput = getSingleResultOutput(r);\n\tconst finalizedOutput = finalizeSingleOutput({\n\t\tfullOutput,\n\t\ttruncatedOutput: r.truncation?.text,\n\t\toutputPath,\n\t\toutputMode: r.outputMode,\n\t\texitCode: r.exitCode,\n\t\tsavedPath: r.savedOutputPath,\n\t\toutputReference: r.outputReference,\n\t\tsaveError: r.outputSaveError,\n\t});\n\tif (foregroundControl) {\n\t\tupdateForegroundNestedProjection(foregroundControl);\n\t\tattachRootChildrenToSteps(runId, [r], foregroundControl.nestedChildren);\n\t}\n\tconst details = compactForegroundDetails({\n\t\tmode: \"single\",\n\t\trunId,\n\t\tresults: [r],\n\t\t...(data.turnBudget ? { turnBudget: data.turnBudget } : {}),\n\t\t...(effectiveToolBudget.toolBudget ? { toolBudget: effectiveToolBudget.toolBudget } : {}),\n\t\tprogress: params.includeProgress ? allProgress : undefined,\n\t\tartifacts: allArtifactPaths.length ? { dir: artifactsDir, files: allArtifactPaths } : undefined,\n\t\ttruncation: r.truncation,\n\t\ttotalChildUsage: sumResultsUsage([r]),\n\t\ttotalCost: sumResultsCost([r]),\n\t});\n\trememberForegroundRun(deps.state, { runId, mode: \"single\", cwd: effectiveCwd, sessionId: data.parentSessionId, results: details.results });\n\n\tif (!r.detached && !r.interrupted) {\n\t\tif (foregroundControl) updateForegroundNestedProjection(foregroundControl);\n\t\tconst intercomReceipt = await maybeBuildForegroundIntercomReceipt({\n\t\t\tpi: deps.pi,\n\t\t\tintercomBridge: data.intercomBridge,\n\t\t\trunId,\n\t\t\tmode: \"single\",\n\t\t\tdetails,\n\t\t\t...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),\n\t\t});\n\t\tif (intercomReceipt) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: intercomReceipt.text }],\n\t\t\t\tdetails: intercomReceipt.details,\n\t\t\t\t...(r.exitCode !== 0 ? { isError: true } : {}),\n\t\t\t};\n\t\t}\n\t}\n\n\tif (r.detached) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Detached for intercom coordination: ${params.agent}. Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\tdetails,\n\t\t};\n\t}\n\n\tif (r.interrupted) {\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: `Run paused after interrupt (${params.agent}). Waiting for explicit next action.` }],\n\t\t\tdetails,\n\t\t};\n\t}\n\n\tif (r.exitCode !== 0)\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: formatFailedSingleRunOutput(r, finalizedOutput.displayOutput) }],\n\t\t\tdetails,\n\t\t\tisError: true,\n\t\t};\n\treturn {\n\t\tcontent: [{ type: \"text\", text: finalizedOutput.displayOutput || \"(no output)\" }],\n\t\tdetails,\n\t};\n}\n\nfunction inferExecutionMode(params: SubagentParamsLike): SubagentRunMode {\n\tif ((params.chain?.length ?? 0) > 0) return \"chain\";\n\tif ((params.tasks?.length ?? 0) > 0) return \"parallel\";\n\treturn \"single\";\n}\n\nfunction foregroundCapacityResult(params: SubagentParamsLike, inFlight: number, limit: number): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: `Foreground subagent capacity reached (${inFlight}/${limit} running). Wait for a child to finish, use ONE subagent call with tasks: [{task, description}, …], or set async: true.`,\n\t\t}],\n\t\tisError: true,\n\t\tdetails: { mode: inferExecutionMode(params), results: [] },\n\t};\n}\n\nfunction omitExecutionModeActionAlias(params: SubagentParamsLike): SubagentParamsLike {\n\tconst action = params.action?.toLowerCase();\n\tif (action === \"single\" && params.task !== undefined) {\n\t\tconst rest = { ...params };\n\t\tdelete rest.action;\n\t\treturn rest;\n\t}\n\tif ((action === \"parallel\" || action === \"tasks\") && (params.tasks?.length ?? 0) > 0) {\n\t\tconst rest = { ...params };\n\t\tdelete rest.action;\n\t\treturn rest;\n\t}\n\treturn params;\n}\n\nexport function createSubagentExecutor(deps: ExecutorDeps): {\n\texecute: (\n\t\tid: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t) => Promise<AgentToolResult<Details>>;\n} {\n\tconst execute = async (\n\t\t_id: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t): Promise<AgentToolResult<Details>> => {\n\t\tdeps.state.baseCwd = ctx.cwd;\n\t\tdeps.state.foregroundRuns ??= new Map();\n\t\tdeps.state.foregroundControls ??= new Map();\n\t\tdeps.state.lastForegroundControlId ??= null;\n\t\tconst requestParams = omitExecutionModeActionAlias(params);\n\t\tconst requestCwd = resolveRequestedCwd(ctx.cwd, requestParams.cwd);\n\t\tconst paramsWithResolvedCwd = requestParams.cwd === undefined ? requestParams : { ...requestParams, cwd: requestCwd };\n\t\tconst action = paramsWithResolvedCwd.action;\n\t\tif (action) {\n\t\t\tif ((WATCHDOG_TOOL_ACTIONS as readonly string[]).includes(action)) {\n\t\t\t\tif (deps.allowMutatingManagementActions === false && MUTATING_MANAGEMENT_ACTIONS.has(action)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Action '${action}' is not available from child-safe subagent fanout mode.` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"management\" as const, results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn handleWatchdogToolAction(action, paramsWithResolvedCwd, ctx, deps.watchdog);\n\t\t\t}\n\t\t\tif (action === \"doctor\") {\n\t\t\t\tlet currentSessionFile: string | null = null;\n\t\t\t\tlet currentSessionId = deps.state.currentSessionId;\n\t\t\t\tlet sessionError: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tcurrentSessionFile = ctx.sessionManager.getSessionFile() ?? null;\n\t\t\t\t\tcurrentSessionId = ctx.sessionManager.getSessionId();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsessionError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n\t\t\t\t}\n\t\t\t\tlet orchestratorTarget: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\torchestratorTarget = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!sessionError) sessionError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: buildDoctorReport({\n\t\t\t\t\t\t\tcwd: requestCwd,\n\t\t\t\t\t\t\tconfig: deps.config,\n\t\t\t\t\t\t\tstate: deps.state,\n\t\t\t\t\t\t\tcontext: paramsWithResolvedCwd.context,\n\t\t\t\t\t\t\trequestedSessionDir: paramsWithResolvedCwd.sessionDir,\n\t\t\t\t\t\t\tcurrentSessionFile,\n\t\t\t\t\t\t\tcurrentSessionId,\n\t\t\t\t\t\t\torchestratorTarget,\n\t\t\t\t\t\t\tsessionError,\n\t\t\t\t\t\t\texpandTilde: deps.expandTilde,\n\t\t\t\t\t\t}),\n\t\t\t\t\t}],\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (action === \"status\") {\n\t\t\t\tdeps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;\n\t\t\t\tconst nestedScope = nestedResolutionScopeForExecutor(deps);\n\t\t\t\tconst sessionRoots = trustedSessionRootsForStatus(ctx, deps);\n\t\t\t\tif (paramsWithResolvedCwd.view === \"fleet\") {\n\t\t\t\t\treturn inspectSubagentStatus(paramsWithResolvedCwd, { state: deps.state, nested: nestedScope, sessionRoots });\n\t\t\t\t}\n\t\t\t\tif (targetRunId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst resolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedScope });\n\t\t\t\t\t\tif (resolved?.kind === \"foreground\") {\n\t\t\t\t\t\t\tconst foreground = getForegroundControl(deps.state, resolved.id);\n\t\t\t\t\t\t\tif (foreground) {\n\t\t\t\t\t\t\t\tif (paramsWithResolvedCwd.view === \"transcript\") {\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"Live foreground transcript is already visible in the expanded running subagent result. Persisted session transcript becomes inspectable after the foreground run completes when sessions are enabled.\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn foregroundStatusResult(foreground);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst foreground = getForegroundControl(deps.state, undefined);\n\t\t\t\t\tif (foreground && paramsWithResolvedCwd.view !== \"transcript\") return foregroundStatusResult(foreground);\n\t\t\t\t\tif (foreground && paramsWithResolvedCwd.view === \"transcript\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"Live foreground transcript is already visible in the expanded running subagent result. Pass an async run id to inspect a background transcript.\" }],\n\t\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn inspectSubagentStatus(paramsWithResolvedCwd, { state: deps.state, nested: nestedScope, sessionRoots });\n\t\t\t}\n\t\t\tif (action === \"resume\") {\n\t\t\t\treturn resumeAsyncRun({ params: paramsWithResolvedCwd, requestCwd, ctx, deps });\n\t\t\t}\n\t\t\tif (action === \"steer\") {\n\t\t\t\tdeps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);\n\t\t\t\tconst message = (paramsWithResolvedCwd.message ?? paramsWithResolvedCwd.task ?? \"\").trim();\n\t\t\t\tif (!message) return { content: [{ type: \"text\", text: \"action='steer' requires message.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;\n\t\t\t\tif (paramsWithResolvedCwd.dir) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst location = resolveAsyncRunLocation(paramsWithResolvedCwd, ASYNC_DIR, RESULTS_DIR);\n\t\t\t\t\t\tconst runId = location.resolvedId ?? targetRunId ?? path.basename(location.asyncDir ?? paramsWithResolvedCwd.dir);\n\t\t\t\t\t\treturn steerAsyncRun({ state: deps.state, runId, message, index: paramsWithResolvedCwd.index, kill: deps.kill, location, signal, recover: ({ absoluteDeadlineAt, ...limits }) => resumeAsyncRun({ params: { ...limits, action: \"resume\", id: runId, message }, requestCwd, ctx, deps, absoluteDeadlineAt }) });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!targetRunId) return { content: [{ type: \"text\", text: \"action='steer' requires id or dir.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tresolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn { content: [{ type: \"text\", text }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t}\n\t\t\t\tif (resolved?.kind === \"nested\") return steerNestedRun({ target: resolved, message, index: paramsWithResolvedCwd.index, signal });\n\t\t\t\tif (resolved?.kind === \"foreground\") return { content: [{ type: \"text\", text: \"action='steer' currently supports live async Pi child sessions only; use action='interrupt' or action='resume' for foreground runs.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tif (resolved?.kind !== \"async\") return { content: [{ type: \"text\", text: `No async run found for '${targetRunId}'.` }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\treturn steerAsyncRun({ state: deps.state, runId: resolved.id, message, index: paramsWithResolvedCwd.index, kill: deps.kill, location: resolved.location, signal, recover: ({ absoluteDeadlineAt, ...limits }) => resumeAsyncRun({ params: { ...limits, action: \"resume\", id: resolved!.id, message }, requestCwd, ctx, deps, absoluteDeadlineAt }) });\n\t\t\t}\n\t\t\tif (action === \"append-step\") {\n\t\t\t\treturn appendStepToAsyncChain({ params: paramsWithResolvedCwd, requestCwd, ctx, deps });\n\t\t\t}\n\t\t\tif (action === \"schedule\" || action === \"schedule-list\" || action === \"schedule-status\" || action === \"schedule-cancel\") {\n\t\t\t\tif (!deps.handleScheduledRunAction) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Action '${action}' is not available in this subagent context.` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn deps.handleScheduledRunAction(paramsWithResolvedCwd, ctx);\n\t\t\t}\n\t\t\tif (action === \"stop\") {\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;\n\t\t\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\t\t\tif (paramsWithResolvedCwd.dir) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst location = resolveAsyncRunLocation(paramsWithResolvedCwd, ASYNC_DIR, RESULTS_DIR);\n\t\t\t\t\t\treturn stopAsyncRun(deps.state, location.resolvedId ?? targetRunId ?? path.basename(location.asyncDir ?? paramsWithResolvedCwd.dir), deps.kill, location);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!targetRunId) return { content: [{ type: \"text\", text: \"action='stop' requires id or dir.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\ttry {\n\t\t\t\t\tresolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t}\n\t\t\t\tif (resolved?.kind === \"nested\") return { content: [{ type: \"text\", text: \"action='stop' supports current-session top-level async runs only.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tif (resolved?.kind === \"foreground\") return { content: [{ type: \"text\", text: \"action='stop' supports async runs only. Use action='interrupt' for foreground runs.\" }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\tconst stopResult = stopAsyncRun(\n\t\t\t\t\tdeps.state,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.id : targetRunId,\n\t\t\t\t\tdeps.kill,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.location : undefined,\n\t\t\t\t);\n\t\t\t\tif (stopResult) return stopResult;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"No stoppable async run found in this session.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (action === \"interrupt\") {\n\t\t\t\tconst targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;\n\t\t\t\tlet resolved: ResolvedSubagentRunId | undefined;\n\t\t\t\tif (targetRunId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\treturn { content: [{ type: \"text\", text: message }], isError: true, details: { mode: \"management\", results: [] } };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (resolved?.kind === \"nested\") return interruptNestedRun(resolved);\n\t\t\t\tconst foreground = getForegroundControl(deps.state, resolved?.kind === \"foreground\" ? resolved.id : targetRunId);\n\t\t\t\tif (foreground?.interrupt) {\n\t\t\t\t\tconst interrupted = foreground.interrupt();\n\t\t\t\t\tif (interrupted) {\n\t\t\t\t\t\tforeground.updatedAt = Date.now();\n\t\t\t\t\t\tforeground.currentActivityState = undefined;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Interrupt requested for foreground run ${foreground.runId}.` }],\n\t\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Foreground run ${foreground.runId} has no active child step to interrupt.` }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst asyncInterruptResult = interruptAsyncRun(\n\t\t\t\t\tdeps.state,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.id : targetRunId,\n\t\t\t\t\tdeps.kill,\n\t\t\t\t\tresolved?.kind === \"async\" ? resolved.location : undefined,\n\t\t\t\t);\n\t\t\t\tif (asyncInterruptResult) return asyncInterruptResult;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"No interrupt-capable run found in this session.\" }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: \"management\", results: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Every supported control action returns above. Named-agent CRUD actions are\n\t\t\t// intentionally absent from SUBAGENT_ACTIONS and have no fallback handler.\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown action: ${action}. Valid: ${SUBAGENT_ACTIONS.join(\", \")}` }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"management\" as const, results: [] },\n\t\t\t};\n\t\t}\n\n\t\tconst { blocked, depth, maxDepth } = checkSubagentDepth(deps.config.maxSubagentDepth);\n\t\tif (blocked) {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext:\n\t\t\t\t\t\t\t`Nested subagent call blocked (depth=${depth}, max=${maxDepth}). ` +\n\t\t\t\t\t\t\t\"You are running at the maximum subagent nesting depth. \" +\n\t\t\t\t\t\t\t\"Complete your current task directly without delegating to further subagents.\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t};\n\t\t}\n\n\t\tconst normalized = normalizeRepeatedParallelCounts(paramsWithResolvedCwd);\n\t\tif (normalized.error) return normalized.error;\n\t\tconst normalizedParams = normalized.params!;\n\n\t\tlet effectiveParams = applyForceTopLevelAsyncOverride(\n\t\t\tnormalizedParams,\n\t\t\tdepth,\n\t\t\tdeps.config.forceTopLevelAsync === true,\n\t\t);\n\t\tconst runToolBudget = resolveToolBudget(effectiveParams.toolBudget, \"toolBudget\");\n\t\tif (runToolBudget.error) return buildRequestedModeError(effectiveParams, runToolBudget.error);\n\t\tconst configToolBudget = resolveToolBudget(deps.config.toolBudget, \"config.toolBudget\");\n\t\tif (configToolBudget.error) return buildRequestedModeError(effectiveParams, configToolBudget.error);\n\n\t\tconst effectiveCwd = effectiveParams.cwd ?? ctx.cwd;\n\t\tconst parentSessionFile = ctx.sessionManager.getSessionFile() ?? null;\n\t\tdeps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);\n\t\tconst runId = randomUUID().slice(0, 8);\n\t\tconst parentPermissionMode = snapshotParentPermissionMode(deps.state.currentSessionId);\n\t\tlet internalized: ReturnType<typeof internalizePromptDrivenChildren>;\n\t\ttry {\n\t\t\tinternalized = internalizePromptDrivenChildren(effectiveParams, {\n\t\t\t\trunId,\n\t\t\t\tparentMode: parentPermissionMode,\n\t\t\t\tdynamicFanoutMaxItems: deps.config.chain?.dynamicFanout?.maxItems,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\treturn buildRequestedModeError(effectiveParams, error instanceof Error ? error.message : String(error));\n\t\t}\n\t\teffectiveParams = internalized.params;\n\t\tconst discoveredAgents = internalized.agents;\n\t\tconst modelScope = undefined;\n\t\tconst foregroundTimeout = resolveForegroundTimeout(effectiveParams);\n\t\tif (foregroundTimeout.error) return buildRequestedModeError(effectiveParams, foregroundTimeout.error);\n\t\tconst turnBudget = resolveTurnBudgetConfig(effectiveParams.turnBudget ?? deps.config.turnBudget);\n\t\tif (turnBudget.error) return buildRequestedModeError(effectiveParams, turnBudget.error);\n\t\tconst contextPolicy = resolveAgentDefaultContextPolicy(effectiveParams);\n\t\teffectiveParams = contextPolicy.params;\n\t\tconst sessionName = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());\n\t\tconst intercomBridge = resolveIntercomBridge({\n\t\t\tconfig: deps.config.intercomBridge,\n\t\t\tcontext: effectiveParams.context,\n\t\t\torchestratorTarget: sessionName,\n\t\t});\n\t\tconst agents = intercomBridge.active\n\t\t\t? discoveredAgents.map((agent) => applyIntercomBridgeToAgent(agent, intercomBridge))\n\t\t\t: discoveredAgents;\n\t\tconst inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();\n\t\tconst nestedParentAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;\n\t\tconst nestedRoute = inheritedNestedRoute ?? createNestedRoute(runId);\n\t\tconst shareEnabled = effectiveParams.share === true;\n\t\tconst hasChain = (effectiveParams.chain?.length ?? 0) > 0;\n\t\tconst hasTasks = (effectiveParams.tasks?.length ?? 0) > 0;\n\t\tconst hasSingle = !hasChain && !hasTasks && Boolean(effectiveParams.task);\n\t\tconst allowClarifyTaskPrompt = hasChain\n\t\t\t&& effectiveParams.clarify === true\n\t\t\t&& ctx.hasUI\n\t\t\t&& !(effectiveParams.chain?.some(isParallelStep) ?? false);\n\n\t\tconst validationError = validateExecutionInput(\n\t\t\teffectiveParams,\n\t\t\thasChain,\n\t\t\thasTasks,\n\t\t\thasSingle,\n\t\t\tallowClarifyTaskPrompt,\n\t\t);\n\t\tif (validationError) return validationError;\n\n\t\tlet forkSessionFileForIndex: (idx?: number) => string | undefined = () => undefined;\n\t\tlet forkThinkingOverrideForIndex: (idx?: number) => ChildRuntimeConfig[\"thinking\"] | undefined = () => undefined;\n\t\tlet prepareForkThinking = (_agentName: string, _index: number, _modelOverride?: string): void => {};\n\t\tconst forkThinkingRequirements = new Map<number, boolean>();\n\t\tconst forkThinkingDowngrades = new Map<number, string>();\n\t\ttry {\n\t\t\tconst forkAvailableModels = contextPolicy.usesFork ? ctx.modelRegistry.getAvailable().map(toModelInfo) : [];\n\t\t\tprepareForkThinking = (agentName, index, modelOverride) => {\n\t\t\t\tconst agentConfig = agents.find((agent) => agent.name === agentName);\n\t\t\t\tconst primaryModel = resolveEffectiveSubagentModel(\n\t\t\t\t\tmodelOverride,\n\t\t\t\t\tagentConfig?.model,\n\t\t\t\t\tctx.model,\n\t\t\t\t\tforkAvailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t);\n\t\t\t\tconst candidates = buildModelCandidates(\n\t\t\t\t\tprimaryModel,\n\t\t\t\t\tagentConfig?.fallbackModels,\n\t\t\t\t\tforkAvailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t);\n\t\t\t\tforkThinkingRequirements.set(\n\t\t\t\t\tindex,\n\t\t\t\t\tcandidates.length === 0\n\t\t\t\t\t\t|| candidates.some((candidate) => forkedChildRequiresThinkingOff(candidate, forkAvailableModels, ctx.model?.provider)),\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst forkContextResolver = createForkContextResolver(ctx.sessionManager, contextPolicy.usesFork ? \"fork\" : undefined, {\n\t\t\t\tforceThinkingOffForIndex: (index) => forkThinkingRequirements.get(index) ?? true,\n\t\t\t});\n\t\t\tforkSessionFileForIndex = forkContextResolver.sessionFileForIndex;\n\t\t\tforkThinkingOverrideForIndex = forkContextResolver.thinkingOverrideForIndex;\n\t\t} catch (error) {\n\t\t\treturn toExecutionErrorResult(effectiveParams, error);\n\t\t}\n\t\tconst requestedAsync = effectiveParams.async ?? deps.asyncByDefault;\n\t\tconst backgroundRequestedWhileClarifying = (hasChain || hasTasks) && requestedAsync && effectiveParams.clarify === true;\n\t\tconst effectiveAsync = requestedAsync && effectiveParams.clarify !== true;\n\t\tconst controlConfig = resolveControlConfig(deps.config.control, effectiveParams.control);\n\n\t\tconst artifactConfig: ArtifactConfig = {\n\t\t\t...DEFAULT_ARTIFACT_CONFIG,\n\t\t\tenabled: effectiveParams.artifacts !== false,\n\t\t};\n\t\tconst artifactsDir = getArtifactsDir(parentSessionFile, effectiveCwd);\n\n\t\tlet sessionRoot: string;\n\t\tif (effectiveParams.sessionDir) {\n\t\t\tsessionRoot = path.resolve(deps.expandTilde(effectiveParams.sessionDir));\n\t\t} else {\n\t\t\tconst baseSessionRoot = deps.config.defaultSessionDir\n\t\t\t\t? path.resolve(deps.expandTilde(deps.config.defaultSessionDir))\n\t\t\t\t: deps.getSubagentSessionRoot(parentSessionFile);\n\t\t\tsessionRoot = path.join(baseSessionRoot, runId);\n\t\t}\n\t\ttry {\n\t\t\tfs.mkdirSync(sessionRoot, { recursive: true });\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\treturn toExecutionErrorResult(\n\t\t\t\teffectiveParams,\n\t\t\t\tnew Error(`Failed to create session directory '${sessionRoot}': ${message}`),\n\t\t\t);\n\t\t}\n\t\tconst sessionDirForIndex = (idx?: number) =>\n\t\t\tpath.join(sessionRoot, `run-${idx ?? 0}`);\n\t\tconst forkSessionFileForTask: ForkSessionFileForTask = (agentName, idx = 0, modelOverride) => {\n\t\t\tif (!shouldForkAgent(contextPolicy, agentName)) return undefined;\n\t\t\tprepareForkThinking(agentName, idx, modelOverride);\n\t\t\treturn forkSessionFileForIndex(idx);\n\t\t};\n\t\tconst forkThinkingOverrideForTask: ForkThinkingOverrideForTask = (agentName, idx = 0, modelOverride) => {\n\t\t\tif (!shouldForkAgent(contextPolicy, agentName)) return undefined;\n\t\t\tprepareForkThinking(agentName, idx, modelOverride);\n\t\t\tconst override = forkThinkingOverrideForIndex(idx);\n\t\t\tif (override === \"off\") forkThinkingDowngrades.set(idx, agentName);\n\t\t\treturn override;\n\t\t};\n\t\tconst childSessionFileForTask: ForkSessionFileForTask = (agentName, idx, modelOverride) =>\n\t\t\tforkSessionFileForTask(agentName, idx, modelOverride) ?? path.join(sessionDirForIndex(idx), \"session.jsonl\");\n\t\tconst childSessionFileForIndex = (idx?: number) =>\n\t\t\tpath.join(sessionDirForIndex(idx), \"session.jsonl\");\n\t\ttry {\n\t\t\tif (!(effectiveParams.clarify === true && ctx.hasUI)) {\n\t\t\t\tpreflightForkSessionsForStaticTasks(effectiveParams, contextPolicy, forkSessionFileForTask, deps.config.chain?.dynamicFanout?.maxItems);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn toExecutionErrorResult(effectiveParams, error);\n\t\t}\n\t\tconst chainBindingsError = validateExecutionChainBindings(effectiveParams, deps.config.chain?.dynamicFanout?.maxItems);\n\t\tif (chainBindingsError) return chainBindingsError;\n\n\t\tconst onUpdateWithContext = onUpdate\n\t\t\t? (r: AgentToolResult<Details>) => onUpdate(withForkContext(r, effectiveParams.context))\n\t\t\t: undefined;\n\n\t\tconst foregroundMode: \"single\" | \"parallel\" | \"chain\" = hasChain ? \"chain\" : hasTasks ? \"parallel\" : \"single\";\n\t\tconst spawnLimitError = reserveSubagentSpawns({\n\t\t\tstate: deps.state,\n\t\t\tconfig: deps.config,\n\t\t\tsessionId: deps.state.currentSessionId,\n\t\t\trequested: countRequestedSubagentSpawns(effectiveParams, deps.config),\n\t\t\tmode: foregroundMode,\n\t\t});\n\t\tif (spawnLimitError) return spawnLimitError;\n\n\t\tconst execData: ExecutionContextData = {\n\t\t\tparams: effectiveParams,\n\t\t\teffectiveCwd,\n\t\t\tctx,\n\t\t\tsignal,\n\t\t\tonUpdate: onUpdateWithContext,\n\t\t\tagents,\n\t\t\trunId,\n\t\t\tshareEnabled,\n\t\t\tsessionRoot,\n\t\t\tsessionDirForIndex,\n\t\t\tsessionFileForIndex: childSessionFileForIndex,\n\t\t\tsessionFileForTask: childSessionFileForTask,\n\t\t\tthinkingOverrideForTask: forkThinkingOverrideForTask,\n\t\t\tartifactConfig,\n\t\t\tartifactsDir,\n\t\t\tbackgroundRequestedWhileClarifying,\n\t\t\teffectiveAsync,\n\t\t\tcontrolConfig,\n\t\t\tintercomBridge,\n\t\t\tnestedRoute,\n\t\t\ttimeoutMs: foregroundTimeout.timeoutMs,\n\t\t\tturnBudget: turnBudget.turnBudget,\n\t\t\ttoolBudget: runToolBudget.toolBudget,\n\t\t\tconfigToolBudget: configToolBudget.toolBudget,\n\t\t\tcontextPolicy,\n\t\t\tmodelScope,\n\t\t\tparentSessionId: deps.state.currentSessionId,\n\t\t};\n\n\t\tconst foregroundControl = effectiveAsync\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\trunId,\n\t\t\t\tmode: foregroundMode,\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\tupdatedAt: Date.now(),\n\t\t\t\tcurrentAgent: undefined,\n\t\t\t\tcurrentChildId: undefined,\n\t\t\t\tcurrentIndex: undefined,\n\t\t\t\tcurrentActivityState: undefined,\n\t\t\t\tnestedRoute,\n\t\t\t\tinterrupt: undefined,\n\t\t\t};\n\t\tif (foregroundControl) {\n\t\t\tdeps.state.foregroundControls.set(runId, foregroundControl);\n\t\t\tdeps.state.lastForegroundControlId = runId;\n\t\t}\n\n\t\tconst writeNestedForegroundEvent = (type: \"subagent.nested.started\" | \"subagent.nested.completed\", result?: AgentToolResult<Details>): void => {\n\t\t\tif (!inheritedNestedRoute || !nestedParentAddress) return;\n\t\t\tconst now = Date.now();\n\t\t\tconst details = result?.details;\n\t\t\tconst state = type === \"subagent.nested.started\"\n\t\t\t\t? \"running\"\n\t\t\t\t: details?.results.some((child) => child.interrupted || child.detached)\n\t\t\t\t\t? \"paused\"\n\t\t\t\t\t: result?.isError || details?.results.some((child) => child.exitCode !== 0)\n\t\t\t\t\t\t? \"failed\"\n\t\t\t\t\t\t: \"complete\";\n\t\t\tconst errorText = result?.isError\n\t\t\t\t? result.content.find((item) => item.type === \"text\")?.text\n\t\t\t\t: undefined;\n\t\t\tconst internalChildKeys = hasTasks && effectiveParams.tasks\n\t\t\t\t? effectiveParams.tasks.map((task) => task.agent)\n\t\t\t\t: hasChain && effectiveParams.chain\n\t\t\t\t\t? effectiveParams.chain.flatMap((step) => isParallelStep(step)\n\t\t\t\t\t\t? step.parallel.map((task) => task.agent)\n\t\t\t\t\t\t: isDynamicParallelStep(step) ? [step.parallel.agent] : [(step as SequentialStep).agent])\n\t\t\t\t\t: effectiveParams.agent ? [effectiveParams.agent] : [];\n\t\t\tconst childrenForSummary = hasTasks && effectiveParams.tasks\n\t\t\t\t? effectiveParams.tasks.map((task) => task.description || task.agent || \"child\")\n\t\t\t\t: hasChain && effectiveParams.chain\n\t\t\t\t\t? effectiveParams.chain.flatMap(getStepAgents)\n\t\t\t\t\t: [effectiveParams.description || effectiveParams.agent || \"child\"];\n\t\t\tconst leafIntercomTarget = intercomBridge.active && internalChildKeys[0]\n\t\t\t\t? resolveSubagentIntercomTarget(runId, internalChildKeys[0], 0)\n\t\t\t\t: undefined;\n\t\t\ttry {\n\t\t\t\twriteNestedEvent(inheritedNestedRoute, {\n\t\t\t\t\ttype,\n\t\t\t\t\tts: now,\n\t\t\t\t\tparentRunId: nestedParentAddress.parentRunId,\n\t\t\t\t\tparentStepIndex: nestedParentAddress.parentStepIndex,\n\t\t\t\t\tchild: {\n\t\t\t\t\t\tid: runId,\n\t\t\t\t\t\tparentRunId: nestedParentAddress.parentRunId,\n\t\t\t\t\t\tparentStepIndex: nestedParentAddress.parentStepIndex,\n\t\t\t\t\t\tdepth: nestedParentAddress.depth,\n\t\t\t\t\t\tpath: nestedParentAddress.path,\n\t\t\t\t\t\townerIntercomTarget: process.env.PI_SUBAGENT_INTERCOM_SESSION_NAME,\n\t\t\t\t\t\tleafIntercomTarget,\n\t\t\t\t\t\tintercomTarget: leafIntercomTarget,\n\t\t\t\t\t\townerState: state === \"running\" ? \"live\" : \"gone\",\n\t\t\t\t\t\tmode: foregroundMode,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\tagent: childrenForSummary[0],\n\t\t\t\t\t\tagents: childrenForSummary,\n\t\t\t\t\t\tstartedAt: foregroundControl?.startedAt ?? now,\n\t\t\t\t\t\t...(state !== \"running\" ? { endedAt: now } : {}),\n\t\t\t\t\t\tlastUpdate: now,\n\t\t\t\t\t\t...(details?.totalCost ? { totalCost: details.totalCost } : {}),\n\t\t\t\t\t\t...(errorText ? { error: errorText } : {}),\n\t\t\t\t\t\t...(details?.results.length ? { steps: details.results.map((child) => ({\n\t\t\t\t\t\t\tagent: child.agent,\n\t\t\t\t\t\t\tstatus: child.interrupted || child.detached ? \"paused\" : child.exitCode === 0 ? \"complete\" : \"failed\",\n\t\t\t\t\t\t\t...(child.sessionFile ? { sessionFile: child.sessionFile } : {}),\n\t\t\t\t\t\t\t...(child.error ? { error: child.error } : {}),\n\t\t\t\t\t\t})) } : {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to emit nested foreground status event:\", error);\n\t\t\t}\n\t\t};\n\n\t\tlet nestedForegroundStarted = false;\n\t\ttry {\n\t\t\tconst asyncResult = runAsyncPath(execData, deps);\n\t\t\tif (asyncResult) return withForkContext(withForkThinkingNotes(asyncResult, forkThinkingDowngrades), effectiveParams.context);\n\t\t\tif (foregroundControl) {\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.started\");\n\t\t\t\tnestedForegroundStarted = true;\n\t\t\t}\n\t\t\tif (hasChain && effectiveParams.chain) {\n\t\t\t\tconst result = await runChainPath(execData, deps);\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.completed\", result);\n\t\t\t\treturn withForkContext(withForkThinkingNotes(result, forkThinkingDowngrades), effectiveParams.context);\n\t\t\t}\n\t\t\tif (hasTasks && effectiveParams.tasks) {\n\t\t\t\tconst result = await runParallelPath(execData, deps);\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.completed\", result);\n\t\t\t\treturn withForkContext(withForkThinkingNotes(result, forkThinkingDowngrades), effectiveParams.context);\n\t\t\t}\n\t\t\tif (hasSingle) {\n\t\t\t\tconst result = await runSinglePath(execData, deps);\n\t\t\t\twriteNestedForegroundEvent(\"subagent.nested.completed\", result);\n\t\t\t\treturn withForkContext(withForkThinkingNotes(result, forkThinkingDowngrades), effectiveParams.context);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorResult = withForkThinkingNotes(toExecutionErrorResult(effectiveParams, error), forkThinkingDowngrades);\n\t\t\tif (nestedForegroundStarted) writeNestedForegroundEvent(\"subagent.nested.completed\", errorResult);\n\t\t\treturn errorResult;\n\t\t} finally {\n\t\t\tif (foregroundControl) {\n\t\t\t\tclearPendingForegroundControlNotices(deps.state, runId);\n\t\t\t\tdeps.state.foregroundControls.delete(runId);\n\t\t\t\tif (deps.state.lastForegroundControlId === runId) {\n\t\t\t\t\tdeps.state.lastForegroundControlId = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn withForkContext({\n\t\t\tcontent: [{ type: \"text\", text: \"Invalid params\" }],\n\t\t\tisError: true,\n\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t}, effectiveParams.context);\n\t};\n\n\tconst executeWithSingleDispatchGuard = async (\n\t\tid: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t): Promise<AgentToolResult<Details>> => {\n\t\tconst requestParams = omitExecutionModeActionAlias(params);\n\t\tif (requestParams.action) return execute(id, requestParams, signal, onUpdate, ctx);\n\t\tconst { depth } = checkSubagentDepth(deps.config.maxSubagentDepth);\n\t\tconst dispatchParams = applyForceTopLevelAsyncOverride(requestParams, depth, deps.config.forceTopLevelAsync === true);\n\t\tconst runsForeground = dispatchParams.clarify === true || (dispatchParams.async ?? deps.asyncByDefault) !== true;\n\t\tif (!runsForeground) return execute(id, requestParams, signal, onUpdate, ctx);\n\t\tconst limit = resolveTopLevelParallelConcurrency(undefined, deps.config.parallel?.concurrency);\n\t\tconst inFlight = deps.state.foregroundSubagentInFlight ?? 0;\n\t\tif (inFlight >= limit) return foregroundCapacityResult(requestParams, inFlight, limit);\n\t\tdeps.state.foregroundSubagentInFlight = inFlight + 1;\n\t\ttry {\n\t\t\treturn await execute(id, requestParams, signal, onUpdate, ctx);\n\t\t} finally {\n\t\t\tdeps.state.foregroundSubagentInFlight = Math.max(0, (deps.state.foregroundSubagentInFlight ?? 1) - 1);\n\t\t}\n\t};\n\n\treturn { execute: executeWithSingleDispatchGuard };\n}\n"]}
|