@bastani/atomic 0.8.13-0 → 0.8.14-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -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,14 +2,15 @@ import { execSync } from "node:child_process";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
import * as path from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { getProjectConfigDirs } from "@bastani/atomic";
|
|
6
6
|
import type { AgentConfig } from "../agents/agents.ts";
|
|
7
7
|
import type { ExtensionConfig, IntercomBridgeConfig, IntercomBridgeMode } from "../shared/types.ts";
|
|
8
|
+
import { getAgentDir } from "../shared/utils.ts";
|
|
8
9
|
|
|
9
10
|
const PI_INTERCOM_PACKAGE_NAME = "pi-intercom";
|
|
10
11
|
|
|
11
12
|
function defaultAgentDir(): string {
|
|
12
|
-
return
|
|
13
|
+
return getAgentDir();
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
function defaultIntercomExtensionDir(agentDir = defaultAgentDir()): string {
|
|
@@ -168,8 +169,9 @@ function packageEntryAllowsExtensions(entry: unknown): boolean {
|
|
|
168
169
|
function findNearestProjectConfigDir(cwd: string): string | undefined {
|
|
169
170
|
let current = path.resolve(cwd);
|
|
170
171
|
while (true) {
|
|
171
|
-
const configDir
|
|
172
|
-
|
|
172
|
+
for (const configDir of getProjectConfigDirs(current)) {
|
|
173
|
+
if (fs.existsSync(path.join(configDir, "settings.json"))) return configDir;
|
|
174
|
+
}
|
|
173
175
|
const parent = path.dirname(current);
|
|
174
176
|
if (parent === current) return undefined;
|
|
175
177
|
current = parent;
|
|
@@ -3,6 +3,8 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import {
|
|
4
4
|
type Details,
|
|
5
5
|
type IntercomEventBus,
|
|
6
|
+
type NestedRunSummary,
|
|
7
|
+
type PublicNestedRunSummary,
|
|
6
8
|
type SingleResult,
|
|
7
9
|
type SubagentResultIntercomChild,
|
|
8
10
|
type SubagentResultIntercomPayload,
|
|
@@ -60,6 +62,110 @@ function resolveGroupedStatus(children: SubagentResultIntercomChild[]): Subagent
|
|
|
60
62
|
return "failed";
|
|
61
63
|
}
|
|
62
64
|
|
|
65
|
+
function compactNestedRun(run: NestedRunSummary | PublicNestedRunSummary, depth = 0): PublicNestedRunSummary {
|
|
66
|
+
return {
|
|
67
|
+
id: run.id,
|
|
68
|
+
parentRunId: run.parentRunId,
|
|
69
|
+
...(run.parentStepIndex !== undefined ? { parentStepIndex: run.parentStepIndex } : {}),
|
|
70
|
+
...(run.parentAgent ? { parentAgent: run.parentAgent } : {}),
|
|
71
|
+
depth: run.depth,
|
|
72
|
+
path: run.path.slice(0, 4).map((part) => ({
|
|
73
|
+
runId: part.runId,
|
|
74
|
+
...(part.stepIndex !== undefined ? { stepIndex: part.stepIndex } : {}),
|
|
75
|
+
...(part.agent ? { agent: part.agent } : {}),
|
|
76
|
+
})),
|
|
77
|
+
...(run.asyncDir ? { asyncDir: run.asyncDir } : {}),
|
|
78
|
+
...(run.sessionId ? { sessionId: run.sessionId } : {}),
|
|
79
|
+
...(run.sessionFile ? { sessionFile: run.sessionFile } : {}),
|
|
80
|
+
...(run.intercomTarget ? { intercomTarget: run.intercomTarget } : {}),
|
|
81
|
+
...(run.ownerIntercomTarget ? { ownerIntercomTarget: run.ownerIntercomTarget } : {}),
|
|
82
|
+
...(run.leafIntercomTarget ? { leafIntercomTarget: run.leafIntercomTarget } : {}),
|
|
83
|
+
...(run.ownerState ? { ownerState: run.ownerState } : {}),
|
|
84
|
+
...(run.mode ? { mode: run.mode } : {}),
|
|
85
|
+
state: run.state,
|
|
86
|
+
...(run.agent ? { agent: run.agent } : {}),
|
|
87
|
+
...(run.agents?.length ? { agents: run.agents.slice(0, 12) } : {}),
|
|
88
|
+
...(run.currentStep !== undefined ? { currentStep: run.currentStep } : {}),
|
|
89
|
+
...(run.chainStepCount !== undefined ? { chainStepCount: run.chainStepCount } : {}),
|
|
90
|
+
...(run.parallelGroups?.length ? { parallelGroups: run.parallelGroups.slice(0, 8) } : {}),
|
|
91
|
+
...(run.activityState ? { activityState: run.activityState } : {}),
|
|
92
|
+
...(run.lastActivityAt !== undefined ? { lastActivityAt: run.lastActivityAt } : {}),
|
|
93
|
+
...(run.currentTool ? { currentTool: run.currentTool } : {}),
|
|
94
|
+
...(run.currentToolStartedAt !== undefined ? { currentToolStartedAt: run.currentToolStartedAt } : {}),
|
|
95
|
+
...(run.currentPath ? { currentPath: run.currentPath } : {}),
|
|
96
|
+
...(run.turnCount !== undefined ? { turnCount: run.turnCount } : {}),
|
|
97
|
+
...(run.toolCount !== undefined ? { toolCount: run.toolCount } : {}),
|
|
98
|
+
...(run.totalTokens ? { totalTokens: run.totalTokens } : {}),
|
|
99
|
+
...(run.startedAt !== undefined ? { startedAt: run.startedAt } : {}),
|
|
100
|
+
...(run.endedAt !== undefined ? { endedAt: run.endedAt } : {}),
|
|
101
|
+
...(run.lastUpdate !== undefined ? { lastUpdate: run.lastUpdate } : {}),
|
|
102
|
+
...(run.error ? { error: run.error } : {}),
|
|
103
|
+
...(run.steps?.length ? { steps: run.steps.slice(0, 12).map((step) => ({
|
|
104
|
+
agent: step.agent,
|
|
105
|
+
status: step.status,
|
|
106
|
+
...(step.sessionFile ? { sessionFile: step.sessionFile } : {}),
|
|
107
|
+
...(step.activityState ? { activityState: step.activityState } : {}),
|
|
108
|
+
...(step.lastActivityAt !== undefined ? { lastActivityAt: step.lastActivityAt } : {}),
|
|
109
|
+
...(step.currentTool ? { currentTool: step.currentTool } : {}),
|
|
110
|
+
...(step.currentToolStartedAt !== undefined ? { currentToolStartedAt: step.currentToolStartedAt } : {}),
|
|
111
|
+
...(step.currentPath ? { currentPath: step.currentPath } : {}),
|
|
112
|
+
...(step.turnCount !== undefined ? { turnCount: step.turnCount } : {}),
|
|
113
|
+
...(step.toolCount !== undefined ? { toolCount: step.toolCount } : {}),
|
|
114
|
+
...(step.startedAt !== undefined ? { startedAt: step.startedAt } : {}),
|
|
115
|
+
...(step.endedAt !== undefined ? { endedAt: step.endedAt } : {}),
|
|
116
|
+
...(step.error ? { error: step.error } : {}),
|
|
117
|
+
...(depth < 2 && step.children?.length ? { children: step.children.slice(0, 8).map((child) => compactNestedRun(child, depth + 1)) } : {}),
|
|
118
|
+
})) } : {}),
|
|
119
|
+
...(depth < 2 && run.children?.length ? { children: run.children.slice(0, 8).map((child) => compactNestedRun(child, depth + 1)) } : {}),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function compactNestedResultChildren(children: Array<NestedRunSummary | PublicNestedRunSummary> | undefined): PublicNestedRunSummary[] | undefined {
|
|
124
|
+
if (!children?.length) return undefined;
|
|
125
|
+
return children.slice(0, 16).map((child) => compactNestedRun(child));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function attachNestedChildrenToResultChildren(
|
|
129
|
+
runId: string,
|
|
130
|
+
children: SubagentResultIntercomChild[],
|
|
131
|
+
nestedChildren: NestedRunSummary[] | undefined,
|
|
132
|
+
): SubagentResultIntercomChild[] {
|
|
133
|
+
const compact = compactNestedResultChildren(nestedChildren);
|
|
134
|
+
if (!compact?.length) return children.map((child) => ({ ...child, children: compactNestedResultChildren(child.children) }));
|
|
135
|
+
return children.map((child, index) => {
|
|
136
|
+
const childIndex = child.index ?? index;
|
|
137
|
+
const alreadyAttachedIds = new Set(child.children?.map((nested) => nested.id) ?? []);
|
|
138
|
+
const attached = compact.filter((nested) => nested.parentRunId === runId && nested.parentStepIndex === childIndex && !alreadyAttachedIds.has(nested.id));
|
|
139
|
+
const fallbackAttached = children.length === 1
|
|
140
|
+
? compact.filter((nested) => nested.parentRunId === runId && nested.parentStepIndex === undefined && !alreadyAttachedIds.has(nested.id))
|
|
141
|
+
: [];
|
|
142
|
+
const merged = compactNestedResultChildren([...(child.children ?? []), ...attached, ...fallbackAttached]);
|
|
143
|
+
return merged?.length ? { ...child, children: merged } : { ...child, children: undefined };
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function formatNestedResultLines(children: PublicNestedRunSummary[] | undefined): string[] {
|
|
148
|
+
if (!children?.length) return [];
|
|
149
|
+
const lines = ["Nested subagents:"];
|
|
150
|
+
let remaining = 10;
|
|
151
|
+
const append = (runs: PublicNestedRunSummary[] | undefined, indent: string): void => {
|
|
152
|
+
for (const run of runs ?? []) {
|
|
153
|
+
if (remaining <= 0) {
|
|
154
|
+
lines.push(`${indent}↳ +more nested runs; inspect status for full tree`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
remaining--;
|
|
158
|
+
const label = run.agent ?? run.agents?.join("+") ?? run.id;
|
|
159
|
+
lines.push(`${indent}↳ ${label} — ${run.state} [${run.id}]`);
|
|
160
|
+
if (run.sessionFile) lines.push(`${indent} Session: ${run.sessionFile}`);
|
|
161
|
+
append(run.children, `${indent} `);
|
|
162
|
+
for (const step of run.steps ?? []) append(step.children, `${indent} `);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
append(children, "");
|
|
166
|
+
return lines;
|
|
167
|
+
}
|
|
168
|
+
|
|
63
169
|
interface GroupedResultIntercomMessageInput {
|
|
64
170
|
to: string;
|
|
65
171
|
runId: string;
|
|
@@ -128,6 +234,7 @@ function formatSubagentResultIntercomMessage(input: {
|
|
|
128
234
|
if (child.intercomTarget) lines.push(`${input.source === "async" ? "Previous intercom target" : "Run intercom target"}: ${child.intercomTarget}`);
|
|
129
235
|
if (child.artifactPath) lines.push(`Output artifact: ${child.artifactPath}`);
|
|
130
236
|
if (child.sessionPath) lines.push(`Session: ${child.sessionPath}`);
|
|
237
|
+
lines.push(...formatNestedResultLines(child.children));
|
|
131
238
|
lines.push("Summary:");
|
|
132
239
|
lines.push(child.summary);
|
|
133
240
|
}
|
|
@@ -139,6 +246,7 @@ export function buildSubagentResultIntercomPayload(input: GroupedResultIntercomM
|
|
|
139
246
|
const children = input.children.map((child) => ({
|
|
140
247
|
...child,
|
|
141
248
|
summary: child.summary.trim() || "(no output)",
|
|
249
|
+
children: compactNestedResultChildren(child.children),
|
|
142
250
|
}));
|
|
143
251
|
const status = resolveGroupedStatus(children);
|
|
144
252
|
const summary = formatStatusCounts(countStatuses(children));
|
|
@@ -169,7 +277,7 @@ export async function deliverSubagentResultIntercomEvent(
|
|
|
169
277
|
payload: SubagentResultIntercomPayload,
|
|
170
278
|
timeoutMs = 500,
|
|
171
279
|
): Promise<boolean> {
|
|
172
|
-
return deliverSubagentIntercomMessageEvent(events, payload.to, payload.message, timeoutMs, payload);
|
|
280
|
+
return deliverSubagentIntercomMessageEvent(events, payload.to, payload.message, timeoutMs, payload as unknown as Record<string, unknown>);
|
|
173
281
|
}
|
|
174
282
|
|
|
175
283
|
export async function deliverSubagentIntercomMessageEvent(
|
|
@@ -8,10 +8,10 @@ import * as os from "node:os";
|
|
|
8
8
|
import * as path from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
|
-
import type
|
|
11
|
+
import { APP_NAME, getEnvValue, type ExtensionAPI } from "@bastani/atomic";
|
|
12
12
|
import type { AgentConfig } from "../../agents/agents.ts";
|
|
13
|
-
import { applyThinkingSuffix } from "../shared/pi-args.ts";
|
|
14
|
-
import { injectSingleOutputInstruction, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
|
|
13
|
+
import { applyThinkingSuffix, SUBAGENT_INTERCOM_SESSION_NAME_ENV } from "../shared/pi-args.ts";
|
|
14
|
+
import { injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
|
|
15
15
|
import { buildChainInstructions, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
|
|
16
16
|
import type { RunnerStep } from "../shared/parallel-utils.ts";
|
|
17
17
|
import { resolvePiPackageRoot } from "../shared/pi-spawn.ts";
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type ArtifactConfig,
|
|
25
25
|
type Details,
|
|
26
26
|
type MaxOutputConfig,
|
|
27
|
+
type NestedRouteInfo,
|
|
27
28
|
type ResolvedControlConfig,
|
|
28
29
|
type SubagentRunMode,
|
|
29
30
|
ASYNC_DIR,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
getAsyncConfigPath,
|
|
34
35
|
resolveChildMaxSubagentDepth,
|
|
35
36
|
} from "../../shared/types.ts";
|
|
37
|
+
import { NESTED_RUNS_DIR, nestedResultsPath, resolveInheritedNestedRouteFromEnv, resolveNestedParentAddressFromEnv, writeNestedEvent } from "../shared/nested-events.ts";
|
|
36
38
|
|
|
37
39
|
const require = createRequire(import.meta.url);
|
|
38
40
|
const piPackageRoot = resolvePiPackageRoot();
|
|
@@ -112,6 +114,7 @@ interface AsyncChainParams {
|
|
|
112
114
|
controlConfig?: ResolvedControlConfig;
|
|
113
115
|
controlIntercomTarget?: string;
|
|
114
116
|
childIntercomTarget?: (agent: string, index: number) => string | undefined;
|
|
117
|
+
nestedRoute?: NestedRouteInfo;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
interface AsyncSingleParams {
|
|
@@ -127,7 +130,7 @@ interface AsyncSingleParams {
|
|
|
127
130
|
sessionRoot?: string;
|
|
128
131
|
sessionFile?: string;
|
|
129
132
|
skills?: string[];
|
|
130
|
-
output?: string |
|
|
133
|
+
output?: string | boolean;
|
|
131
134
|
outputMode?: "inline" | "file-only";
|
|
132
135
|
modelOverride?: string;
|
|
133
136
|
availableModels?: AvailableModelInfo[];
|
|
@@ -137,6 +140,7 @@ interface AsyncSingleParams {
|
|
|
137
140
|
controlConfig?: ResolvedControlConfig;
|
|
138
141
|
controlIntercomTarget?: string;
|
|
139
142
|
childIntercomTarget?: (agent: string, index: number) => string | undefined;
|
|
143
|
+
nestedRoute?: NestedRouteInfo;
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
interface AsyncExecutionResult {
|
|
@@ -165,6 +169,13 @@ export function isAsyncAvailable(): boolean {
|
|
|
165
169
|
/**
|
|
166
170
|
* Spawn the async runner process
|
|
167
171
|
*/
|
|
172
|
+
export function writeAsyncRunnerConfig(cfg: object, suffix: string): string {
|
|
173
|
+
fs.mkdirSync(TEMP_ROOT_DIR, { recursive: true });
|
|
174
|
+
const cfgPath = getAsyncConfigPath(suffix);
|
|
175
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg), { mode: 0o600 });
|
|
176
|
+
return cfgPath;
|
|
177
|
+
}
|
|
178
|
+
|
|
168
179
|
function spawnRunner(cfg: object, suffix: string, cwd: string): { pid?: number; error?: string } {
|
|
169
180
|
if (!jitiCliPath) {
|
|
170
181
|
return { error: "upstream jiti for TypeScript execution could not be found; ensure package dependencies are installed" };
|
|
@@ -179,9 +190,7 @@ function spawnRunner(cfg: object, suffix: string, cwd: string): { pid?: number;
|
|
|
179
190
|
return { error: `cwd does not exist: ${cwd}` };
|
|
180
191
|
}
|
|
181
192
|
|
|
182
|
-
|
|
183
|
-
const cfgPath = getAsyncConfigPath(suffix);
|
|
184
|
-
fs.writeFileSync(cfgPath, JSON.stringify(cfg));
|
|
193
|
+
const cfgPath = writeAsyncRunnerConfig(cfg, suffix);
|
|
185
194
|
const runner = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-runner.ts");
|
|
186
195
|
|
|
187
196
|
const proc = spawn(process.execPath, [jitiCliPath, runner, cfgPath], {
|
|
@@ -191,7 +200,7 @@ function spawnRunner(cfg: object, suffix: string, cwd: string): { pid?: number;
|
|
|
191
200
|
windowsHide: true,
|
|
192
201
|
});
|
|
193
202
|
proc.on("error", (error) => {
|
|
194
|
-
console.error(`[
|
|
203
|
+
console.error(`[${APP_NAME}-subagents] async spawn failed: ${error.message}`);
|
|
195
204
|
});
|
|
196
205
|
if (typeof proc.pid !== "number") {
|
|
197
206
|
return { error: `async runner did not produce a pid for cwd: ${cwd}` };
|
|
@@ -237,6 +246,7 @@ export function executeAsyncChain(
|
|
|
237
246
|
controlConfig,
|
|
238
247
|
controlIntercomTarget,
|
|
239
248
|
childIntercomTarget,
|
|
249
|
+
nestedRoute,
|
|
240
250
|
} = params;
|
|
241
251
|
const resultMode = params.resultMode ?? "chain";
|
|
242
252
|
const chainSkills = params.chainSkills ?? [];
|
|
@@ -262,7 +272,11 @@ export function executeAsyncChain(
|
|
|
262
272
|
}
|
|
263
273
|
}
|
|
264
274
|
|
|
265
|
-
const
|
|
275
|
+
const inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();
|
|
276
|
+
const nestedAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;
|
|
277
|
+
const asyncDir = inheritedNestedRoute
|
|
278
|
+
? path.join(NESTED_RUNS_DIR, inheritedNestedRoute.rootRunId, id)
|
|
279
|
+
: path.join(ASYNC_DIR, id);
|
|
266
280
|
try {
|
|
267
281
|
fs.mkdirSync(asyncDir, { recursive: true });
|
|
268
282
|
} catch (error) {
|
|
@@ -318,12 +332,13 @@ export function executeAsyncChain(
|
|
|
318
332
|
cwd: stepCwd,
|
|
319
333
|
model,
|
|
320
334
|
thinking: resolveEffectiveThinking(model, a.thinking),
|
|
321
|
-
modelCandidates: buildModelCandidates(behavior.model ?? a.model, a.fallbackModels, availableModels, ctx.currentModelProvider, ctx.currentModel)
|
|
322
|
-
applyThinkingSuffix(candidate, a.thinking)
|
|
323
|
-
|
|
335
|
+
modelCandidates: buildModelCandidates(behavior.model ?? a.model, a.fallbackModels, availableModels, ctx.currentModelProvider, ctx.currentModel)
|
|
336
|
+
.map((candidate) => applyThinkingSuffix(candidate, a.thinking))
|
|
337
|
+
.filter((candidate): candidate is string => typeof candidate === "string"),
|
|
324
338
|
tools: a.tools,
|
|
325
339
|
extensions: a.extensions,
|
|
326
340
|
mcpDirectTools: a.mcpDirectTools,
|
|
341
|
+
completionGuard: a.completionGuard,
|
|
327
342
|
systemPrompt,
|
|
328
343
|
systemPromptMode: a.systemPromptMode,
|
|
329
344
|
inheritProjectContext: a.inheritProjectContext,
|
|
@@ -393,7 +408,7 @@ export function executeAsyncChain(
|
|
|
393
408
|
{
|
|
394
409
|
id,
|
|
395
410
|
steps,
|
|
396
|
-
resultPath: path.join(RESULTS_DIR, `${id}.json`),
|
|
411
|
+
resultPath: inheritedNestedRoute ? nestedResultsPath(inheritedNestedRoute.rootRunId, id) : path.join(RESULTS_DIR, `${id}.json`),
|
|
397
412
|
cwd: runnerCwd,
|
|
398
413
|
placeholder: "{previous}",
|
|
399
414
|
maxOutput,
|
|
@@ -411,6 +426,13 @@ export function executeAsyncChain(
|
|
|
411
426
|
controlIntercomTarget,
|
|
412
427
|
childIntercomTargets,
|
|
413
428
|
resultMode,
|
|
429
|
+
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
430
|
+
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
431
|
+
parentRunId: nestedAddress.parentRunId,
|
|
432
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
433
|
+
depth: nestedAddress.depth,
|
|
434
|
+
path: nestedAddress.path,
|
|
435
|
+
} : undefined,
|
|
414
436
|
},
|
|
415
437
|
id,
|
|
416
438
|
runnerCwd,
|
|
@@ -443,6 +465,40 @@ export function executeAsyncChain(
|
|
|
443
465
|
flatStepStart++;
|
|
444
466
|
}
|
|
445
467
|
}
|
|
468
|
+
if (inheritedNestedRoute && nestedAddress) {
|
|
469
|
+
const now = Date.now();
|
|
470
|
+
try {
|
|
471
|
+
writeNestedEvent(inheritedNestedRoute, {
|
|
472
|
+
type: "subagent.nested.started",
|
|
473
|
+
ts: now,
|
|
474
|
+
parentRunId: nestedAddress.parentRunId,
|
|
475
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
476
|
+
child: {
|
|
477
|
+
id,
|
|
478
|
+
parentRunId: nestedAddress.parentRunId,
|
|
479
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
480
|
+
depth: nestedAddress.depth,
|
|
481
|
+
path: nestedAddress.path,
|
|
482
|
+
asyncDir,
|
|
483
|
+
pid: spawnResult.pid,
|
|
484
|
+
ownerIntercomTarget: getEnvValue(SUBAGENT_INTERCOM_SESSION_NAME_ENV),
|
|
485
|
+
leafIntercomTarget: childIntercomTargets?.[0],
|
|
486
|
+
intercomTarget: childIntercomTargets?.[0],
|
|
487
|
+
ownerState: "live",
|
|
488
|
+
mode: resultMode,
|
|
489
|
+
state: "running",
|
|
490
|
+
agent: firstAgents[0],
|
|
491
|
+
agents: flatAgents,
|
|
492
|
+
chainStepCount: chain.length,
|
|
493
|
+
parallelGroups,
|
|
494
|
+
startedAt: now,
|
|
495
|
+
lastUpdate: now,
|
|
496
|
+
},
|
|
497
|
+
});
|
|
498
|
+
} catch (error) {
|
|
499
|
+
console.error("Failed to emit nested async start event:", error);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
446
502
|
ctx.pi.events.emit(SUBAGENT_ASYNC_STARTED_EVENT, {
|
|
447
503
|
id,
|
|
448
504
|
pid: spawnResult.pid,
|
|
@@ -460,6 +516,7 @@ export function executeAsyncChain(
|
|
|
460
516
|
parallelGroups,
|
|
461
517
|
cwd: runnerCwd,
|
|
462
518
|
asyncDir,
|
|
519
|
+
nestedRoute,
|
|
463
520
|
});
|
|
464
521
|
}
|
|
465
522
|
|
|
@@ -499,6 +556,7 @@ export function executeAsyncSingle(
|
|
|
499
556
|
controlConfig,
|
|
500
557
|
controlIntercomTarget,
|
|
501
558
|
childIntercomTarget,
|
|
559
|
+
nestedRoute,
|
|
502
560
|
} = params;
|
|
503
561
|
const task = params.task ?? "";
|
|
504
562
|
const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
|
|
@@ -512,7 +570,11 @@ export function executeAsyncSingle(
|
|
|
512
570
|
systemPrompt = systemPrompt ? `${systemPrompt}\n\n${injection}` : injection;
|
|
513
571
|
}
|
|
514
572
|
|
|
515
|
-
const
|
|
573
|
+
const inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();
|
|
574
|
+
const nestedAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;
|
|
575
|
+
const asyncDir = inheritedNestedRoute
|
|
576
|
+
? path.join(NESTED_RUNS_DIR, inheritedNestedRoute.rootRunId, id)
|
|
577
|
+
: path.join(ASYNC_DIR, id);
|
|
516
578
|
try {
|
|
517
579
|
fs.mkdirSync(asyncDir, { recursive: true });
|
|
518
580
|
} catch (error) {
|
|
@@ -524,7 +586,8 @@ export function executeAsyncSingle(
|
|
|
524
586
|
};
|
|
525
587
|
}
|
|
526
588
|
|
|
527
|
-
const
|
|
589
|
+
const effectiveOutput = normalizeSingleOutputOverride(params.output, agentConfig.output);
|
|
590
|
+
const outputPath = resolveSingleOutputPath(effectiveOutput, ctx.cwd, runnerCwd);
|
|
528
591
|
const outputMode = params.outputMode ?? "inline";
|
|
529
592
|
const validationError = validateFileOnlyOutputMode(outputMode, outputPath, `Async single run (${agent})`);
|
|
530
593
|
if (validationError) return formatAsyncStartError("single", validationError);
|
|
@@ -545,12 +608,13 @@ export function executeAsyncSingle(
|
|
|
545
608
|
cwd: runnerCwd,
|
|
546
609
|
model,
|
|
547
610
|
thinking: resolveEffectiveThinking(model, agentConfig.thinking),
|
|
548
|
-
modelCandidates: buildModelCandidates(params.modelOverride ?? agentConfig.model, agentConfig.fallbackModels, availableModels, ctx.currentModelProvider, ctx.currentModel)
|
|
549
|
-
applyThinkingSuffix(candidate, agentConfig.thinking)
|
|
550
|
-
|
|
611
|
+
modelCandidates: buildModelCandidates(params.modelOverride ?? agentConfig.model, agentConfig.fallbackModels, availableModels, ctx.currentModelProvider, ctx.currentModel)
|
|
612
|
+
.map((candidate) => applyThinkingSuffix(candidate, agentConfig.thinking))
|
|
613
|
+
.filter((candidate): candidate is string => typeof candidate === "string"),
|
|
551
614
|
tools: agentConfig.tools,
|
|
552
615
|
extensions: agentConfig.extensions,
|
|
553
616
|
mcpDirectTools: agentConfig.mcpDirectTools,
|
|
617
|
+
completionGuard: agentConfig.completionGuard,
|
|
554
618
|
systemPrompt,
|
|
555
619
|
systemPromptMode: agentConfig.systemPromptMode,
|
|
556
620
|
inheritProjectContext: agentConfig.inheritProjectContext,
|
|
@@ -562,7 +626,7 @@ export function executeAsyncSingle(
|
|
|
562
626
|
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, agentConfig.maxSubagentDepth),
|
|
563
627
|
},
|
|
564
628
|
],
|
|
565
|
-
resultPath: path.join(RESULTS_DIR, `${id}.json`),
|
|
629
|
+
resultPath: inheritedNestedRoute ? nestedResultsPath(inheritedNestedRoute.rootRunId, id) : path.join(RESULTS_DIR, `${id}.json`),
|
|
566
630
|
cwd: runnerCwd,
|
|
567
631
|
placeholder: "{previous}",
|
|
568
632
|
maxOutput,
|
|
@@ -580,6 +644,13 @@ export function executeAsyncSingle(
|
|
|
580
644
|
controlIntercomTarget,
|
|
581
645
|
childIntercomTargets: childIntercomTarget ? [childIntercomTarget(agent, 0)] : undefined,
|
|
582
646
|
resultMode: "single",
|
|
647
|
+
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
648
|
+
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
649
|
+
parentRunId: nestedAddress.parentRunId,
|
|
650
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
651
|
+
depth: nestedAddress.depth,
|
|
652
|
+
path: nestedAddress.path,
|
|
653
|
+
} : undefined,
|
|
583
654
|
},
|
|
584
655
|
id,
|
|
585
656
|
runnerCwd,
|
|
@@ -594,6 +665,39 @@ export function executeAsyncSingle(
|
|
|
594
665
|
}
|
|
595
666
|
|
|
596
667
|
if (spawnResult.pid) {
|
|
668
|
+
if (inheritedNestedRoute && nestedAddress) {
|
|
669
|
+
const now = Date.now();
|
|
670
|
+
try {
|
|
671
|
+
writeNestedEvent(inheritedNestedRoute, {
|
|
672
|
+
type: "subagent.nested.started",
|
|
673
|
+
ts: now,
|
|
674
|
+
parentRunId: nestedAddress.parentRunId,
|
|
675
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
676
|
+
child: {
|
|
677
|
+
id,
|
|
678
|
+
parentRunId: nestedAddress.parentRunId,
|
|
679
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
680
|
+
depth: nestedAddress.depth,
|
|
681
|
+
path: nestedAddress.path,
|
|
682
|
+
asyncDir,
|
|
683
|
+
pid: spawnResult.pid,
|
|
684
|
+
ownerIntercomTarget: getEnvValue(SUBAGENT_INTERCOM_SESSION_NAME_ENV),
|
|
685
|
+
leafIntercomTarget: childIntercomTarget?.(agent, 0),
|
|
686
|
+
intercomTarget: childIntercomTarget?.(agent, 0),
|
|
687
|
+
ownerState: "live",
|
|
688
|
+
mode: "single",
|
|
689
|
+
state: "running",
|
|
690
|
+
agent,
|
|
691
|
+
agents: [agent],
|
|
692
|
+
chainStepCount: 1,
|
|
693
|
+
startedAt: now,
|
|
694
|
+
lastUpdate: now,
|
|
695
|
+
},
|
|
696
|
+
});
|
|
697
|
+
} catch (error) {
|
|
698
|
+
console.error("Failed to emit nested async start event:", error);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
597
701
|
ctx.pi.events.emit(SUBAGENT_ASYNC_STARTED_EVENT, {
|
|
598
702
|
id,
|
|
599
703
|
pid: spawnResult.pid,
|
|
@@ -603,6 +707,7 @@ export function executeAsyncSingle(
|
|
|
603
707
|
task: task?.slice(0, 50),
|
|
604
708
|
cwd: runnerCwd,
|
|
605
709
|
asyncDir,
|
|
710
|
+
nestedRoute,
|
|
606
711
|
});
|
|
607
712
|
}
|
|
608
713
|
|
|
@@ -15,7 +15,8 @@ import {
|
|
|
15
15
|
} from "../../shared/types.ts";
|
|
16
16
|
import { readStatus } from "../../shared/utils.ts";
|
|
17
17
|
import { normalizeParallelGroups } from "./parallel-groups.ts";
|
|
18
|
-
import { reconcileAsyncRun } from "./stale-run-reconciler.ts";
|
|
18
|
+
import { reconcileAsyncRun, reconcileNestedAsyncDescendants } from "./stale-run-reconciler.ts";
|
|
19
|
+
import { hasLiveNestedDescendants, updateAsyncJobNestedProjection } from "../shared/nested-events.ts";
|
|
19
20
|
|
|
20
21
|
interface AsyncJobTrackerOptions {
|
|
21
22
|
completionRetentionMs?: number;
|
|
@@ -38,9 +39,14 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
38
39
|
renderWidget(ctx, jobs);
|
|
39
40
|
ctx.ui.requestRender?.();
|
|
40
41
|
};
|
|
41
|
-
const
|
|
42
|
+
const cancelCleanup = (asyncId: string) => {
|
|
42
43
|
const existingTimer = state.cleanupTimers.get(asyncId);
|
|
43
|
-
if (existingTimer)
|
|
44
|
+
if (!existingTimer) return;
|
|
45
|
+
clearTimeout(existingTimer);
|
|
46
|
+
state.cleanupTimers.delete(asyncId);
|
|
47
|
+
};
|
|
48
|
+
const scheduleCleanup = (asyncId: string) => {
|
|
49
|
+
cancelCleanup(asyncId);
|
|
44
50
|
const timer = setTimeout(() => {
|
|
45
51
|
state.cleanupTimers.delete(asyncId);
|
|
46
52
|
state.asyncJobs.delete(asyncId);
|
|
@@ -121,8 +127,27 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
121
127
|
let widgetChanged = false;
|
|
122
128
|
for (const job of state.asyncJobs.values()) {
|
|
123
129
|
const widgetStateBefore = widgetRenderKey(job);
|
|
130
|
+
let nestedRefreshFailed = false;
|
|
131
|
+
const refreshNestedProjection = () => {
|
|
132
|
+
try {
|
|
133
|
+
updateAsyncJobNestedProjection(job);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
nestedRefreshFailed = true;
|
|
136
|
+
console.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const reconcileNestedDescendants = () => {
|
|
140
|
+
try {
|
|
141
|
+
if (job.nestedRoute) reconcileNestedAsyncDescendants(job.nestedRoute, { resultsDir, kill: options.kill, now: options.now });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
nestedRefreshFailed = true;
|
|
144
|
+
console.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);
|
|
145
|
+
}
|
|
146
|
+
refreshNestedProjection();
|
|
147
|
+
};
|
|
124
148
|
try {
|
|
125
149
|
emitNewControlEvents(job);
|
|
150
|
+
reconcileNestedDescendants();
|
|
126
151
|
const reconciliation = reconcileAsyncRun(job.asyncDir, {
|
|
127
152
|
resultsDir,
|
|
128
153
|
kill: options.kill,
|
|
@@ -143,6 +168,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
143
168
|
if (status) {
|
|
144
169
|
const previousStatus = job.status;
|
|
145
170
|
job.status = status.state;
|
|
171
|
+
if (job.status !== "complete" && job.status !== "failed" && job.status !== "paused") cancelCleanup(job.asyncId);
|
|
146
172
|
job.sessionId = status.sessionId ?? job.sessionId;
|
|
147
173
|
job.activityState = status.activityState;
|
|
148
174
|
job.lastActivityAt = status.lastActivityAt ?? job.lastActivityAt;
|
|
@@ -169,6 +195,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
169
195
|
job.activeParallelGroup = Boolean(activeGroup);
|
|
170
196
|
job.agents = visibleSteps.map((step) => step.agent);
|
|
171
197
|
job.steps = visibleSteps;
|
|
198
|
+
refreshNestedProjection();
|
|
172
199
|
job.stepsTotal = visibleSteps.length;
|
|
173
200
|
job.runningSteps = visibleSteps.filter((step) => step.status === "running").length;
|
|
174
201
|
job.completedSteps = visibleSteps.filter((step) => step.status === "complete" || step.status === "completed").length;
|
|
@@ -178,7 +205,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
178
205
|
job.outputFile = status.outputFile ?? job.outputFile;
|
|
179
206
|
job.totalTokens = status.totalTokens ?? job.totalTokens;
|
|
180
207
|
job.sessionFile = status.sessionFile ?? job.sessionFile;
|
|
181
|
-
if ((job.status === "complete" || job.status === "failed" || job.status === "paused") && (previousStatus !== job.status || !state.cleanupTimers.has(job.asyncId))) {
|
|
208
|
+
if ((job.status === "complete" || job.status === "failed" || job.status === "paused") && !nestedRefreshFailed && !hasLiveNestedDescendants(job.nestedChildren) && (previousStatus !== job.status || !state.cleanupTimers.has(job.asyncId))) {
|
|
182
209
|
scheduleCleanup(job.asyncId);
|
|
183
210
|
}
|
|
184
211
|
if (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;
|
|
@@ -194,7 +221,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
194
221
|
job.status = "failed";
|
|
195
222
|
job.updatedAt = Date.now();
|
|
196
223
|
}
|
|
197
|
-
if (!state.cleanupTimers.has(job.asyncId)) {
|
|
224
|
+
if (!hasLiveNestedDescendants(job.nestedChildren) && !state.cleanupTimers.has(job.asyncId)) {
|
|
198
225
|
scheduleCleanup(job.asyncId);
|
|
199
226
|
}
|
|
200
227
|
}
|
|
@@ -228,6 +255,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
228
255
|
agents,
|
|
229
256
|
chainStepCount: info.chainStepCount,
|
|
230
257
|
parallelGroups: validParallelGroups,
|
|
258
|
+
nestedRoute: info.nestedRoute,
|
|
231
259
|
stepsTotal: firstGroupCount ?? agents?.length,
|
|
232
260
|
hasParallelGroups: validParallelGroups.length > 0,
|
|
233
261
|
activeParallelGroup: Boolean(firstGroupCount && firstGroupCount > 0),
|
|
@@ -245,15 +273,22 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
245
273
|
const asyncId = result.id;
|
|
246
274
|
if (!asyncId) return;
|
|
247
275
|
const job = state.asyncJobs.get(asyncId);
|
|
276
|
+
let nestedRefreshFailed = false;
|
|
248
277
|
if (job) {
|
|
249
278
|
job.status = result.success ? "complete" : "failed";
|
|
250
279
|
job.updatedAt = Date.now();
|
|
251
280
|
if (result.asyncDir) job.asyncDir = result.asyncDir;
|
|
281
|
+
try {
|
|
282
|
+
updateAsyncJobNestedProjection(job);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
nestedRefreshFailed = true;
|
|
285
|
+
console.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);
|
|
286
|
+
}
|
|
252
287
|
}
|
|
253
288
|
if (state.lastUiContext) {
|
|
254
289
|
rerenderWidget(state.lastUiContext);
|
|
255
290
|
}
|
|
256
|
-
scheduleCleanup(asyncId);
|
|
291
|
+
if (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);
|
|
257
292
|
};
|
|
258
293
|
|
|
259
294
|
const resetJobs = (ctx?: ExtensionContext) => {
|
|
@@ -149,6 +149,29 @@ function exactResultPath(resultsDir: string, runId: string): string | null {
|
|
|
149
149
|
return fs.existsSync(resultPath) ? resultPath : null;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
export function findAsyncRunPrefixMatches(prefix: string, asyncDirRoot: string, resultsDir: string): Array<{ id: string; location: AsyncRunLocation }> {
|
|
153
|
+
const requestedId = assertRunId(prefix, "id");
|
|
154
|
+
if (!requestedId) return [];
|
|
155
|
+
const asyncRoot = path.resolve(asyncDirRoot);
|
|
156
|
+
const resultRoot = path.resolve(resultsDir);
|
|
157
|
+
const matchingIds = [...new Set([
|
|
158
|
+
...prefixedRunIds(asyncRoot, requestedId),
|
|
159
|
+
...prefixedRunIds(resultRoot, requestedId, ".json"),
|
|
160
|
+
])].sort();
|
|
161
|
+
return matchingIds.map((id) => {
|
|
162
|
+
const asyncDir = path.join(asyncRoot, id);
|
|
163
|
+
assertInsideRoot(asyncRoot, asyncDir, "Async run directory");
|
|
164
|
+
return {
|
|
165
|
+
id,
|
|
166
|
+
location: {
|
|
167
|
+
asyncDir: fs.existsSync(asyncDir) ? asyncDir : null,
|
|
168
|
+
resultPath: exactResultPath(resultRoot, id),
|
|
169
|
+
resolvedId: id,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
152
175
|
export function resolveAsyncRunLocation(params: AsyncResumeParams, asyncDirRoot: string, resultsDir: string): AsyncRunLocation {
|
|
153
176
|
const asyncRoot = path.resolve(asyncDirRoot);
|
|
154
177
|
const resultRoot = path.resolve(resultsDir);
|
|
@@ -175,22 +198,12 @@ export function resolveAsyncRunLocation(params: AsyncResumeParams, asyncDirRoot:
|
|
|
175
198
|
};
|
|
176
199
|
}
|
|
177
200
|
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (matchingIds.length === 0) return { asyncDir: null, resultPath: null, resolvedId: requestedId };
|
|
183
|
-
if (matchingIds.length > 1) {
|
|
184
|
-
throw new Error(`Ambiguous async run id prefix '${requestedId}' matched: ${matchingIds.join(", ")}. Provide a longer id.`);
|
|
201
|
+
const matching = findAsyncRunPrefixMatches(requestedId, asyncRoot, resultRoot);
|
|
202
|
+
if (matching.length === 0) return { asyncDir: null, resultPath: null, resolvedId: requestedId };
|
|
203
|
+
if (matching.length > 1) {
|
|
204
|
+
throw new Error(`Ambiguous async run id prefix '${requestedId}' matched: ${matching.map((match) => match.id).join(", ")}. Provide a longer id.`);
|
|
185
205
|
}
|
|
186
|
-
|
|
187
|
-
const asyncDir = path.join(asyncRoot, resolvedId);
|
|
188
|
-
assertInsideRoot(asyncRoot, asyncDir, "Async run directory");
|
|
189
|
-
return {
|
|
190
|
-
asyncDir: fs.existsSync(asyncDir) ? asyncDir : null,
|
|
191
|
-
resultPath: exactResultPath(resultRoot, resolvedId),
|
|
192
|
-
resolvedId,
|
|
193
|
-
};
|
|
206
|
+
return matching[0]!.location;
|
|
194
207
|
}
|
|
195
208
|
|
|
196
209
|
function resultState(result: AsyncResultFile): AsyncStatus["state"] {
|