@bastani/atomic 0.8.13 → 0.8.14
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 +23 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/host-html-template.ts +1 -1
- package/dist/builtin/mcp/init.ts +15 -2
- package/dist/builtin/mcp/mcp-callback-server.ts +10 -9
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/ui-session.ts +9 -6
- package/dist/builtin/subagents/CHANGELOG.md +8 -1
- package/dist/builtin/subagents/README.md +39 -32
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
- package/dist/builtin/subagents/src/agents/agent-management.ts +6 -1
- package/dist/builtin/subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/builtin/subagents/src/agents/agents.ts +44 -19
- package/dist/builtin/subagents/src/extension/config.ts +16 -0
- package/dist/builtin/subagents/src/extension/fanout-child.ts +246 -0
- package/dist/builtin/subagents/src/extension/index.ts +466 -603
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +6 -4
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +109 -1
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +124 -19
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +41 -6
- package/dist/builtin/subagents/src/runs/background/async-resume.ts +28 -15
- package/dist/builtin/subagents/src/runs/background/async-status.ts +60 -30
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +111 -54
- package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +83 -0
- package/dist/builtin/subagents/src/runs/background/run-status.ts +79 -3
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +46 -1
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +66 -14
- package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +10 -3
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +14 -2
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +320 -23
- package/dist/builtin/subagents/src/runs/shared/completion-guard.ts +23 -1
- package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +369 -0
- package/dist/builtin/subagents/src/runs/shared/nested-events.ts +935 -0
- package/dist/builtin/subagents/src/runs/shared/nested-path.ts +52 -0
- package/dist/builtin/subagents/src/runs/shared/nested-render.ts +115 -0
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +1 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +82 -9
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +1 -1
- package/dist/builtin/subagents/src/runs/shared/single-output.ts +12 -2
- package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +32 -10
- package/dist/builtin/subagents/src/runs/shared/worktree.ts +3 -2
- package/dist/builtin/subagents/src/shared/artifacts.ts +0 -1
- package/dist/builtin/subagents/src/shared/types.ts +96 -1
- package/dist/builtin/subagents/src/shared/utils.ts +10 -2
- package/dist/builtin/subagents/src/slash/slash-commands.ts +468 -625
- package/dist/builtin/subagents/src/tui/render.ts +1227 -2093
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +24 -0
- package/dist/builtin/workflows/README.md +28 -11
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +323 -40
- package/dist/builtin/workflows/builtin/ralph.ts +362 -176
- package/dist/builtin/workflows/package.json +2 -5
- package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
- package/dist/builtin/workflows/skills/skill-creator/LICENSE.txt +202 -0
- package/dist/builtin/workflows/skills/skill-creator/SKILL.md +489 -0
- package/dist/builtin/workflows/skills/skill-creator/agents/analyzer.md +274 -0
- package/dist/builtin/workflows/skills/skill-creator/agents/comparator.md +202 -0
- package/dist/builtin/workflows/skills/skill-creator/agents/grader.md +223 -0
- package/dist/builtin/workflows/skills/skill-creator/assets/eval_review.html +146 -0
- package/dist/builtin/workflows/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/dist/builtin/workflows/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/dist/builtin/workflows/skills/skill-creator/references/schemas.md +430 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/__init__.py +0 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/generate_report.py +326 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/improve_description.py +247 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/package_skill.py +136 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/run_eval.py +310 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/run_loop.py +328 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/utils.py +47 -0
- package/dist/builtin/workflows/src/extension/index.ts +869 -93
- package/dist/builtin/workflows/src/extension/render-call.ts +34 -1
- package/dist/builtin/workflows/src/extension/render-result.ts +126 -21
- package/dist/builtin/workflows/src/extension/runtime.ts +91 -3
- package/dist/builtin/workflows/src/extension/wiring.ts +38 -12
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +62 -5
- package/dist/builtin/workflows/src/runs/background/runner.ts +3 -3
- package/dist/builtin/workflows/src/runs/background/status.ts +42 -8
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +410 -95
- package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +5 -2
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +8 -0
- package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +6 -4
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +3 -2
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +138 -5
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +30 -0
- package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +78 -120
- package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +193 -0
- package/dist/builtin/workflows/src/shared/store-types.ts +26 -1
- package/dist/builtin/workflows/src/shared/store.ts +145 -17
- package/dist/builtin/workflows/src/shared/timing.ts +6 -2
- package/dist/builtin/workflows/src/shared/workflow-failures.ts +375 -0
- package/dist/builtin/workflows/src/tui/chat-surface.ts +68 -17
- package/dist/builtin/workflows/src/tui/connectors.ts +2 -2
- package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +24 -26
- package/dist/builtin/workflows/src/tui/graph-canvas.ts +4 -8
- package/dist/builtin/workflows/src/tui/graph-view.ts +17 -14
- package/dist/builtin/workflows/src/tui/header.ts +38 -0
- package/dist/builtin/workflows/src/tui/inline-form-card.ts +161 -238
- package/dist/builtin/workflows/src/tui/inline-form-editor.ts +68 -73
- package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +2 -3
- package/dist/builtin/workflows/src/tui/inline-form-store.ts +2 -1
- package/dist/builtin/workflows/src/tui/inputs-overlay.ts +1 -3
- package/dist/builtin/workflows/src/tui/inputs-picker.ts +286 -399
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +11 -0
- package/dist/builtin/workflows/src/tui/node-card.ts +2 -1
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +9 -1
- package/dist/builtin/workflows/src/tui/prompt-card.ts +46 -19
- package/dist/builtin/workflows/src/tui/run-detail.ts +63 -80
- package/dist/builtin/workflows/src/tui/session-confirm.ts +9 -3
- package/dist/builtin/workflows/src/tui/session-picker.ts +19 -16
- package/dist/builtin/workflows/src/tui/stage-chat-layout.ts +88 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +368 -879
- package/dist/builtin/workflows/src/tui/status-helpers.ts +4 -0
- package/dist/builtin/workflows/src/tui/status-list.ts +67 -75
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +50 -12
- package/dist/builtin/workflows/src/tui/submit-pane.ts +164 -0
- package/dist/builtin/workflows/src/tui/switcher.ts +27 -4
- package/dist/builtin/workflows/src/tui/text-helpers.ts +98 -4
- package/dist/builtin/workflows/src/tui/widget.ts +90 -68
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +23 -2
- package/dist/builtin/workflows/src/tui/workflow-list.ts +44 -68
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -3
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -10
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +2 -1
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +3 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +6 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +16 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +8 -9
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +8 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +6 -3
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +12 -29
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +5 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +8 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +145 -58
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +6 -20
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +38 -31
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +9 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +32 -24
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -15
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +8 -22
- package/dist/core/skills.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +5 -4
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js +34 -11
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/contract.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/projections.js +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/projections.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/state-reducer.d.ts +1 -2
- package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/state-reducer.js +26 -9
- package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/state.d.ts +4 -0
- package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/state.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts +1 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/option-list-view.js +1 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts +9 -6
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +28 -7
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/view/props-adapter.js +4 -1
- package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +56 -53
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +3 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +8 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +3 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +44 -81
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +27 -12
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +2 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +3 -3
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -5
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +2 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +11 -4
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts +2 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +39 -21
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +9 -8
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js +12 -2
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +20 -35
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/chat-input-actions.d.ts +24 -0
- package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -0
- package/dist/modes/interactive/chat-input-actions.js +179 -0
- package/dist/modes/interactive/chat-input-actions.js.map +1 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +14 -3
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts +157 -0
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -0
- package/dist/modes/interactive/components/chat-session-host.js +1007 -0
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +1 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +14 -5
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +9 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +29 -4
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +18 -67
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/child-process.d.ts +1 -0
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +8 -0
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +3 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js +14 -8
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -0
- package/dist/utils/image-resize-core.js +124 -0
- package/dist/utils/image-resize-core.js.map +1 -0
- package/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/dist/utils/image-resize-worker.js +31 -0
- package/dist/utils/image-resize-worker.js.map +1 -0
- package/dist/utils/image-resize.d.ts +7 -27
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +75 -115
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/paths.d.ts +16 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +49 -7
- package/dist/utils/paths.js.map +1 -1
- package/docs/changelog.mdx +29 -0
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +2 -2
- package/docs/development.md +1 -1
- package/docs/docs.json +98 -143
- package/docs/extensions.md +29 -16
- package/docs/favicon.svg +29 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/images/workflow-command.png +0 -0
- package/docs/images/workflow-graph.png +0 -0
- package/docs/images/workflow-input-picker.png +0 -0
- package/docs/images/workflow-list.png +0 -0
- package/docs/index.md +10 -1
- package/docs/logo.svg +59 -0
- package/docs/packages.md +3 -3
- package/docs/providers.md +1 -1
- package/docs/quickstart.md +98 -2
- package/docs/rpc.md +8 -8
- package/docs/sdk.md +23 -12
- package/docs/sessions.md +1 -1
- package/docs/skills.md +15 -1
- package/docs/termux.md +11 -1
- package/docs/themes.md +6 -6
- package/docs/tui.md +18 -18
- package/docs/usage.md +1 -1
- package/docs/workflows.md +172 -2
- package/examples/extensions/subagent/index.ts +2 -1
- package/package.json +6 -6
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/SKILL.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/element-attributes.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/playwright-tests.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/request-mocking.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/running-code.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/session-management.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/spec-driven-testing.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/storage-state.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/test-generation.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/tracing.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/video-recording.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/SKILL.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/deep-modules.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/interface-design.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/mocking.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/refactoring.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/tests.md +0 -0
|
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
5
|
-
import type
|
|
5
|
+
import { APP_NAME, getEnvValue, type ExtensionAPI, type ExtensionContext } from "@bastani/atomic";
|
|
6
6
|
import { type AgentConfig, type AgentScope } from "../../agents/agents.ts";
|
|
7
7
|
import { getArtifactsDir } from "../../shared/artifacts.ts";
|
|
8
8
|
import { ChainClarifyComponent, type ChainClarifyResult } from "./chain-clarify.ts";
|
|
@@ -14,6 +14,7 @@ import { buildDoctorReport } from "../../extension/doctor.ts";
|
|
|
14
14
|
import { clearPendingForegroundControlNotices } from "../../extension/control-notices.ts";
|
|
15
15
|
import { runSync } from "./execution.ts";
|
|
16
16
|
import { currentModelFullId, resolveModelCandidate } from "../shared/model-fallback.ts";
|
|
17
|
+
import { SUBAGENT_INTERCOM_SESSION_NAME_ENV } from "../shared/pi-args.ts";
|
|
17
18
|
import { aggregateParallelOutputs } from "../shared/parallel-utils.ts";
|
|
18
19
|
import { recordRun } from "../shared/run-history.ts";
|
|
19
20
|
import {
|
|
@@ -35,9 +36,10 @@ import { createForkContextResolver } from "../../shared/fork-context.ts";
|
|
|
35
36
|
import { resolveCurrentSessionId } from "../../shared/session-identity.ts";
|
|
36
37
|
import { applyIntercomBridgeToAgent, INTERCOM_BRIDGE_MARKER, resolveIntercomBridge, resolveIntercomSessionTarget, resolveSubagentIntercomTarget, type IntercomBridgeState } from "../../intercom/intercom-bridge.ts";
|
|
37
38
|
import { formatControlIntercomMessage, formatControlNoticeMessage, resolveControlConfig, shouldNotifyControlEvent } from "../shared/subagent-control.ts";
|
|
38
|
-
import { finalizeSingleOutput, injectSingleOutputInstruction, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
|
|
39
|
+
import { finalizeSingleOutput, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
|
|
39
40
|
import { compactForegroundDetails, getSingleResultOutput, mapConcurrent, readStatus, resolveChildCwd } from "../../shared/utils.ts";
|
|
40
41
|
import {
|
|
42
|
+
attachNestedChildrenToResultChildren,
|
|
41
43
|
buildSubagentResultIntercomPayload,
|
|
42
44
|
deliverSubagentIntercomMessageEvent,
|
|
43
45
|
deliverSubagentResultIntercomEvent,
|
|
@@ -46,6 +48,9 @@ import {
|
|
|
46
48
|
stripDetailsOutputsForIntercomReceipt,
|
|
47
49
|
} from "../../intercom/result-intercom.ts";
|
|
48
50
|
import { buildRevivedAsyncTask, resolveAsyncResumeTarget } from "../background/async-resume.ts";
|
|
51
|
+
import { createNestedRoute, readNestedControlResults, resolveInheritedNestedRouteFromEnv, resolveNestedAsyncDir, resolveNestedParentAddressFromEnv, updateForegroundNestedProjection, writeNestedControlRequest, writeNestedEvent, type NestedRunResolutionScope } from "../shared/nested-events.ts";
|
|
52
|
+
import { resolveSubagentRunId, type ResolvedSubagentRunId } from "../background/run-id-resolver.ts";
|
|
53
|
+
import { formatNestedRunStatusLines } from "../shared/nested-render.ts";
|
|
49
54
|
import { inspectSubagentStatus } from "../background/run-status.ts";
|
|
50
55
|
import { applyForceTopLevelAsyncOverride } from "../background/top-level-async.ts";
|
|
51
56
|
import {
|
|
@@ -67,6 +72,8 @@ import {
|
|
|
67
72
|
type ExtensionConfig,
|
|
68
73
|
type IntercomEventBus,
|
|
69
74
|
type MaxOutputConfig,
|
|
75
|
+
type NestedRouteInfo,
|
|
76
|
+
type NestedRunSummary,
|
|
70
77
|
type ResolvedControlConfig,
|
|
71
78
|
type SingleResult,
|
|
72
79
|
type SubagentRunMode,
|
|
@@ -84,6 +91,7 @@ import {
|
|
|
84
91
|
} from "../../shared/types.ts";
|
|
85
92
|
|
|
86
93
|
const ASYNC_INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === "win32" ? "SIGBREAK" : "SIGUSR2";
|
|
94
|
+
const MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete"]);
|
|
87
95
|
|
|
88
96
|
interface TaskParam {
|
|
89
97
|
agent: string;
|
|
@@ -138,6 +146,7 @@ interface ExecutorDeps {
|
|
|
138
146
|
getSubagentSessionRoot: (parentSessionFile: string | null) => string;
|
|
139
147
|
expandTilde: (p: string) => string;
|
|
140
148
|
discoverAgents: (cwd: string, scope: AgentScope) => { agents: AgentConfig[] };
|
|
149
|
+
allowMutatingManagementActions?: boolean;
|
|
141
150
|
}
|
|
142
151
|
|
|
143
152
|
interface ExecutionContextData {
|
|
@@ -158,6 +167,7 @@ interface ExecutionContextData {
|
|
|
158
167
|
effectiveAsync: boolean;
|
|
159
168
|
controlConfig: ResolvedControlConfig;
|
|
160
169
|
intercomBridge: IntercomBridgeState;
|
|
170
|
+
nestedRoute?: NestedRouteInfo;
|
|
161
171
|
}
|
|
162
172
|
|
|
163
173
|
function resolveRequestedCwd(runtimeCwd: string, requestedCwd: string | undefined): string {
|
|
@@ -196,7 +206,23 @@ function formatForegroundActivity(control: SubagentState["foregroundControls"] e
|
|
|
196
206
|
return [`active ${seconds}s ago`, ...facts].join(" | ");
|
|
197
207
|
}
|
|
198
208
|
|
|
209
|
+
function nestedResolutionScopeForExecutor(deps: ExecutorDeps): NestedRunResolutionScope | undefined {
|
|
210
|
+
if (deps.allowMutatingManagementActions !== false) return undefined;
|
|
211
|
+
const route = resolveInheritedNestedRouteFromEnv();
|
|
212
|
+
const address = route ? resolveNestedParentAddressFromEnv() : undefined;
|
|
213
|
+
return {
|
|
214
|
+
routes: route ? [route] : [],
|
|
215
|
+
...(address ? { descendantOf: { parentRunId: address.parentRunId, ...(address.parentStepIndex !== undefined ? { parentStepIndex: address.parentStepIndex } : {}) } } : {}),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
199
219
|
function foregroundStatusResult(control: SubagentState["foregroundControls"] extends Map<string, infer T> ? T : never): AgentToolResult<Details> {
|
|
220
|
+
let nestedWarning: string | undefined;
|
|
221
|
+
try {
|
|
222
|
+
updateForegroundNestedProjection(control);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
nestedWarning = `Nested status unavailable: ${error instanceof Error ? error.message : String(error)}`;
|
|
225
|
+
}
|
|
200
226
|
const activity = formatForegroundActivity(control);
|
|
201
227
|
const lines = [
|
|
202
228
|
`Run: ${control.runId}`,
|
|
@@ -205,6 +231,8 @@ function foregroundStatusResult(control: SubagentState["foregroundControls"] ext
|
|
|
205
231
|
control.currentAgent ? `Current: ${control.currentAgent}${control.currentIndex !== undefined ? ` step ${control.currentIndex + 1}` : ""}` : undefined,
|
|
206
232
|
activity ? `Activity: ${activity}` : undefined,
|
|
207
233
|
].filter((line): line is string => Boolean(line));
|
|
234
|
+
lines.push(...formatNestedRunStatusLines(control.nestedChildren, { indent: "", commandHints: true, maxLines: 20 }));
|
|
235
|
+
if (nestedWarning) lines.push(`Warning: ${nestedWarning}`);
|
|
208
236
|
return { content: [{ type: "text", text: lines.join("\n") }], details: { mode: "management", results: [] } };
|
|
209
237
|
}
|
|
210
238
|
|
|
@@ -252,7 +280,18 @@ function resolveForegroundResumeTarget(params: SubagentParamsLike, state: Subage
|
|
|
252
280
|
|
|
253
281
|
type AsyncResumeSourceTarget = ReturnType<typeof resolveAsyncResumeTarget> & { source: "async" };
|
|
254
282
|
type ForegroundResumeSourceTarget = NonNullable<ReturnType<typeof resolveForegroundResumeTarget>> & { kind: "revive"; source: "foreground" };
|
|
255
|
-
type
|
|
283
|
+
type NestedResumeSourceTarget = {
|
|
284
|
+
kind: "revive";
|
|
285
|
+
source: "nested";
|
|
286
|
+
runId: string;
|
|
287
|
+
state: "complete" | "failed" | "paused";
|
|
288
|
+
agent: string;
|
|
289
|
+
index: number;
|
|
290
|
+
intercomTarget: string;
|
|
291
|
+
cwd?: string;
|
|
292
|
+
sessionFile: string;
|
|
293
|
+
};
|
|
294
|
+
type ResumeSourceTarget = AsyncResumeSourceTarget | ForegroundResumeSourceTarget | NestedResumeSourceTarget;
|
|
256
295
|
|
|
257
296
|
function isAsyncRunNotFound(error: unknown): boolean {
|
|
258
297
|
return error instanceof Error && error.message.startsWith("Async run not found.");
|
|
@@ -392,6 +431,119 @@ function interruptAsyncRun(state: SubagentState, runId: string | undefined): Age
|
|
|
392
431
|
}
|
|
393
432
|
}
|
|
394
433
|
|
|
434
|
+
function nestedRunSessionFile(run: NestedRunSummary): string | undefined {
|
|
435
|
+
return run.sessionFile ?? (run.steps?.length === 1 ? run.steps[0]?.sessionFile : undefined);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function nestedRunAgent(run: NestedRunSummary): string | undefined {
|
|
439
|
+
return run.agent ?? run.agents?.[0] ?? (run.steps?.length === 1 ? run.steps[0]?.agent : undefined);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function pathWithin(base: string, candidate: string): boolean {
|
|
443
|
+
const resolvedBase = path.resolve(base);
|
|
444
|
+
const resolvedCandidate = path.resolve(candidate);
|
|
445
|
+
return resolvedCandidate === resolvedBase || resolvedCandidate.startsWith(`${resolvedBase}${path.sep}`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function validateNestedSessionFile(run: NestedRunSummary, trustedSessionRoots: string[]): string {
|
|
449
|
+
const sessionFile = nestedRunSessionFile(run);
|
|
450
|
+
if (!sessionFile) throw new Error(`Nested run '${run.id}' does not have a persisted session file to resume from.`);
|
|
451
|
+
if (path.extname(sessionFile) !== ".jsonl") throw new Error(`Nested run '${run.id}' session file must be a .jsonl file: ${sessionFile}`);
|
|
452
|
+
const resolved = path.resolve(sessionFile);
|
|
453
|
+
if (!path.isAbsolute(sessionFile)) throw new Error(`Nested run '${run.id}' session file must be absolute: ${sessionFile}`);
|
|
454
|
+
if (!fs.existsSync(resolved)) throw new Error(`Nested run '${run.id}' session file does not exist: ${sessionFile}`);
|
|
455
|
+
const stat = fs.lstatSync(resolved);
|
|
456
|
+
if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`Nested run '${run.id}' session file is not a regular file: ${sessionFile}`);
|
|
457
|
+
const realSessionFile = fs.realpathSync(resolved);
|
|
458
|
+
const trustedRoots = trustedSessionRoots
|
|
459
|
+
.filter((root) => fs.existsSync(root))
|
|
460
|
+
.map((root) => fs.realpathSync(root));
|
|
461
|
+
if (!trustedRoots.some((root) => pathWithin(root, realSessionFile))) {
|
|
462
|
+
throw new Error(`Nested run '${run.id}' session file is outside trusted nested session roots: ${sessionFile}`);
|
|
463
|
+
}
|
|
464
|
+
if (!realSessionFile.split(path.sep).includes(run.id)) {
|
|
465
|
+
throw new Error(`Nested run '${run.id}' session file is not under that nested run's session directory: ${sessionFile}`);
|
|
466
|
+
}
|
|
467
|
+
return realSessionFile;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function resolveNestedResumeTarget(match: ResolvedSubagentRunId & { kind: "nested" }, trustedSessionRoots: string[]): NestedResumeSourceTarget {
|
|
471
|
+
const run = match.match.run;
|
|
472
|
+
if (run.state === "running" || run.state === "queued") throw new Error(`Nested run '${run.id}' is live; route the follow-up to the owner process instead.`);
|
|
473
|
+
const agent = nestedRunAgent(run);
|
|
474
|
+
if (!agent) throw new Error(`Could not determine child agent for nested run '${run.id}'.`);
|
|
475
|
+
const state = run.state === "complete" || run.state === "failed" || run.state === "paused" ? run.state : "failed";
|
|
476
|
+
const asyncDir = resolveNestedAsyncDir(match.match.rootRunId, run);
|
|
477
|
+
return {
|
|
478
|
+
kind: "revive",
|
|
479
|
+
source: "nested",
|
|
480
|
+
runId: run.id,
|
|
481
|
+
state,
|
|
482
|
+
agent,
|
|
483
|
+
index: 0,
|
|
484
|
+
intercomTarget: resolveSubagentIntercomTarget(run.id, agent, 0),
|
|
485
|
+
cwd: asyncDir ? path.dirname(asyncDir) : undefined,
|
|
486
|
+
sessionFile: validateNestedSessionFile(run, trustedSessionRoots),
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function waitForNestedControlResult(target: ResolvedSubagentRunId & { kind: "nested" }, requestId: string, timeoutMs = 1_000) {
|
|
491
|
+
const deadline = Date.now() + timeoutMs;
|
|
492
|
+
while (Date.now() < deadline) {
|
|
493
|
+
const result = readNestedControlResults(target.match.route).find((candidate) => candidate.requestId === requestId && candidate.targetRunId === target.match.run.id);
|
|
494
|
+
if (result) return result;
|
|
495
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
496
|
+
}
|
|
497
|
+
return undefined;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
async function sendNestedControlRequest(target: ResolvedSubagentRunId & { kind: "nested" }, action: "interrupt" | "resume", message?: string) {
|
|
501
|
+
const requestId = randomUUID();
|
|
502
|
+
writeNestedControlRequest(target.match.route, {
|
|
503
|
+
ts: Date.now(),
|
|
504
|
+
requestId,
|
|
505
|
+
targetRunId: target.match.run.id,
|
|
506
|
+
action,
|
|
507
|
+
...(message ? { message } : {}),
|
|
508
|
+
});
|
|
509
|
+
return waitForNestedControlResult(target, requestId);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function directNestedAsyncInterrupt(target: ResolvedSubagentRunId & { kind: "nested" }): AgentToolResult<Details> | undefined {
|
|
513
|
+
const run = target.match.run;
|
|
514
|
+
const asyncDir = resolveNestedAsyncDir(target.match.rootRunId, run);
|
|
515
|
+
if (!asyncDir) return undefined;
|
|
516
|
+
const status = readStatus(asyncDir);
|
|
517
|
+
const pid = typeof status?.pid === "number" && status.pid > 0 ? status.pid : run.pid;
|
|
518
|
+
if (!status || status.state !== "running" || typeof pid !== "number" || pid <= 0) return undefined;
|
|
519
|
+
try {
|
|
520
|
+
process.kill(pid, ASYNC_INTERRUPT_SIGNAL);
|
|
521
|
+
return { content: [{ type: "text", text: `Interrupt requested for nested async run ${run.id}.` }], details: { mode: "management", results: [] } };
|
|
522
|
+
} catch (error) {
|
|
523
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
524
|
+
return { content: [{ type: "text", text: `Failed to interrupt nested async run ${run.id}: ${message}` }], isError: true, details: { mode: "management", results: [] } };
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
async function interruptNestedRun(target: ResolvedSubagentRunId & { kind: "nested" }): Promise<AgentToolResult<Details>> {
|
|
529
|
+
const run = target.match.run;
|
|
530
|
+
if (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: [] } };
|
|
531
|
+
if (run.state === "failed") return { content: [{ type: "text", text: `Nested run ${run.id} has failed and cannot be interrupted.` }], isError: true, details: { mode: "management", results: [] } };
|
|
532
|
+
if (run.state === "paused") return { content: [{ type: "text", text: `Nested run ${run.id} is already paused.` }], isError: true, details: { mode: "management", results: [] } };
|
|
533
|
+
const result = await sendNestedControlRequest(target, "interrupt");
|
|
534
|
+
if (result) return { content: [{ type: "text", text: result.message }], isError: result.ok ? undefined : true, details: { mode: "management", results: [] } };
|
|
535
|
+
const direct = directNestedAsyncInterrupt(target);
|
|
536
|
+
if (direct) return direct;
|
|
537
|
+
return { 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: [] } };
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
async function resumeLiveNestedRun(input: { target: ResolvedSubagentRunId & { kind: "nested" }; message: string }): Promise<AgentToolResult<Details>> {
|
|
541
|
+
const run = input.target.match.run;
|
|
542
|
+
const result = await sendNestedControlRequest(input.target, "resume", input.message);
|
|
543
|
+
if (result) return { content: [{ type: "text", text: result.message }], isError: result.ok ? undefined : true, details: { mode: "management", results: [] } };
|
|
544
|
+
return { 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: [] } };
|
|
545
|
+
}
|
|
546
|
+
|
|
395
547
|
async function resumeAsyncRun(input: {
|
|
396
548
|
params: SubagentParamsLike;
|
|
397
549
|
requestCwd: string;
|
|
@@ -408,8 +560,22 @@ async function resumeAsyncRun(input: {
|
|
|
408
560
|
}
|
|
409
561
|
|
|
410
562
|
let target: ResumeSourceTarget;
|
|
563
|
+
const parentSessionFile = input.ctx.sessionManager.getSessionFile() ?? null;
|
|
411
564
|
try {
|
|
412
|
-
|
|
565
|
+
const requestedId = input.params.id ?? input.params.runId;
|
|
566
|
+
const resolved = requestedId ? resolveSubagentRunId(requestedId, { state: input.deps.state, nested: nestedResolutionScopeForExecutor(input.deps) }) : undefined;
|
|
567
|
+
if (resolved?.kind === "nested") {
|
|
568
|
+
if (resolved.match.run.state === "running" || resolved.match.run.state === "queued") {
|
|
569
|
+
return resumeLiveNestedRun({ target: resolved, message: followUp });
|
|
570
|
+
}
|
|
571
|
+
const trustedSessionRoots = [
|
|
572
|
+
...(input.deps.config.defaultSessionDir ? [path.resolve(input.deps.expandTilde(input.deps.config.defaultSessionDir))] : []),
|
|
573
|
+
...(parentSessionFile ? [input.deps.getSubagentSessionRoot(parentSessionFile)] : []),
|
|
574
|
+
];
|
|
575
|
+
target = resolveNestedResumeTarget(resolved, trustedSessionRoots);
|
|
576
|
+
} else {
|
|
577
|
+
target = resolveResumeTarget(input.params, input.deps.state);
|
|
578
|
+
}
|
|
413
579
|
} catch (error) {
|
|
414
580
|
const message = error instanceof Error ? error.message : String(error);
|
|
415
581
|
return { content: [{ type: "text", text: message }], isError: true, details: { mode: "management", results: [] } };
|
|
@@ -445,7 +611,6 @@ async function resumeAsyncRun(input: {
|
|
|
445
611
|
};
|
|
446
612
|
}
|
|
447
613
|
|
|
448
|
-
const parentSessionFile = input.ctx.sessionManager.getSessionFile() ?? null;
|
|
449
614
|
input.deps.state.currentSessionId = resolveCurrentSessionId(input.ctx.sessionManager);
|
|
450
615
|
const effectiveCwd = target.cwd ?? input.requestCwd;
|
|
451
616
|
const scope: AgentScope = resolveExecutionAgentScope(input.params.agentScope);
|
|
@@ -502,7 +667,7 @@ async function resumeAsyncRun(input: {
|
|
|
502
667
|
|
|
503
668
|
const revivedId = result.details.asyncId ?? runId;
|
|
504
669
|
const revivedTarget = intercomBridge.active ? resolveSubagentIntercomTarget(revivedId, target.agent, 0) : undefined;
|
|
505
|
-
const sourceLabel = target.source
|
|
670
|
+
const sourceLabel = target.source;
|
|
506
671
|
const lines = [
|
|
507
672
|
`Revived ${sourceLabel} subagent from ${target.runId}.`,
|
|
508
673
|
`Revived run: ${revivedId}`,
|
|
@@ -539,6 +704,7 @@ async function emitForegroundResultIntercom(input: {
|
|
|
539
704
|
mode: SubagentRunMode;
|
|
540
705
|
results: SingleResult[];
|
|
541
706
|
chainSteps?: number;
|
|
707
|
+
nestedChildren?: NestedRunSummary[];
|
|
542
708
|
}): Promise<ReturnType<typeof buildSubagentResultIntercomPayload> | null> {
|
|
543
709
|
if (!input.intercomBridge.active || !input.intercomBridge.orchestratorTarget) return null;
|
|
544
710
|
const children = input.results.flatMap((result, index) => result.detached ? [] : [{
|
|
@@ -560,7 +726,7 @@ async function emitForegroundResultIntercom(input: {
|
|
|
560
726
|
runId: input.runId,
|
|
561
727
|
mode: input.mode,
|
|
562
728
|
source: "foreground",
|
|
563
|
-
children,
|
|
729
|
+
children: attachNestedChildrenToResultChildren(input.runId, children, input.nestedChildren),
|
|
564
730
|
...(typeof input.chainSteps === "number" ? { chainSteps: input.chainSteps } : {}),
|
|
565
731
|
});
|
|
566
732
|
const delivered = await deliverSubagentResultIntercomEvent(input.pi.events, payload);
|
|
@@ -574,6 +740,7 @@ async function maybeBuildForegroundIntercomReceipt(input: {
|
|
|
574
740
|
runId: string;
|
|
575
741
|
mode: SubagentRunMode;
|
|
576
742
|
details: Details;
|
|
743
|
+
nestedChildren?: NestedRunSummary[];
|
|
577
744
|
}): Promise<{ text: string; details: Details } | null> {
|
|
578
745
|
const payload = await emitForegroundResultIntercom({
|
|
579
746
|
pi: input.pi,
|
|
@@ -582,6 +749,7 @@ async function maybeBuildForegroundIntercomReceipt(input: {
|
|
|
582
749
|
mode: input.mode,
|
|
583
750
|
results: input.details.results,
|
|
584
751
|
...(typeof input.details.totalSteps === "number" ? { chainSteps: input.details.totalSteps } : {}),
|
|
752
|
+
...(input.nestedChildren?.length ? { nestedChildren: input.nestedChildren } : {}),
|
|
585
753
|
});
|
|
586
754
|
if (!payload) return null;
|
|
587
755
|
return {
|
|
@@ -851,6 +1019,7 @@ function runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentTool
|
|
|
851
1019
|
effectiveAsync,
|
|
852
1020
|
controlConfig,
|
|
853
1021
|
intercomBridge,
|
|
1022
|
+
nestedRoute,
|
|
854
1023
|
} = data;
|
|
855
1024
|
const hasChain = (params.chain?.length ?? 0) > 0;
|
|
856
1025
|
const hasTasks = (params.tasks?.length ?? 0) > 0;
|
|
@@ -881,7 +1050,7 @@ function runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentTool
|
|
|
881
1050
|
|
|
882
1051
|
if (!isAsyncAvailable()) {
|
|
883
1052
|
return {
|
|
884
|
-
content: [{ type: "text", text:
|
|
1053
|
+
content: [{ type: "text", text: `Async mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the ${APP_NAME}-subagents package dependencies are installed.` }],
|
|
885
1054
|
isError: true,
|
|
886
1055
|
details: { mode: "single" as const, results: [] },
|
|
887
1056
|
};
|
|
@@ -941,6 +1110,7 @@ function runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentTool
|
|
|
941
1110
|
controlConfig,
|
|
942
1111
|
controlIntercomTarget,
|
|
943
1112
|
childIntercomTarget,
|
|
1113
|
+
nestedRoute,
|
|
944
1114
|
});
|
|
945
1115
|
}
|
|
946
1116
|
|
|
@@ -968,6 +1138,7 @@ function runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentTool
|
|
|
968
1138
|
controlConfig,
|
|
969
1139
|
controlIntercomTarget,
|
|
970
1140
|
childIntercomTarget,
|
|
1141
|
+
nestedRoute,
|
|
971
1142
|
});
|
|
972
1143
|
}
|
|
973
1144
|
|
|
@@ -981,7 +1152,7 @@ function runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentTool
|
|
|
981
1152
|
};
|
|
982
1153
|
}
|
|
983
1154
|
const rawOutput = params.output !== undefined ? params.output : a.output;
|
|
984
|
-
const effectiveOutput
|
|
1155
|
+
const effectiveOutput = normalizeSingleOutputOverride(rawOutput, a.output);
|
|
985
1156
|
const effectiveOutputMode = params.outputMode ?? "inline";
|
|
986
1157
|
const normalizedSkills = normalizeSkillInput(params.skill);
|
|
987
1158
|
const skills = normalizedSkills === false ? [] : normalizedSkills;
|
|
@@ -1010,6 +1181,7 @@ function runAsyncPath(data: ExecutionContextData, deps: ExecutorDeps): AgentTool
|
|
|
1010
1181
|
controlConfig,
|
|
1011
1182
|
controlIntercomTarget,
|
|
1012
1183
|
childIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(agent, index) : undefined,
|
|
1184
|
+
nestedRoute,
|
|
1013
1185
|
});
|
|
1014
1186
|
}
|
|
1015
1187
|
|
|
@@ -1062,6 +1234,7 @@ async function runChainPath(data: ExecutionContextData, deps: ExecutorDeps): Pro
|
|
|
1062
1234
|
childIntercomTarget: childIntercomTarget ? (agent, index) => childIntercomTarget(runId, agent, index) : undefined,
|
|
1063
1235
|
orchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,
|
|
1064
1236
|
foregroundControl,
|
|
1237
|
+
nestedRoute: foregroundControl?.nestedRoute,
|
|
1065
1238
|
chainSkills,
|
|
1066
1239
|
chainDir: params.chainDir,
|
|
1067
1240
|
maxSubagentDepth: currentMaxSubagentDepth,
|
|
@@ -1072,7 +1245,7 @@ async function runChainPath(data: ExecutionContextData, deps: ExecutorDeps): Pro
|
|
|
1072
1245
|
if (chainResult.requestedAsync) {
|
|
1073
1246
|
if (!isAsyncAvailable()) {
|
|
1074
1247
|
return {
|
|
1075
|
-
content: [{ type: "text", text:
|
|
1248
|
+
content: [{ type: "text", text: `Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the ${APP_NAME}-subagents package dependencies are installed.` }],
|
|
1076
1249
|
isError: true,
|
|
1077
1250
|
details: { mode: "chain" as const, results: [] },
|
|
1078
1251
|
};
|
|
@@ -1106,10 +1279,12 @@ async function runChainPath(data: ExecutionContextData, deps: ExecutorDeps): Pro
|
|
|
1106
1279
|
controlConfig,
|
|
1107
1280
|
controlIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,
|
|
1108
1281
|
childIntercomTarget: data.intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(id, agent, index) : undefined,
|
|
1282
|
+
nestedRoute: data.nestedRoute,
|
|
1109
1283
|
});
|
|
1110
1284
|
}
|
|
1111
1285
|
|
|
1112
1286
|
const chainDetails = chainResult.details ? compactForegroundDetails({ ...chainResult.details, runId }) : undefined;
|
|
1287
|
+
if (foregroundControl) updateForegroundNestedProjection(foregroundControl);
|
|
1113
1288
|
if (chainDetails) rememberForegroundRun(deps.state, { runId, mode: "chain", cwd: effectiveCwd, results: chainDetails.results });
|
|
1114
1289
|
const intercomReceipt = chainDetails && !chainDetails.results.some((result) => result.interrupted || result.detached)
|
|
1115
1290
|
? await maybeBuildForegroundIntercomReceipt({
|
|
@@ -1118,6 +1293,7 @@ async function runChainPath(data: ExecutionContextData, deps: ExecutorDeps): Pro
|
|
|
1118
1293
|
runId,
|
|
1119
1294
|
mode: "chain",
|
|
1120
1295
|
details: chainDetails,
|
|
1296
|
+
...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),
|
|
1121
1297
|
})
|
|
1122
1298
|
: null;
|
|
1123
1299
|
if (intercomReceipt) {
|
|
@@ -1314,6 +1490,7 @@ async function runForegroundParallelTasks(input: ForegroundParallelRunInput): Pr
|
|
|
1314
1490
|
onControlEvent: input.onControlEvent,
|
|
1315
1491
|
intercomSessionName: input.childIntercomTarget?.(task.agent, index),
|
|
1316
1492
|
orchestratorIntercomTarget: input.orchestratorIntercomTarget,
|
|
1493
|
+
nestedRoute: input.foregroundControl?.nestedRoute,
|
|
1317
1494
|
modelOverride: input.modelOverrides[index],
|
|
1318
1495
|
availableModels: input.availableModels,
|
|
1319
1496
|
preferredModelProvider: input.ctx.model?.provider,
|
|
@@ -1483,7 +1660,7 @@ async function runParallelPath(data: ExecutionContextData, deps: ExecutorDeps):
|
|
|
1483
1660
|
if (result.runInBackground) {
|
|
1484
1661
|
if (!isAsyncAvailable()) {
|
|
1485
1662
|
return {
|
|
1486
|
-
content: [{ type: "text", text:
|
|
1663
|
+
content: [{ type: "text", text: `Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the ${APP_NAME}-subagents package dependencies are installed.` }],
|
|
1487
1664
|
isError: true,
|
|
1488
1665
|
details: { mode: "parallel" as const, results: [] },
|
|
1489
1666
|
};
|
|
@@ -1640,12 +1817,14 @@ async function runParallelPath(data: ExecutionContextData, deps: ExecutorDeps):
|
|
|
1640
1817
|
};
|
|
1641
1818
|
}
|
|
1642
1819
|
|
|
1820
|
+
if (foregroundControl) updateForegroundNestedProjection(foregroundControl);
|
|
1643
1821
|
const intercomReceipt = await maybeBuildForegroundIntercomReceipt({
|
|
1644
1822
|
pi: deps.pi,
|
|
1645
1823
|
intercomBridge: data.intercomBridge,
|
|
1646
1824
|
runId,
|
|
1647
1825
|
mode: "parallel",
|
|
1648
1826
|
details,
|
|
1827
|
+
...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),
|
|
1649
1828
|
});
|
|
1650
1829
|
if (intercomReceipt) {
|
|
1651
1830
|
return {
|
|
@@ -1721,7 +1900,7 @@ async function runSinglePath(data: ExecutionContextData, deps: ExecutorDeps): Pr
|
|
|
1721
1900
|
);
|
|
1722
1901
|
let skillOverride: string[] | false | undefined = normalizeSkillInput(params.skill);
|
|
1723
1902
|
const rawOutput = params.output !== undefined ? params.output : agentConfig.output;
|
|
1724
|
-
let effectiveOutput
|
|
1903
|
+
let effectiveOutput = normalizeSingleOutputOverride(rawOutput, agentConfig.output);
|
|
1725
1904
|
const effectiveOutputMode = params.outputMode ?? "inline";
|
|
1726
1905
|
const currentMaxSubagentDepth = resolveCurrentMaxSubagentDepth(deps.config.maxSubagentDepth);
|
|
1727
1906
|
const maxSubagentDepth = resolveChildMaxSubagentDepth(currentMaxSubagentDepth, agentConfig.maxSubagentDepth);
|
|
@@ -1755,13 +1934,13 @@ async function runSinglePath(data: ExecutionContextData, deps: ExecutorDeps): Pr
|
|
|
1755
1934
|
task = result.templates[0]!;
|
|
1756
1935
|
const override = result.behaviorOverrides[0];
|
|
1757
1936
|
if (override?.model) modelOverride = override.model;
|
|
1758
|
-
if (override?.output !== undefined) effectiveOutput = override.output;
|
|
1937
|
+
if (override?.output !== undefined) effectiveOutput = normalizeSingleOutputOverride(override.output, agentConfig.output);
|
|
1759
1938
|
if (override?.skills !== undefined) skillOverride = override.skills;
|
|
1760
1939
|
|
|
1761
1940
|
if (result.runInBackground) {
|
|
1762
1941
|
if (!isAsyncAvailable()) {
|
|
1763
1942
|
return {
|
|
1764
|
-
content: [{ type: "text", text:
|
|
1943
|
+
content: [{ type: "text", text: `Background mode requires upstream jiti for TypeScript execution but it could not be found. Ensure the ${APP_NAME}-subagents package dependencies are installed.` }],
|
|
1765
1944
|
isError: true,
|
|
1766
1945
|
details: { mode: "single" as const, results: [] },
|
|
1767
1946
|
};
|
|
@@ -1875,6 +2054,7 @@ async function runSinglePath(data: ExecutionContextData, deps: ExecutorDeps): Pr
|
|
|
1875
2054
|
onControlEvent,
|
|
1876
2055
|
intercomSessionName: childIntercomTarget,
|
|
1877
2056
|
orchestratorIntercomTarget: data.intercomBridge.active ? data.intercomBridge.orchestratorTarget : undefined,
|
|
2057
|
+
nestedRoute: foregroundControl?.nestedRoute,
|
|
1878
2058
|
index: 0,
|
|
1879
2059
|
modelOverride,
|
|
1880
2060
|
availableModels,
|
|
@@ -1921,12 +2101,14 @@ async function runSinglePath(data: ExecutionContextData, deps: ExecutorDeps): Pr
|
|
|
1921
2101
|
rememberForegroundRun(deps.state, { runId, mode: "single", cwd: effectiveCwd, results: details.results });
|
|
1922
2102
|
|
|
1923
2103
|
if (!r.detached && !r.interrupted) {
|
|
2104
|
+
if (foregroundControl) updateForegroundNestedProjection(foregroundControl);
|
|
1924
2105
|
const intercomReceipt = await maybeBuildForegroundIntercomReceipt({
|
|
1925
2106
|
pi: deps.pi,
|
|
1926
2107
|
intercomBridge: data.intercomBridge,
|
|
1927
2108
|
runId,
|
|
1928
2109
|
mode: "single",
|
|
1929
2110
|
details,
|
|
2111
|
+
...(foregroundControl?.nestedChildren?.length ? { nestedChildren: foregroundControl.nestedChildren } : {}),
|
|
1930
2112
|
});
|
|
1931
2113
|
if (intercomReceipt) {
|
|
1932
2114
|
return {
|
|
@@ -2020,16 +2202,41 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2020
2202
|
};
|
|
2021
2203
|
}
|
|
2022
2204
|
if (params.action === "status") {
|
|
2023
|
-
const
|
|
2024
|
-
if (
|
|
2025
|
-
|
|
2205
|
+
const targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
|
|
2206
|
+
if (targetRunId) {
|
|
2207
|
+
try {
|
|
2208
|
+
const nestedScope = nestedResolutionScopeForExecutor(deps);
|
|
2209
|
+
const resolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedScope });
|
|
2210
|
+
if (resolved?.kind === "foreground") {
|
|
2211
|
+
const foreground = getForegroundControl(deps.state, resolved.id);
|
|
2212
|
+
if (foreground) return foregroundStatusResult(foreground);
|
|
2213
|
+
}
|
|
2214
|
+
} catch (error) {
|
|
2215
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2216
|
+
return { content: [{ type: "text", text: message }], isError: true, details: { mode: "management", results: [] } };
|
|
2217
|
+
}
|
|
2218
|
+
} else {
|
|
2219
|
+
const foreground = getForegroundControl(deps.state, undefined);
|
|
2220
|
+
if (foreground) return foregroundStatusResult(foreground);
|
|
2221
|
+
}
|
|
2222
|
+
return inspectSubagentStatus(paramsWithResolvedCwd, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });
|
|
2026
2223
|
}
|
|
2027
2224
|
if (params.action === "resume") {
|
|
2028
2225
|
return resumeAsyncRun({ params: paramsWithResolvedCwd, requestCwd, ctx, deps });
|
|
2029
2226
|
}
|
|
2030
2227
|
if (params.action === "interrupt") {
|
|
2031
2228
|
const targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;
|
|
2032
|
-
|
|
2229
|
+
let resolved: ResolvedSubagentRunId | undefined;
|
|
2230
|
+
if (targetRunId) {
|
|
2231
|
+
try {
|
|
2232
|
+
resolved = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });
|
|
2233
|
+
} catch (error) {
|
|
2234
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2235
|
+
return { content: [{ type: "text", text: message }], isError: true, details: { mode: "management", results: [] } };
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
if (resolved?.kind === "nested") return interruptNestedRun(resolved);
|
|
2239
|
+
const foreground = getForegroundControl(deps.state, resolved?.kind === "foreground" ? resolved.id : targetRunId);
|
|
2033
2240
|
if (foreground?.interrupt) {
|
|
2034
2241
|
const interrupted = foreground.interrupt();
|
|
2035
2242
|
if (interrupted) {
|
|
@@ -2046,7 +2253,7 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2046
2253
|
details: { mode: "management", results: [] },
|
|
2047
2254
|
};
|
|
2048
2255
|
}
|
|
2049
|
-
const asyncInterruptResult = interruptAsyncRun(deps.state, targetRunId);
|
|
2256
|
+
const asyncInterruptResult = interruptAsyncRun(deps.state, resolved?.kind === "async" ? resolved.id : targetRunId);
|
|
2050
2257
|
if (asyncInterruptResult) return asyncInterruptResult;
|
|
2051
2258
|
return {
|
|
2052
2259
|
content: [{ type: "text", text: "No interrupt-capable run found in this session." }],
|
|
@@ -2061,6 +2268,13 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2061
2268
|
details: { mode: "management" as const, results: [] },
|
|
2062
2269
|
};
|
|
2063
2270
|
}
|
|
2271
|
+
if (deps.allowMutatingManagementActions === false && MUTATING_MANAGEMENT_ACTIONS.has(params.action)) {
|
|
2272
|
+
return {
|
|
2273
|
+
content: [{ type: "text", text: `Action '${params.action}' is not available from child-safe subagent fanout mode.` }],
|
|
2274
|
+
isError: true,
|
|
2275
|
+
details: { mode: "management" as const, results: [] },
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2064
2278
|
return handleManagementAction(params.action, paramsWithResolvedCwd, { ...ctx, cwd: requestCwd });
|
|
2065
2279
|
}
|
|
2066
2280
|
|
|
@@ -2108,6 +2322,9 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2108
2322
|
? discoveredAgents.map((agent) => applyIntercomBridgeToAgent(agent, intercomBridge))
|
|
2109
2323
|
: discoveredAgents;
|
|
2110
2324
|
const runId = randomUUID().slice(0, 8);
|
|
2325
|
+
const inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();
|
|
2326
|
+
const nestedParentAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;
|
|
2327
|
+
const nestedRoute = inheritedNestedRoute ?? createNestedRoute(runId);
|
|
2111
2328
|
const shareEnabled = effectiveParams.share === true;
|
|
2112
2329
|
const hasChain = (effectiveParams.chain?.length ?? 0) > 0;
|
|
2113
2330
|
const hasTasks = (effectiveParams.tasks?.length ?? 0) > 0;
|
|
@@ -2189,6 +2406,7 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2189
2406
|
effectiveAsync,
|
|
2190
2407
|
controlConfig,
|
|
2191
2408
|
intercomBridge,
|
|
2409
|
+
nestedRoute,
|
|
2192
2410
|
};
|
|
2193
2411
|
|
|
2194
2412
|
const foregroundMode: "single" | "parallel" | "chain" = hasChain ? "chain" : hasTasks ? "parallel" : "single";
|
|
@@ -2202,6 +2420,7 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2202
2420
|
currentAgent: undefined,
|
|
2203
2421
|
currentIndex: undefined,
|
|
2204
2422
|
currentActivityState: undefined,
|
|
2423
|
+
nestedRoute,
|
|
2205
2424
|
interrupt: undefined,
|
|
2206
2425
|
};
|
|
2207
2426
|
if (foregroundControl) {
|
|
@@ -2209,14 +2428,92 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
|
|
|
2209
2428
|
deps.state.lastForegroundControlId = runId;
|
|
2210
2429
|
}
|
|
2211
2430
|
|
|
2431
|
+
const writeNestedForegroundEvent = (type: "subagent.nested.started" | "subagent.nested.completed", result?: AgentToolResult<Details>): void => {
|
|
2432
|
+
if (!inheritedNestedRoute || !nestedParentAddress) return;
|
|
2433
|
+
const now = Date.now();
|
|
2434
|
+
const details = result?.details;
|
|
2435
|
+
const state = type === "subagent.nested.started"
|
|
2436
|
+
? "running"
|
|
2437
|
+
: result?.isError || details?.results.some((child) => child.exitCode !== 0)
|
|
2438
|
+
? "failed"
|
|
2439
|
+
: details?.results.some((child) => child.interrupted)
|
|
2440
|
+
? "paused"
|
|
2441
|
+
: "complete";
|
|
2442
|
+
const errorText = result?.isError
|
|
2443
|
+
? result.content.find((item) => item.type === "text")?.text
|
|
2444
|
+
: undefined;
|
|
2445
|
+
const agentsForSummary = hasTasks && effectiveParams.tasks
|
|
2446
|
+
? effectiveParams.tasks.map((task) => task.agent)
|
|
2447
|
+
: hasChain && effectiveParams.chain
|
|
2448
|
+
? effectiveParams.chain.flatMap((step) => isParallelStep(step) ? step.parallel.map((task) => task.agent) : [(step as SequentialStep).agent])
|
|
2449
|
+
: effectiveParams.agent ? [effectiveParams.agent] : [];
|
|
2450
|
+
const leafIntercomTarget = intercomBridge.active && agentsForSummary[0]
|
|
2451
|
+
? resolveSubagentIntercomTarget(runId, agentsForSummary[0], 0)
|
|
2452
|
+
: undefined;
|
|
2453
|
+
try {
|
|
2454
|
+
writeNestedEvent(inheritedNestedRoute, {
|
|
2455
|
+
type,
|
|
2456
|
+
ts: now,
|
|
2457
|
+
parentRunId: nestedParentAddress.parentRunId,
|
|
2458
|
+
parentStepIndex: nestedParentAddress.parentStepIndex,
|
|
2459
|
+
child: {
|
|
2460
|
+
id: runId,
|
|
2461
|
+
parentRunId: nestedParentAddress.parentRunId,
|
|
2462
|
+
parentStepIndex: nestedParentAddress.parentStepIndex,
|
|
2463
|
+
depth: nestedParentAddress.depth,
|
|
2464
|
+
path: nestedParentAddress.path,
|
|
2465
|
+
ownerIntercomTarget: getEnvValue(SUBAGENT_INTERCOM_SESSION_NAME_ENV),
|
|
2466
|
+
leafIntercomTarget,
|
|
2467
|
+
intercomTarget: leafIntercomTarget,
|
|
2468
|
+
ownerState: state === "running" ? "live" : "gone",
|
|
2469
|
+
mode: foregroundMode,
|
|
2470
|
+
state,
|
|
2471
|
+
agent: agentsForSummary[0],
|
|
2472
|
+
agents: agentsForSummary,
|
|
2473
|
+
startedAt: foregroundControl?.startedAt ?? now,
|
|
2474
|
+
...(state !== "running" ? { endedAt: now } : {}),
|
|
2475
|
+
lastUpdate: now,
|
|
2476
|
+
...(errorText ? { error: errorText } : {}),
|
|
2477
|
+
...(details?.results.length ? { steps: details.results.map((child) => ({
|
|
2478
|
+
agent: child.agent,
|
|
2479
|
+
status: child.interrupted ? "paused" : child.exitCode === 0 ? "complete" : "failed",
|
|
2480
|
+
...(child.sessionFile ? { sessionFile: child.sessionFile } : {}),
|
|
2481
|
+
...(child.error ? { error: child.error } : {}),
|
|
2482
|
+
})) } : {}),
|
|
2483
|
+
},
|
|
2484
|
+
});
|
|
2485
|
+
} catch (error) {
|
|
2486
|
+
console.error("Failed to emit nested foreground status event:", error);
|
|
2487
|
+
}
|
|
2488
|
+
};
|
|
2489
|
+
|
|
2490
|
+
let nestedForegroundStarted = false;
|
|
2212
2491
|
try {
|
|
2213
2492
|
const asyncResult = runAsyncPath(execData, deps);
|
|
2214
2493
|
if (asyncResult) return withForkContext(asyncResult, effectiveParams.context);
|
|
2215
|
-
if (
|
|
2216
|
-
|
|
2217
|
-
|
|
2494
|
+
if (foregroundControl) {
|
|
2495
|
+
writeNestedForegroundEvent("subagent.nested.started");
|
|
2496
|
+
nestedForegroundStarted = true;
|
|
2497
|
+
}
|
|
2498
|
+
if (hasChain && effectiveParams.chain) {
|
|
2499
|
+
const result = await runChainPath(execData, deps);
|
|
2500
|
+
writeNestedForegroundEvent("subagent.nested.completed", result);
|
|
2501
|
+
return withForkContext(result, effectiveParams.context);
|
|
2502
|
+
}
|
|
2503
|
+
if (hasTasks && effectiveParams.tasks) {
|
|
2504
|
+
const result = await runParallelPath(execData, deps);
|
|
2505
|
+
writeNestedForegroundEvent("subagent.nested.completed", result);
|
|
2506
|
+
return withForkContext(result, effectiveParams.context);
|
|
2507
|
+
}
|
|
2508
|
+
if (hasSingle) {
|
|
2509
|
+
const result = await runSinglePath(execData, deps);
|
|
2510
|
+
writeNestedForegroundEvent("subagent.nested.completed", result);
|
|
2511
|
+
return withForkContext(result, effectiveParams.context);
|
|
2512
|
+
}
|
|
2218
2513
|
} catch (error) {
|
|
2219
|
-
|
|
2514
|
+
const errorResult = toExecutionErrorResult(effectiveParams, error);
|
|
2515
|
+
if (nestedForegroundStarted) writeNestedForegroundEvent("subagent.nested.completed", errorResult);
|
|
2516
|
+
return errorResult;
|
|
2220
2517
|
} finally {
|
|
2221
2518
|
if (foregroundControl) {
|
|
2222
2519
|
clearPendingForegroundControlNotices(deps.state, runId);
|