@prometheus-ai/agent 0.5.4 → 0.5.8
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 +30 -0
- package/dist/cli.js +25110 -0
- package/dist/types/async/index.d.ts +0 -1
- package/dist/types/async/job-manager.d.ts +33 -0
- package/dist/types/autolearn/controller.d.ts +25 -0
- package/dist/types/autolearn/managed-skills.d.ts +45 -0
- package/dist/types/autoresearch/state.d.ts +1 -1
- package/dist/types/autoresearch/tools/init-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/log-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/run-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/update-notes.d.ts +1 -1
- package/dist/types/autoresearch/types.d.ts +1 -1
- package/dist/types/capability/context-file.d.ts +0 -13
- package/dist/types/capability/mcp.d.ts +1 -0
- package/dist/types/capability/rule-buckets.d.ts +1 -1
- package/dist/types/capability/rule.d.ts +6 -1
- package/dist/types/capability/types.d.ts +0 -4
- package/dist/types/cli/args.d.ts +23 -3
- package/dist/types/cli/bench-cli.d.ts +78 -0
- package/dist/types/cli/claude-trace-cli.d.ts +7 -0
- package/dist/types/cli/dry-balance-cli.d.ts +16 -2
- package/dist/types/cli/gallery-cli.d.ts +43 -0
- package/dist/types/cli/gallery-fixtures/agentic.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/codeintel.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/edit.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/fs.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/index.d.ts +4 -0
- package/dist/types/cli/gallery-fixtures/interaction.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/memory.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/misc.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/search.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/shell.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/types.d.ts +55 -0
- package/dist/types/cli/gallery-fixtures/web.d.ts +2 -0
- package/dist/types/cli/gallery-screenshot.d.ts +35 -0
- package/dist/types/cli/grievances-cli.d.ts +1 -1
- package/dist/types/cli/list-models.d.ts +6 -14
- package/dist/types/cli/models-cli.d.ts +49 -0
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/cli/setup-model-picker.d.ts +14 -0
- package/dist/types/cli/startup-cwd.d.ts +2 -0
- package/dist/types/cli/update-cli.d.ts +13 -40
- package/dist/types/cli/usage-cli.d.ts +81 -0
- package/dist/types/cli-commands.d.ts +12 -0
- package/dist/types/collab/crypto.d.ts +7 -0
- package/dist/types/collab/guest.d.ts +37 -0
- package/dist/types/collab/host.d.ts +29 -0
- package/dist/types/collab/protocol.d.ts +119 -0
- package/dist/types/collab/relay-client.d.ts +22 -0
- package/dist/types/commands/bench.d.ts +29 -0
- package/dist/types/commands/gallery.d.ts +47 -0
- package/dist/types/commands/install.d.ts +1 -1
- package/dist/types/commands/join.d.ts +12 -0
- package/dist/types/commands/launch.d.ts +8 -4
- package/dist/types/commands/models.d.ts +33 -0
- package/dist/types/commands/read.d.ts +1 -1
- package/dist/types/commands/say.d.ts +24 -0
- package/dist/types/commands/token.d.ts +25 -0
- package/dist/types/commands/usage.d.ts +34 -0
- package/dist/types/commit/agentic/tools/analyze-file.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-file-diff.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-hunk.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-overview.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +1 -1
- package/dist/types/commit/agentic/tools/recent-commits.d.ts +1 -1
- package/dist/types/commit/agentic/tools/schemas.d.ts +1 -1
- package/dist/types/commit/agentic/tools/split-commit.d.ts +1 -1
- package/dist/types/commit/analysis/conventional.d.ts +2 -2
- package/dist/types/commit/analysis/summary.d.ts +2 -2
- package/dist/types/commit/changelog/generate.d.ts +3 -3
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/index.d.ts +3 -3
- package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
- package/dist/types/commit/model-selection.d.ts +10 -4
- package/dist/types/commit/shared-llm.d.ts +1 -1
- package/dist/types/config/api-key-resolver.d.ts +43 -0
- package/dist/types/config/append-only-context-mode.d.ts +2 -1
- package/dist/types/config/keybindings.d.ts +12 -7
- package/dist/types/config/model-discovery.d.ts +57 -0
- package/dist/types/config/model-equivalence.d.ts +1 -1
- package/dist/types/config/model-registry.d.ts +86 -222
- package/dist/types/config/model-resolver.d.ts +43 -12
- package/dist/types/config/model-roles.d.ts +29 -0
- package/dist/types/config/models-config-schema.d.ts +536 -43
- package/dist/types/config/models-config.d.ts +391 -0
- package/dist/types/config/settings-schema.d.ts +1202 -324
- package/dist/types/config/settings.d.ts +15 -3
- package/dist/types/dap/config.d.ts +14 -1
- package/dist/types/dap/types.d.ts +10 -0
- package/dist/types/debug/log-viewer.d.ts +1 -1
- package/dist/types/debug/raw-sse.d.ts +1 -1
- package/dist/types/debug/report-bundle.d.ts +3 -0
- package/dist/types/debug/terminal-info.d.ts +0 -1
- package/dist/types/discovery/at-imports.d.ts +15 -0
- package/dist/types/discovery/prometheus-extension-roots.d.ts +7 -7
- package/dist/types/edit/diff.d.ts +3 -2
- package/dist/types/edit/file-snapshot-store.d.ts +18 -0
- package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
- package/dist/types/edit/hashline/params.d.ts +1 -1
- package/dist/types/edit/index.d.ts +0 -1
- package/dist/types/edit/modes/apply-patch.d.ts +1 -1
- package/dist/types/edit/modes/patch.d.ts +1 -1
- package/dist/types/edit/modes/replace.d.ts +1 -1
- package/dist/types/edit/renderer.d.ts +1 -0
- package/dist/types/eval/__tests__/completion-bridge.test.d.ts +1 -0
- package/dist/types/eval/__tests__/helpers-local-roots.test.d.ts +1 -0
- package/dist/types/eval/__tests__/js-context-manager.test.d.ts +1 -0
- package/dist/types/eval/backend.d.ts +7 -2
- package/dist/types/eval/bridge-timeout.d.ts +1 -1
- package/dist/types/eval/completion-bridge.d.ts +25 -0
- package/dist/types/eval/idle-timeout.d.ts +1 -5
- package/dist/types/eval/js/context-manager.d.ts +1 -0
- package/dist/types/eval/js/executor.d.ts +2 -0
- package/dist/types/eval/js/index.d.ts +1 -1
- package/dist/types/eval/js/shared/helpers.d.ts +7 -1
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
- package/dist/types/eval/js/shared/runtime.d.ts +6 -1
- package/dist/types/eval/js/worker-protocol.d.ts +6 -0
- package/dist/types/eval/py/__tests__/prelude.test.d.ts +1 -0
- package/dist/types/eval/py/executor.d.ts +12 -0
- package/dist/types/eval/py/index.d.ts +1 -1
- package/dist/types/eval/py/kernel.d.ts +6 -1
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exa/index.d.ts +1 -19
- package/dist/types/exa/mcp-client.d.ts +10 -3
- package/dist/types/exa/types.d.ts +0 -83
- package/dist/types/exec/bash-executor.d.ts +7 -0
- package/dist/types/export/custom-share.d.ts +1 -2
- package/dist/types/export/html/index.d.ts +39 -0
- package/dist/types/export/html/template-js.d.ts +2 -0
- package/dist/types/export/share.d.ts +61 -0
- package/dist/types/export/ttsr.d.ts +14 -0
- package/dist/types/extensibility/custom-commands/types.d.ts +9 -4
- package/dist/types/extensibility/custom-tools/loader.d.ts +30 -4
- package/dist/types/extensibility/custom-tools/types.d.ts +16 -8
- package/dist/types/extensibility/extensions/index.d.ts +1 -1
- package/dist/types/extensibility/extensions/loader.d.ts +20 -1
- package/dist/types/extensibility/extensions/model-api.d.ts +17 -0
- package/dist/types/extensibility/extensions/runner.d.ts +5 -2
- package/dist/types/extensibility/extensions/types.d.ts +72 -11
- package/dist/types/extensibility/hooks/index.d.ts +2 -1
- package/dist/types/extensibility/hooks/loader.d.ts +1 -1
- package/dist/types/extensibility/hooks/types.d.ts +11 -5
- package/dist/types/extensibility/{legacy-pi-ai-shim.d.ts → legacy-package-ai-shim.d.ts} +2 -2
- package/dist/types/extensibility/plugins/{legacy-pi-compat.d.ts → legacy-package-compat.d.ts} +20 -3
- package/dist/types/extensibility/plugins/loader.d.ts +11 -0
- package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
- package/dist/types/extensibility/plugins/types.d.ts +2 -2
- package/dist/types/extensibility/shared-events.d.ts +3 -3
- package/dist/types/extensibility/skills.d.ts +10 -0
- package/dist/types/extensibility/slash-commands.d.ts +1 -11
- package/dist/types/goals/guided-setup.d.ts +18 -0
- package/dist/types/goals/state.d.ts +1 -1
- package/dist/types/goals/tools/goal-tool.d.ts +1 -1
- package/dist/types/hindsight/mental-models.d.ts +17 -8
- package/dist/types/hindsight/transcript.d.ts +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/history-protocol.d.ts +14 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/local-protocol.d.ts +14 -2
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/irc/bus.d.ts +79 -0
- package/dist/types/lib/xai-http.d.ts +1 -1
- package/dist/types/lsp/client.d.ts +10 -0
- package/dist/types/lsp/config.d.ts +2 -2
- package/dist/types/lsp/edits.d.ts +9 -0
- package/dist/types/lsp/format-options.d.ts +32 -0
- package/dist/types/lsp/index.d.ts +2 -7
- package/dist/types/lsp/types.d.ts +13 -1
- package/dist/types/lsp/utils.d.ts +6 -2
- package/dist/types/main.d.ts +23 -8
- package/dist/types/mcp/json-rpc.d.ts +5 -0
- package/dist/types/mcp/manager.d.ts +8 -0
- package/dist/types/mcp/oauth-discovery.d.ts +6 -1
- package/dist/types/mcp/oauth-flow.d.ts +13 -3
- package/dist/types/mcp/startup-events.d.ts +11 -0
- package/dist/types/mcp/tool-bridge.d.ts +2 -0
- package/dist/types/mcp/transports/stdio.d.ts +13 -0
- package/dist/types/mcp/types.d.ts +2 -0
- package/dist/types/memories/index.d.ts +7 -15
- package/dist/types/memories/storage.d.ts +0 -10
- package/dist/types/memory-backend/index.d.ts +3 -1
- package/dist/types/memory-backend/local-backend.d.ts +4 -3
- package/dist/types/memory-backend/resolve.d.ts +2 -2
- package/dist/types/memory-backend/runtime.d.ts +4 -0
- package/dist/types/memory-backend/types.d.ts +67 -2
- package/dist/types/mnemopi/config.d.ts +31 -1
- package/dist/types/mnemopi/state.d.ts +40 -2
- package/dist/types/modes/acp/acp-agent.d.ts +1 -2
- package/dist/types/modes/components/agent-dashboard.d.ts +17 -1
- package/dist/types/modes/components/agent-hub.d.ts +82 -0
- package/dist/types/modes/components/assistant-message.d.ts +5 -12
- package/dist/types/modes/components/bash-execution.d.ts +1 -1
- package/dist/types/modes/components/chat-block.d.ts +64 -0
- package/dist/types/modes/components/collab-prompt-message.d.ts +10 -0
- package/dist/types/modes/components/compaction-summary-message.d.ts +25 -5
- package/dist/types/modes/components/copy-selector.d.ts +1 -1
- package/dist/types/modes/components/custom-editor.d.ts +49 -2
- package/dist/types/modes/components/custom-editor.test.d.ts +1 -0
- package/dist/types/modes/components/dynamic-border.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
- package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
- package/dist/types/modes/components/footer.d.ts +1 -1
- package/dist/types/modes/components/hook-editor.d.ts +5 -0
- package/dist/types/modes/components/hook-input.d.ts +4 -0
- package/dist/types/modes/components/hook-selector.d.ts +5 -7
- package/dist/types/modes/components/index.d.ts +1 -0
- package/dist/types/modes/components/late-diagnostics-message.d.ts +20 -0
- package/dist/types/modes/components/logout-account-selector.d.ts +8 -0
- package/dist/types/modes/components/mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -1
- package/dist/types/modes/components/oauth-selector.d.ts +10 -1
- package/dist/types/modes/components/overlay-box.d.ts +17 -0
- package/dist/types/modes/components/plan-review-overlay.d.ts +61 -0
- package/dist/types/modes/components/plan-toc.d.ts +41 -0
- package/dist/types/modes/components/read-tool-group.d.ts +8 -0
- package/dist/types/modes/components/reset-usage-selector.d.ts +12 -0
- package/dist/types/modes/components/segment-track.d.ts +11 -6
- package/dist/types/modes/components/session-selector.d.ts +18 -9
- package/dist/types/modes/components/settings-defs.d.ts +9 -2
- package/dist/types/modes/components/settings-selector.d.ts +17 -4
- package/dist/types/modes/components/snapcompact-shape-preview.d.ts +31 -0
- package/dist/types/modes/components/status-line/component.d.ts +61 -0
- package/dist/types/modes/components/status-line/index.d.ts +1 -0
- package/dist/types/modes/components/status-line/types.d.ts +47 -3
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
- package/dist/types/modes/components/tool-execution.d.ts +49 -2
- package/dist/types/modes/components/transcript-container.d.ts +76 -26
- package/dist/types/modes/components/tree-selector.d.ts +2 -2
- package/dist/types/modes/components/ttsr-notification.d.ts +5 -1
- package/dist/types/modes/components/usage-row.d.ts +3 -0
- package/dist/types/modes/components/user-message-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message.d.ts +2 -1
- package/dist/types/modes/components/visual-truncate.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +12 -2
- package/dist/types/modes/controllers/command-controller.d.ts +3 -2
- package/dist/types/modes/controllers/event-controller.d.ts +7 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
- package/dist/types/modes/controllers/input-controller.d.ts +25 -3
- package/dist/types/modes/controllers/mcp-command-controller.d.ts +8 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +5 -2
- package/dist/types/modes/controllers/session-focus-controller.d.ts +31 -0
- package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
- package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
- package/dist/types/modes/controllers/tool-args-reveal.d.ts +43 -0
- package/dist/types/modes/gradient-highlight.d.ts +9 -4
- package/dist/types/modes/image-references.d.ts +14 -3
- package/dist/types/modes/index.d.ts +8 -7
- package/dist/types/modes/interactive-mode.d.ts +92 -16
- package/dist/types/modes/magic-keywords.d.ts +14 -2
- package/dist/types/modes/markdown-prose.d.ts +1 -1
- package/dist/types/modes/oauth-manual-input.d.ts +7 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +48 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +67 -2
- package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +113 -1
- package/dist/types/modes/runtime-init.d.ts +4 -0
- package/dist/types/modes/session-observer-registry.d.ts +9 -0
- package/dist/types/modes/setup-version.d.ts +11 -0
- package/dist/types/modes/setup-wizard/index.d.ts +7 -2
- package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +4 -1
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +11 -2
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +6 -2
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +42 -7
- package/dist/types/modes/types.d.ts +62 -13
- package/dist/types/modes/utils/context-usage.d.ts +6 -1
- package/dist/types/modes/utils/copy-targets.d.ts +21 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +4 -4
- package/dist/types/modes/workflow.d.ts +3 -3
- package/dist/types/plan-mode/approved-plan.d.ts +27 -8
- package/dist/types/plan-mode/plan-protection.d.ts +4 -4
- package/dist/types/registry/agent-lifecycle.d.ts +51 -0
- package/dist/types/registry/agent-registry.d.ts +33 -5
- package/dist/types/sdk.d.ts +46 -4
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +9 -3
- package/dist/types/session/agent-session.d.ts +136 -66
- package/dist/types/session/agent-storage.d.ts +2 -1
- package/dist/types/session/auth-broker-config.d.ts +4 -0
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/codex-auto-reset.d.ts +111 -0
- package/dist/types/session/indexed-session-storage.d.ts +3 -3
- package/dist/types/session/messages.d.ts +26 -15
- package/dist/types/session/session-context.d.ts +39 -0
- package/dist/types/session/session-entries.d.ts +159 -0
- package/dist/types/session/session-history-format.d.ts +12 -0
- package/dist/types/session/session-listing.d.ts +69 -0
- package/dist/types/session/session-loader.d.ts +16 -0
- package/dist/types/session/session-manager.d.ts +107 -440
- package/dist/types/session/session-migrations.d.ts +12 -0
- package/dist/types/session/session-paths.d.ts +25 -0
- package/dist/types/session/session-persistence.d.ts +8 -0
- package/dist/types/session/session-storage.d.ts +11 -7
- package/dist/types/session/snapcompact-inline.d.ts +145 -0
- package/dist/types/session/snapcompact-savings-journal.d.ts +46 -0
- package/dist/types/session/streaming-output.d.ts +46 -0
- package/dist/types/session/tool-choice-queue.d.ts +6 -6
- package/dist/types/session/yield-queue.d.ts +10 -1
- package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
- package/dist/types/slash-commands/available-commands.d.ts +34 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +10 -0
- package/dist/types/slash-commands/helpers/active-oauth-account.d.ts +14 -0
- package/dist/types/slash-commands/helpers/logout.d.ts +15 -0
- package/dist/types/slash-commands/helpers/reset-usage.d.ts +27 -0
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
- package/dist/types/slash-commands/types.d.ts +5 -9
- package/dist/types/ssh/connection-manager.d.ts +8 -0
- package/dist/types/stt/asr-client.d.ts +90 -0
- package/dist/types/stt/asr-protocol.d.ts +97 -0
- package/dist/types/stt/asr-worker.d.ts +2 -0
- package/dist/types/stt/downloader.d.ts +38 -0
- package/dist/types/stt/endpointer.d.ts +59 -0
- package/dist/types/stt/index.d.ts +5 -1
- package/dist/types/stt/models.d.ts +120 -0
- package/dist/types/stt/recorder.d.ts +17 -0
- package/dist/types/stt/stt-controller.d.ts +6 -0
- package/dist/types/stt/transcriber.d.ts +5 -7
- package/dist/types/stt/wav.d.ts +29 -0
- package/dist/types/system-prompt.d.ts +9 -1
- package/dist/types/task/commands.d.ts +1 -1
- package/dist/types/task/discovery.d.ts +1 -2
- package/dist/types/task/executor.d.ts +61 -2
- package/dist/types/task/index.d.ts +37 -6
- package/dist/types/task/output-manager.d.ts +0 -7
- package/dist/types/task/parallel.d.ts +2 -2
- package/dist/types/task/prometheus-command.d.ts +2 -2
- package/dist/types/task/render.d.ts +20 -7
- package/dist/types/task/repair-args.d.ts +8 -7
- package/dist/types/task/types.d.ts +109 -52
- package/dist/types/task/worktree.d.ts +2 -0
- package/dist/types/telemetry-export.d.ts +2 -2
- package/dist/types/thinking.d.ts +4 -0
- package/dist/types/tiny/models.d.ts +1 -1
- package/dist/types/tiny/title-client.d.ts +12 -1
- package/dist/types/tiny/title-protocol.d.ts +1 -0
- package/dist/types/tools/archive-reader.d.ts +5 -0
- package/dist/types/tools/ask.d.ts +6 -1
- package/dist/types/tools/ast-edit.d.ts +4 -1
- package/dist/types/tools/ast-grep.d.ts +4 -1
- package/dist/types/tools/bash.d.ts +5 -2
- package/dist/types/tools/browser/attach.d.ts +4 -4
- package/dist/types/tools/browser/cmux/cmux-tab.d.ts +202 -0
- package/dist/types/tools/browser/cmux/rpc.d.ts +70 -0
- package/dist/types/tools/browser/cmux/socket-client.d.ts +19 -0
- package/dist/types/tools/browser/registry.d.ts +17 -3
- package/dist/types/tools/browser/render.d.ts +2 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +16 -4
- package/dist/types/tools/browser/tab-worker.d.ts +18 -1
- package/dist/types/tools/browser.d.ts +3 -1
- package/dist/types/tools/checkpoint.d.ts +1 -1
- package/dist/types/tools/conflict-detect.d.ts +16 -0
- package/dist/types/tools/debug.d.ts +1 -1
- package/dist/types/tools/eval-render.d.ts +1 -8
- package/dist/types/tools/eval.d.ts +9 -1
- package/dist/types/tools/fetch.d.ts +17 -8
- package/dist/types/tools/find.d.ts +1 -8
- package/dist/types/tools/gh-cache-invalidation.d.ts +6 -0
- package/dist/types/tools/gh.d.ts +4 -1
- package/dist/types/tools/github-cache.d.ts +19 -0
- package/dist/types/tools/grouped-file-output.d.ts +46 -12
- package/dist/types/tools/image-gen.d.ts +1 -1
- package/dist/types/tools/index.d.ts +89 -8
- package/dist/types/tools/inspect-image.d.ts +1 -1
- package/dist/types/tools/irc.d.ts +79 -39
- package/dist/types/tools/job.d.ts +8 -2
- package/dist/types/tools/learn.d.ts +51 -0
- package/dist/types/tools/manage-skill.d.ts +40 -0
- package/dist/types/tools/memory-edit.d.ts +2 -2
- package/dist/types/tools/memory-recall.d.ts +1 -1
- package/dist/types/tools/memory-reflect.d.ts +1 -1
- package/dist/types/tools/memory-render.d.ts +4 -1
- package/dist/types/tools/memory-retain.d.ts +1 -1
- package/dist/types/tools/path-utils.d.ts +17 -5
- package/dist/types/tools/plan-mode-guard.d.ts +18 -9
- package/dist/types/tools/read.d.ts +3 -2
- package/dist/types/tools/render-mermaid.d.ts +1 -1
- package/dist/types/tools/render-utils.d.ts +47 -27
- package/dist/types/tools/renderers.d.ts +10 -2
- package/dist/types/tools/report-tool-issue.d.ts +6 -1
- package/dist/types/tools/resolve.d.ts +1 -1
- package/dist/types/tools/review.d.ts +1 -1
- package/dist/types/tools/search-tool-bm25.d.ts +1 -1
- package/dist/types/tools/search.d.ts +7 -3
- package/dist/types/tools/sqlite-reader.d.ts +4 -0
- package/dist/types/tools/ssh.d.ts +2 -1
- package/dist/types/tools/todo.d.ts +7 -15
- package/dist/types/tools/tool-result.d.ts +2 -0
- package/dist/types/tools/tool-timeouts.d.ts +1 -1
- package/dist/types/tools/tts.d.ts +26 -1
- package/dist/types/tools/write.d.ts +6 -3
- package/dist/types/tools/yield.d.ts +8 -0
- package/dist/types/tts/downloader.d.ts +20 -0
- package/dist/types/tts/index.d.ts +8 -0
- package/dist/types/tts/models.d.ts +82 -0
- package/dist/types/tts/player.d.ts +32 -0
- package/dist/types/tts/runtime.d.ts +6 -0
- package/dist/types/tts/streaming-player.d.ts +41 -0
- package/dist/types/tts/tts-client.d.ts +93 -0
- package/dist/types/tts/tts-protocol.d.ts +95 -0
- package/dist/types/tts/tts-worker.d.ts +2 -0
- package/dist/types/tts/vocalizer.d.ts +41 -0
- package/dist/types/tts/wav.d.ts +8 -0
- package/dist/types/tui/code-cell.d.ts +0 -2
- package/dist/types/tui/hyperlink.d.ts +13 -7
- package/dist/types/tui/output-block.d.ts +16 -22
- package/dist/types/tui/status-line.d.ts +3 -0
- package/dist/types/utils/block-context.d.ts +35 -0
- package/dist/types/utils/changelog.d.ts +8 -0
- package/dist/types/utils/clipboard.d.ts +4 -3
- package/dist/types/utils/enhanced-paste.d.ts +20 -0
- package/dist/types/utils/file-mentions.d.ts +7 -0
- package/dist/types/utils/git.d.ts +22 -3
- package/dist/types/utils/image-loading.d.ts +30 -1
- package/dist/types/utils/session-color.d.ts +15 -3
- package/dist/types/utils/thinking-display.d.ts +17 -0
- package/dist/types/utils/title-generator.d.ts +3 -2
- package/dist/types/utils/tool-choice.d.ts +8 -0
- package/dist/types/utils/tools-manager.d.ts +2 -1
- package/dist/types/web/kagi.d.ts +2 -2
- package/dist/types/web/parallel.d.ts +3 -0
- package/dist/types/web/scrapers/github.d.ts +22 -0
- package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
- package/dist/types/web/scrapers/types.d.ts +12 -0
- package/dist/types/web/search/index.d.ts +1 -1
- package/dist/types/web/search/providers/anthropic.d.ts +2 -1
- package/dist/types/web/search/providers/base.d.ts +2 -1
- package/dist/types/web/search/providers/brave.d.ts +2 -1
- package/dist/types/web/search/providers/codex.d.ts +2 -1
- package/dist/types/web/search/providers/exa.d.ts +2 -1
- package/dist/types/web/search/providers/gemini.d.ts +10 -6
- package/dist/types/web/search/providers/jina.d.ts +7 -2
- package/dist/types/web/search/providers/kagi.d.ts +7 -2
- package/dist/types/web/search/providers/kimi.d.ts +7 -2
- package/dist/types/web/search/providers/parallel.d.ts +2 -1
- package/dist/types/web/search/providers/perplexity.d.ts +10 -2
- package/dist/types/web/search/providers/searxng.d.ts +2 -1
- package/dist/types/web/search/providers/synthetic.d.ts +7 -3
- package/dist/types/web/search/providers/tavily.d.ts +2 -1
- package/dist/types/web/search/providers/zai.d.ts +2 -1
- package/dist/types/web/search/types.d.ts +1 -1
- package/examples/extensions/api-demo.ts +2 -2
- package/package.json +41 -15
- package/scripts/bench-guard.ts +71 -0
- package/scripts/build-binary.ts +24 -25
- package/scripts/bundle-dist.ts +97 -0
- package/scripts/generate-share-viewer.ts +34 -0
- package/scripts/prometheus +42 -0
- package/scripts/prometheus.ts +20 -0
- package/src/async/index.ts +0 -1
- package/src/async/job-manager.ts +106 -3
- package/src/auto-thinking/classifier.ts +2 -1
- package/src/autolearn/controller.ts +139 -0
- package/src/autolearn/managed-skills.ts +257 -0
- package/src/autoresearch/dashboard.ts +1 -1
- package/src/autoresearch/prompt-setup.md +6 -6
- package/src/autoresearch/prompt.md +6 -6
- package/src/autoresearch/state.ts +1 -1
- package/src/autoresearch/storage.ts +2 -1
- package/src/autoresearch/tools/init-experiment.ts +1 -1
- package/src/autoresearch/tools/log-experiment.ts +1 -1
- package/src/autoresearch/tools/run-experiment.ts +1 -1
- package/src/autoresearch/tools/update-notes.ts +1 -1
- package/src/autoresearch/types.ts +1 -1
- package/src/capability/context-file.ts +0 -14
- package/src/capability/fs.ts +10 -0
- package/src/capability/index.ts +1 -6
- package/src/capability/mcp.ts +1 -0
- package/src/capability/rule-buckets.ts +4 -2
- package/src/capability/rule.ts +10 -1
- package/src/capability/types.ts +0 -4
- package/src/cli/args.ts +66 -13
- package/src/cli/auth-broker-cli.ts +6 -7
- package/src/cli/auth-gateway-cli.ts +8 -9
- package/src/cli/bench-cli.ts +437 -0
- package/src/cli/claude-trace-cli.ts +28 -50
- package/src/cli/completion-gen.ts +28 -28
- package/src/cli/dry-balance-cli.ts +56 -23
- package/src/cli/gallery-cli.ts +231 -0
- package/src/cli/gallery-fixtures/agentic.ts +407 -0
- package/src/cli/gallery-fixtures/codeintel.ts +187 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +220 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +57 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli/grievances-cli.ts +1 -1
- package/src/cli/list-models.ts +16 -174
- package/src/cli/models-cli.ts +429 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +148 -47
- package/src/cli/setup-model-picker.ts +43 -0
- package/src/cli/startup-cwd.ts +68 -0
- package/src/cli/update-cli.ts +144 -272
- package/src/cli/usage-cli.ts +774 -0
- package/src/cli-commands.ts +36 -0
- package/src/cli.ts +141 -32
- package/src/collab/crypto.ts +63 -0
- package/src/collab/guest.ts +451 -0
- package/src/collab/host.ts +565 -0
- package/src/collab/protocol.ts +241 -0
- package/src/collab/relay-client.ts +216 -0
- package/src/commands/bench.ts +42 -0
- package/src/commands/complete.ts +1 -1
- package/src/commands/gallery.ts +52 -0
- package/src/commands/install.ts +1 -1
- package/src/commands/join.ts +39 -0
- package/src/commands/launch.ts +8 -4
- package/src/commands/models.ts +61 -0
- package/src/commands/read.ts +6 -3
- package/src/commands/say.ts +102 -0
- package/src/commands/setup.ts +1 -1
- package/src/commands/token.ts +89 -0
- package/src/commands/usage.ts +43 -0
- package/src/commit/agentic/agent.ts +2 -1
- package/src/commit/agentic/tools/analyze-file.ts +42 -20
- package/src/commit/agentic/tools/git-file-diff.ts +1 -1
- package/src/commit/agentic/tools/git-hunk.ts +1 -1
- package/src/commit/agentic/tools/git-overview.ts +1 -1
- package/src/commit/agentic/tools/propose-changelog.ts +1 -1
- package/src/commit/agentic/tools/propose-commit.ts +1 -1
- package/src/commit/agentic/tools/recent-commits.ts +1 -1
- package/src/commit/agentic/tools/schemas.ts +1 -1
- package/src/commit/agentic/tools/split-commit.ts +9 -2
- package/src/commit/analysis/conventional.ts +2 -2
- package/src/commit/analysis/summary.ts +3 -3
- package/src/commit/changelog/generate.ts +3 -3
- package/src/commit/changelog/index.ts +2 -2
- package/src/commit/map-reduce/index.ts +3 -3
- package/src/commit/map-reduce/map-phase.ts +2 -2
- package/src/commit/map-reduce/reduce-phase.ts +2 -2
- package/src/commit/model-selection.ts +35 -12
- package/src/commit/pipeline.ts +4 -4
- package/src/commit/shared-llm.ts +1 -1
- package/src/config/api-key-resolver.ts +67 -0
- package/src/config/append-only-context-mode.ts +6 -12
- package/src/config/keybindings.ts +9 -4
- package/src/config/mcp-schema.json +4 -0
- package/src/config/model-discovery.ts +574 -0
- package/src/config/model-equivalence.ts +5 -4
- package/src/config/model-registry.ts +659 -1093
- package/src/config/model-resolver.ts +374 -174
- package/src/config/model-roles.ts +88 -0
- package/src/config/models-config-schema.ts +61 -9
- package/src/config/models-config.ts +130 -0
- package/src/config/settings-schema.ts +1441 -387
- package/src/config/settings.ts +261 -69
- package/src/dap/client.ts +138 -53
- package/src/dap/config.ts +41 -2
- package/src/dap/defaults.json +1 -0
- package/src/dap/session.ts +263 -161
- package/src/dap/types.ts +10 -0
- package/src/debug/index.ts +50 -60
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/protocol-probe.ts +1 -1
- package/src/debug/raw-sse-buffer.ts +7 -4
- package/src/debug/raw-sse.ts +1 -1
- package/src/debug/report-bundle.ts +9 -0
- package/src/debug/terminal-info.ts +0 -3
- package/src/discovery/agents-md.ts +25 -21
- package/src/discovery/agents.ts +9 -15
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-rules/index.ts +4 -0
- package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
- package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
- package/src/discovery/builtin.ts +45 -23
- package/src/discovery/claude-plugins.ts +44 -5
- package/src/discovery/helpers.ts +50 -9
- package/src/discovery/prometheus-extension-roots.ts +10 -10
- package/src/discovery/prometheus-plugins.ts +10 -10
- package/src/edit/diff.ts +191 -4
- package/src/edit/file-snapshot-store.ts +34 -1
- package/src/edit/hashline/block-resolver.ts +20 -1
- package/src/edit/hashline/diff.ts +123 -2
- package/src/edit/hashline/execute.ts +60 -4
- package/src/edit/hashline/filesystem.ts +2 -1
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/edit/hashline/params.ts +1 -1
- package/src/edit/index.ts +47 -18
- package/src/edit/modes/apply-patch.ts +1 -1
- package/src/edit/modes/patch.ts +59 -3
- package/src/edit/modes/replace.ts +58 -24
- package/src/edit/notebook.ts +22 -2
- package/src/edit/renderer.ts +315 -151
- package/src/eval/__tests__/agent-bridge.test.ts +105 -39
- package/src/eval/__tests__/budget-bridge.test.ts +1 -1
- package/src/eval/__tests__/completion-bridge.test.ts +412 -0
- package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
- package/src/eval/__tests__/js-context-manager.test.ts +241 -0
- package/src/eval/__tests__/llm-bridge.test.ts +6 -4
- package/src/eval/__tests__/shared-executors.test.ts +34 -92
- package/src/eval/agent-bridge.ts +39 -23
- package/src/eval/backend.ts +15 -2
- package/src/eval/bridge-timeout.ts +1 -1
- package/src/eval/completion-bridge.ts +203 -0
- package/src/eval/idle-timeout.ts +3 -10
- package/src/eval/js/context-manager.ts +108 -31
- package/src/eval/js/executor.ts +9 -2
- package/src/eval/js/index.ts +7 -3
- package/src/eval/js/shared/helpers.ts +59 -13
- package/src/eval/js/shared/local-module-loader.ts +2 -2
- package/src/eval/js/shared/prelude.txt +167 -30
- package/src/eval/js/shared/rewrite-imports.ts +58 -34
- package/src/eval/js/shared/runtime.ts +24 -16
- package/src/eval/js/tool-bridge.ts +4 -0
- package/src/eval/js/worker-core.ts +1 -0
- package/src/eval/js/worker-entry.ts +6 -0
- package/src/eval/js/worker-protocol.ts +6 -0
- package/src/eval/llm-bridge.ts +2 -1
- package/src/eval/py/__tests__/prelude.test.ts +19 -0
- package/src/eval/py/executor.ts +70 -26
- package/src/eval/py/index.ts +13 -4
- package/src/eval/py/kernel.ts +48 -9
- package/src/eval/py/prelude.py +73 -24
- package/src/eval/py/runner.py +133 -28
- package/src/eval/py/runtime.ts +38 -1
- package/src/exa/index.ts +1 -26
- package/src/exa/mcp-client.ts +10 -10
- package/src/exa/types.ts +0 -97
- package/src/exec/bash-executor.ts +104 -7
- package/src/export/custom-share.ts +1 -1
- package/src/export/html/index.ts +119 -17
- package/src/export/html/share-loader.js +102 -0
- package/src/export/html/template-js.ts +6 -0
- package/src/export/html/template.css +745 -459
- package/src/export/html/template.css.d.ts +2 -0
- package/src/export/html/template.html +6 -3
- package/src/export/html/template.js +277 -891
- package/src/export/html/tool-views.generated.d.ts +2 -0
- package/src/export/html/tool-views.generated.js +38 -0
- package/src/export/share.ts +269 -0
- package/src/export/ttsr.ts +122 -1
- package/src/extensibility/custom-commands/loader.ts +7 -4
- package/src/extensibility/custom-commands/types.ts +9 -4
- package/src/extensibility/custom-tools/loader.ts +51 -23
- package/src/extensibility/custom-tools/types.ts +16 -8
- package/src/extensibility/extensions/get-commands-handler.ts +2 -1
- package/src/extensibility/extensions/index.ts +1 -0
- package/src/extensibility/extensions/loader.ts +70 -20
- package/src/extensibility/extensions/model-api.ts +41 -0
- package/src/extensibility/extensions/runner.ts +12 -2
- package/src/extensibility/extensions/types.ts +83 -11
- package/src/extensibility/extensions/wrapper.ts +41 -5
- package/src/extensibility/hooks/index.ts +2 -1
- package/src/extensibility/hooks/loader.ts +6 -3
- package/src/extensibility/hooks/types.ts +11 -5
- package/src/extensibility/{legacy-pi-ai-shim.ts → legacy-package-ai-shim.ts} +2 -2
- package/src/extensibility/plugins/doctor.ts +1 -2
- package/src/extensibility/plugins/installer.ts +2 -2
- package/src/extensibility/plugins/{legacy-pi-compat.ts → legacy-package-compat.ts} +165 -77
- package/src/extensibility/plugins/loader.ts +34 -23
- package/src/extensibility/plugins/manager.ts +226 -95
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/extensibility/plugins/types.ts +3 -3
- package/src/extensibility/shared-events.ts +3 -3
- package/src/extensibility/skills.ts +113 -9
- package/src/extensibility/slash-commands.ts +1 -97
- package/src/goals/guided-setup.ts +133 -0
- package/src/goals/state.ts +1 -1
- package/src/goals/tools/goal-tool.ts +38 -28
- package/src/hindsight/bank.ts +17 -2
- package/src/hindsight/client.ts +27 -2
- package/src/hindsight/mental-models.ts +59 -12
- package/src/hindsight/state.ts +12 -3
- package/src/hindsight/transcript.ts +1 -1
- package/src/index.ts +5 -0
- package/src/internal-urls/artifact-protocol.ts +11 -2
- package/src/internal-urls/docs-index.generated.ts +9 -7
- package/src/internal-urls/history-protocol.ts +113 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/issue-pr-protocol.ts +22 -9
- package/src/internal-urls/local-protocol.ts +42 -7
- package/src/internal-urls/memory-protocol.ts +4 -31
- package/src/internal-urls/router.ts +3 -1
- package/src/internal-urls/types.ts +1 -1
- package/src/irc/bus.ts +303 -0
- package/src/lib/xai-http.ts +3 -3
- package/src/lsp/client.ts +245 -104
- package/src/lsp/clients/biome-client.ts +101 -39
- package/src/lsp/clients/lsp-linter-client.ts +2 -10
- package/src/lsp/config.ts +15 -5
- package/src/lsp/defaults.json +6 -0
- package/src/lsp/edits.ts +143 -95
- package/src/lsp/format-options.ts +119 -0
- package/src/lsp/index.ts +233 -93
- package/src/lsp/render.ts +11 -35
- package/src/lsp/types.ts +13 -1
- package/src/lsp/utils.ts +31 -12
- package/src/main.ts +396 -216
- package/src/mcp/config-writer.ts +7 -3
- package/src/mcp/json-rpc.ts +35 -5
- package/src/mcp/manager.ts +31 -16
- package/src/mcp/oauth-discovery.ts +34 -4
- package/src/mcp/oauth-flow.ts +61 -8
- package/src/mcp/render.ts +7 -1
- package/src/mcp/startup-events.ts +21 -0
- package/src/mcp/tool-bridge.ts +2 -0
- package/src/mcp/transports/stdio.ts +224 -4
- package/src/mcp/types.ts +2 -0
- package/src/memories/index.ts +174 -1128
- package/src/memories/storage.ts +2 -41
- package/src/memory-backend/index.ts +14 -1
- package/src/memory-backend/local-backend.ts +18 -3
- package/src/memory-backend/off-backend.ts +9 -0
- package/src/memory-backend/resolve.ts +4 -6
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +82 -2
- package/src/mnemopi/backend.ts +220 -28
- package/src/mnemopi/config.ts +138 -33
- package/src/mnemopi/state.ts +91 -11
- package/src/modes/acp/acp-agent.ts +149 -142
- package/src/modes/acp/acp-event-mapper.ts +5 -1
- package/src/modes/components/agent-dashboard.ts +17 -11
- package/src/modes/components/agent-hub.ts +1346 -0
- package/src/modes/components/assistant-message.ts +190 -80
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/btw-panel.ts +5 -1
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/collab-prompt-message.ts +30 -0
- package/src/modes/components/compaction-summary-message.ts +168 -33
- package/src/modes/components/copy-selector.ts +2 -45
- package/src/modes/components/custom-editor.test.ts +96 -0
- package/src/modes/components/custom-editor.ts +405 -118
- package/src/modes/components/custom-message.ts +1 -3
- package/src/modes/components/diff.ts +13 -2
- package/src/modes/components/dynamic-border.ts +12 -3
- package/src/modes/components/execution-shared.ts +1 -2
- package/src/modes/components/extensions/extension-dashboard.ts +8 -5
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +7 -3
- package/src/modes/components/extensions/state-manager.ts +36 -41
- package/src/modes/components/footer.ts +4 -2
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +8 -0
- package/src/modes/components/hook-input.ts +8 -0
- package/src/modes/components/hook-message.ts +1 -3
- package/src/modes/components/hook-selector.ts +6 -7
- package/src/modes/components/index.ts +1 -0
- package/src/modes/components/late-diagnostics-message.ts +60 -0
- package/src/modes/components/login-dialog.ts +1 -1
- package/src/modes/components/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +14 -1
- package/src/modes/components/model-selector.ts +177 -75
- package/src/modes/components/oauth-selector.ts +102 -16
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +845 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/plugin-settings.ts +22 -5
- package/src/modes/components/read-tool-group.ts +442 -39
- package/src/modes/components/reset-usage-selector.ts +161 -0
- package/src/modes/components/segment-track.ts +44 -7
- package/src/modes/components/session-selector.ts +97 -37
- package/src/modes/components/settings-defs.ts +28 -6
- package/src/modes/components/settings-selector.ts +541 -93
- package/src/modes/components/skill-message.ts +0 -1
- package/src/modes/components/snapcompact-shape-preview-doc.md +11 -0
- package/src/modes/components/snapcompact-shape-preview.ts +193 -0
- package/src/modes/components/{status-line.ts → status-line/component.ts} +205 -168
- package/src/modes/components/status-line/index.ts +1 -0
- package/src/modes/components/status-line/presets.ts +3 -3
- package/src/modes/components/status-line/segments.ts +26 -7
- package/src/modes/components/status-line/types.ts +40 -9
- package/src/modes/components/tiny-title-download-progress.ts +1 -1
- package/src/modes/components/tips.txt +7 -3
- package/src/modes/components/todo-reminder.ts +0 -2
- package/src/modes/components/tool-execution.ts +236 -103
- package/src/modes/components/transcript-container.ts +724 -99
- package/src/modes/components/tree-selector.ts +19 -4
- package/src/modes/components/ttsr-notification.ts +72 -30
- package/src/modes/components/usage-row.ts +18 -0
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +28 -12
- package/src/modes/components/visual-truncate.ts +1 -1
- package/src/modes/components/welcome.ts +80 -22
- package/src/modes/controllers/command-controller-shared.ts +7 -6
- package/src/modes/controllers/command-controller.ts +210 -180
- package/src/modes/controllers/event-controller.ts +352 -142
- package/src/modes/controllers/extension-ui-controller.ts +167 -208
- package/src/modes/controllers/input-controller.ts +778 -162
- package/src/modes/controllers/mcp-command-controller.ts +232 -80
- package/src/modes/controllers/selector-controller.ts +284 -145
- package/src/modes/controllers/session-focus-controller.ts +112 -0
- package/src/modes/controllers/ssh-command-controller.ts +2 -2
- package/src/modes/controllers/streaming-reveal.ts +295 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/controllers/tool-args-reveal.ts +174 -0
- package/src/modes/gradient-highlight.ts +21 -9
- package/src/modes/image-references.ts +33 -7
- package/src/modes/index.ts +8 -25
- package/src/modes/interactive-mode.ts +840 -186
- package/src/modes/magic-keywords.ts +28 -6
- package/src/modes/markdown-prose.ts +1 -1
- package/src/modes/oauth-manual-input.ts +30 -3
- package/src/modes/rpc/rpc-client.ts +186 -3
- package/src/modes/rpc/rpc-mode.ts +318 -24
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +111 -2
- package/src/modes/runtime-init.ts +28 -3
- package/src/modes/session-observer-registry.ts +72 -3
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +16 -4
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +25 -7
- package/src/modes/setup-wizard/scenes/providers.ts +45 -12
- package/src/modes/setup-wizard/scenes/sign-in.ts +14 -13
- package/src/modes/setup-wizard/scenes/splash.ts +1 -1
- package/src/modes/setup-wizard/scenes/theme.ts +29 -2
- package/src/modes/setup-wizard/scenes/types.ts +11 -2
- package/src/modes/setup-wizard/scenes/web-search.ts +26 -9
- package/src/modes/setup-wizard/wizard-overlay.ts +40 -3
- package/src/modes/shared.ts +2 -0
- package/src/modes/theme/defaults/dark-poimandres.json +1 -1
- package/src/modes/theme/defaults/light-poimandres.json +1 -1
- package/src/modes/theme/shimmer.ts +20 -9
- package/src/modes/theme/theme-schema.json +1 -1
- package/src/modes/theme/theme.ts +342 -82
- package/src/modes/types.ts +60 -18
- package/src/modes/utils/context-usage.ts +88 -8
- package/src/modes/utils/copy-targets.ts +133 -27
- package/src/modes/utils/hotkeys-markdown.ts +3 -2
- package/src/modes/utils/ui-helpers.ts +191 -110
- package/src/modes/workflow.ts +10 -10
- package/src/plan-mode/approved-plan.ts +66 -43
- package/src/plan-mode/plan-protection.ts +4 -4
- package/src/priority.json +5 -1
- package/src/prompts/agents/designer.md +1 -1
- package/src/prompts/agents/explore.md +3 -3
- package/src/prompts/agents/librarian.md +2 -3
- package/src/prompts/agents/oracle.md +2 -2
- package/src/prompts/agents/plan.md +6 -6
- package/src/prompts/agents/reviewer.md +1 -1
- package/src/prompts/agents/task.md +6 -5
- package/src/prompts/bench.md +12 -0
- package/src/prompts/ci-green-request.md +5 -7
- package/src/prompts/goals/goal-budget-limit.md +2 -2
- package/src/prompts/goals/goal-continuation.md +4 -4
- package/src/prompts/goals/goal-mode-active.md +1 -1
- package/src/prompts/goals/guided-goal-interview.md +8 -0
- package/src/prompts/goals/guided-goal-system.md +12 -0
- package/src/prompts/memories/consolidation.md +2 -7
- package/src/prompts/memories/consolidation_system.md +4 -0
- package/src/prompts/memories/identity_review.md +2 -2
- package/src/prompts/memories/read-path.md +11 -10
- package/src/prompts/memories/stage_one_system.md +2 -2
- package/src/prompts/review-custom-request.md +1 -1
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/auto-continue.md +1 -1
- package/src/prompts/system/autolearn-guidance-learn.md +1 -0
- package/src/prompts/system/autolearn-guidance.md +7 -0
- package/src/prompts/system/autolearn-nudge.md +3 -0
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/btw-user.md +2 -2
- package/src/prompts/system/commit-message-system.md +13 -1
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/eager-task.md +7 -0
- package/src/prompts/system/eager-todo.md +11 -6
- package/src/prompts/system/empty-stop-retry.md +4 -6
- package/src/prompts/system/irc-autoreply.md +6 -0
- package/src/prompts/system/irc-incoming.md +3 -4
- package/src/prompts/system/manual-continue.md +7 -0
- package/src/prompts/system/omfg-user.md +3 -4
- package/src/prompts/system/orchestrate-notice.md +10 -10
- package/src/prompts/system/personalities/default.md +26 -0
- package/src/prompts/system/personalities/friendly.md +17 -0
- package/src/prompts/system/personalities/pragmatic.md +15 -0
- package/src/prompts/system/plan-mode-active.md +70 -77
- package/src/prompts/system/plan-mode-approved.md +1 -1
- package/src/prompts/system/plan-mode-subagent.md +4 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/system/project-prompt.md +2 -2
- package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-context-stub.md +1 -0
- package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-system-stub.md +1 -0
- package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
- package/src/prompts/system/subagent-system-prompt.md +7 -8
- package/src/prompts/system/system-prompt.md +28 -57
- package/src/prompts/system/tiny-title-system.md +1 -1
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system-marker.md +16 -0
- package/src/prompts/system/title-system.md +16 -3
- package/src/prompts/system/ttsr-tool-reminder.md +1 -1
- package/src/prompts/system/workflow-notice.md +4 -4
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +2 -2
- package/src/prompts/tools/bash.md +16 -8
- package/src/prompts/tools/browser.md +33 -43
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/eval.md +31 -51
- package/src/prompts/tools/find.md +0 -1
- package/src/prompts/tools/github.md +8 -7
- package/src/prompts/tools/goal.md +1 -1
- package/src/prompts/tools/image-gen.md +1 -1
- package/src/prompts/tools/inspect-image-system.md +1 -1
- package/src/prompts/tools/irc.md +39 -31
- package/src/prompts/tools/job.md +2 -1
- package/src/prompts/tools/learn.md +7 -0
- package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
- package/src/prompts/tools/lsp.md +2 -2
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/memory-edit.md +1 -1
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/read.md +31 -39
- package/src/prompts/tools/recall.md +1 -1
- package/src/prompts/tools/reflect.md +1 -1
- package/src/prompts/tools/render-mermaid.md +2 -2
- package/src/prompts/tools/replace.md +4 -10
- package/src/prompts/tools/rewind.md +2 -2
- package/src/prompts/tools/search-tool-bm25.md +1 -9
- package/src/prompts/tools/search.md +0 -1
- package/src/prompts/tools/ssh.md +0 -4
- package/src/prompts/tools/task-summary.md +5 -16
- package/src/prompts/tools/task.md +47 -31
- package/src/prompts/tools/todo.md +6 -3
- package/src/registry/agent-lifecycle.ts +218 -0
- package/src/registry/agent-registry.ts +46 -5
- package/src/sdk.ts +692 -219
- package/src/secrets/index.ts +8 -1
- package/src/secrets/obfuscator.ts +40 -19
- package/src/session/agent-session.ts +1577 -806
- package/src/session/agent-storage.ts +18 -9
- package/src/session/auth-broker-config.ts +30 -1
- package/src/session/auth-storage.ts +6 -0
- package/src/session/codex-auto-reset.ts +202 -0
- package/src/session/history-storage.ts +3 -2
- package/src/session/indexed-session-storage.ts +7 -10
- package/src/session/messages.ts +59 -95
- package/src/session/session-context.ts +352 -0
- package/src/session/session-dump-format.ts +12 -3
- package/src/session/session-entries.ts +194 -0
- package/src/session/session-history-format.ts +246 -0
- package/src/session/session-listing.ts +588 -0
- package/src/session/session-loader.ts +106 -0
- package/src/session/session-manager.ts +1003 -2920
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +193 -0
- package/src/session/session-persistence.ts +131 -0
- package/src/session/session-storage.ts +91 -30
- package/src/session/snapcompact-inline.ts +542 -0
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/streaming-output.ts +248 -11
- package/src/session/tool-choice-queue.ts +23 -11
- package/src/session/yield-queue.ts +20 -2
- package/src/slash-commands/acp-builtins.ts +25 -1
- package/src/slash-commands/available-commands.ts +105 -0
- package/src/slash-commands/builtin-registry.ts +575 -49
- package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
- package/src/slash-commands/helpers/context-report.ts +28 -1
- package/src/slash-commands/helpers/logout.ts +88 -0
- package/src/slash-commands/helpers/reset-usage.ts +66 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/slash-commands/helpers/usage-report.ts +38 -3
- package/src/slash-commands/types.ts +5 -9
- package/src/ssh/connection-manager.ts +27 -0
- package/src/ssh/ssh-executor.ts +60 -4
- package/src/stt/asr-client.ts +520 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +790 -0
- package/src/stt/downloader.ts +107 -47
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +5 -1
- package/src/stt/models.ts +150 -0
- package/src/stt/recorder.ts +254 -67
- package/src/stt/stt-controller.ts +201 -22
- package/src/stt/transcriber.ts +37 -68
- package/src/stt/wav.ts +173 -0
- package/src/system-prompt.ts +52 -10
- package/src/task/agents.ts +3 -4
- package/src/task/commands.ts +3 -2
- package/src/task/discovery.ts +17 -24
- package/src/task/executor.ts +1054 -529
- package/src/task/index.ts +862 -757
- package/src/task/output-manager.ts +0 -11
- package/src/task/parallel.ts +3 -3
- package/src/task/prometheus-command.ts +2 -2
- package/src/task/render.ts +529 -182
- package/src/task/repair-args.ts +21 -9
- package/src/task/types.ts +144 -66
- package/src/task/worktree.ts +64 -56
- package/src/telemetry-export.ts +27 -9
- package/src/thinking.ts +9 -7
- package/src/tiny/models.ts +2 -2
- package/src/tiny/text.ts +5 -1
- package/src/tiny/title-client.ts +72 -20
- package/src/tiny/title-protocol.ts +1 -1
- package/src/tiny/worker.ts +23 -99
- package/src/tool-discovery/tool-index.ts +2 -0
- package/src/tools/archive-reader.ts +94 -2
- package/src/tools/ask.ts +234 -177
- package/src/tools/ast-edit.ts +136 -80
- package/src/tools/ast-grep.ts +41 -45
- package/src/tools/auto-generated-guard.ts +20 -3
- package/src/tools/bash-interactive.ts +28 -8
- package/src/tools/bash.ts +198 -35
- package/src/tools/browser/attach.ts +26 -7
- package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
- package/src/tools/browser/cmux/rpc.ts +156 -0
- package/src/tools/browser/cmux/socket-client.ts +309 -0
- package/src/tools/browser/launch.ts +11 -2
- package/src/tools/browser/readable.ts +19 -2
- package/src/tools/browser/registry.ts +52 -5
- package/src/tools/browser/render.ts +13 -5
- package/src/tools/browser/tab-protocol.ts +2 -0
- package/src/tools/browser/tab-supervisor.ts +256 -34
- package/src/tools/browser/tab-worker.ts +259 -91
- package/src/tools/browser.ts +44 -2
- package/src/tools/checkpoint.ts +1 -1
- package/src/tools/conflict-detect.ts +50 -4
- package/src/tools/debug.ts +27 -12
- package/src/tools/eval-render.ts +32 -35
- package/src/tools/eval.ts +26 -12
- package/src/tools/fetch.ts +450 -99
- package/src/tools/find.ts +182 -142
- package/src/tools/gh-cache-invalidation.ts +255 -0
- package/src/tools/gh-renderer.ts +104 -51
- package/src/tools/gh.ts +232 -37
- package/src/tools/github-cache.ts +97 -7
- package/src/tools/grouped-file-output.ts +159 -52
- package/src/tools/image-gen.ts +237 -132
- package/src/tools/index.ts +147 -26
- package/src/tools/inspect-image-renderer.ts +74 -45
- package/src/tools/inspect-image.ts +12 -6
- package/src/tools/irc.ts +626 -173
- package/src/tools/job.ts +106 -29
- package/src/tools/learn.ts +144 -0
- package/src/tools/manage-skill.ts +104 -0
- package/src/tools/memory-edit.ts +4 -4
- package/src/tools/memory-recall.ts +7 -9
- package/src/tools/memory-reflect.ts +5 -9
- package/src/tools/memory-render.ts +23 -6
- package/src/tools/memory-retain.ts +4 -4
- package/src/tools/path-utils.ts +102 -48
- package/src/tools/plan-mode-guard.ts +101 -40
- package/src/tools/read.ts +475 -120
- package/src/tools/render-mermaid.ts +1 -1
- package/src/tools/render-utils.ts +132 -76
- package/src/tools/renderers.ts +12 -1
- package/src/tools/report-tool-issue.ts +14 -6
- package/src/tools/resolve.ts +20 -3
- package/src/tools/review.ts +2 -2
- package/src/tools/search-tool-bm25.ts +37 -24
- package/src/tools/search.ts +233 -115
- package/src/tools/sqlite-reader.ts +26 -17
- package/src/tools/ssh.ts +20 -14
- package/src/tools/todo.ts +197 -191
- package/src/tools/tool-result.ts +8 -0
- package/src/tools/tool-timeouts.ts +1 -1
- package/src/tools/tts.ts +205 -74
- package/src/tools/write.ts +291 -155
- package/src/tools/yield.ts +10 -1
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/player.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/streaming-player.ts +266 -0
- package/src/tts/tts-client.ts +647 -0
- package/src/tts/tts-protocol.ts +60 -0
- package/src/tts/tts-worker.ts +505 -0
- package/src/tts/vocalizer.ts +162 -0
- package/src/tts/wav.ts +58 -0
- package/src/tui/code-cell.ts +2 -7
- package/src/tui/hyperlink.ts +40 -26
- package/src/tui/output-block.ts +60 -108
- package/src/tui/status-line.ts +5 -1
- package/src/utils/block-context.ts +312 -0
- package/src/utils/changelog.ts +27 -1
- package/src/utils/clipboard.ts +91 -22
- package/src/utils/commit-message-generator.ts +8 -3
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/file-mentions.ts +3 -1
- package/src/utils/git.ts +315 -15
- package/src/utils/image-loading.ts +65 -4
- package/src/utils/session-color.ts +83 -9
- package/src/utils/thinking-display.ts +37 -0
- package/src/utils/title-generator.ts +73 -10
- package/src/utils/tool-choice.ts +16 -0
- package/src/utils/tools-manager.ts +19 -1
- package/src/web/kagi.ts +28 -26
- package/src/web/parallel.ts +7 -3
- package/src/web/scrapers/arxiv.ts +1 -1
- package/src/web/scrapers/github.ts +351 -3
- package/src/web/scrapers/go-pkg.ts +1 -1
- package/src/web/scrapers/iacr.ts +1 -1
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/twitter.ts +2 -1
- package/src/web/scrapers/types.ts +87 -8
- package/src/web/scrapers/wikipedia.ts +1 -1
- package/src/web/scrapers/youtube.ts +9 -3
- package/src/web/search/index.ts +15 -2
- package/src/web/search/providers/anthropic.ts +62 -21
- package/src/web/search/providers/base.ts +2 -1
- package/src/web/search/providers/brave.ts +5 -2
- package/src/web/search/providers/codex.ts +87 -51
- package/src/web/search/providers/exa.ts +101 -10
- package/src/web/search/providers/gemini.ts +49 -24
- package/src/web/search/providers/jina.ts +15 -5
- package/src/web/search/providers/kagi.ts +9 -2
- package/src/web/search/providers/kimi.ts +45 -20
- package/src/web/search/providers/parallel.ts +39 -24
- package/src/web/search/providers/perplexity.ts +226 -63
- package/src/web/search/providers/searxng.ts +19 -3
- package/src/web/search/providers/synthetic.ts +16 -11
- package/src/web/search/providers/tavily.ts +12 -9
- package/src/web/search/providers/zai.ts +22 -9
- package/src/web/search/render.ts +59 -64
- package/src/web/search/types.ts +5 -1
- package/dist/types/discovery/context-files.d.ts +0 -17
- package/dist/types/exa/factory.d.ts +0 -13
- package/dist/types/exa/render.d.ts +0 -19
- package/dist/types/exa/researcher.d.ts +0 -9
- package/dist/types/exa/search.d.ts +0 -9
- package/dist/types/exa/websets.d.ts +0 -9
- package/dist/types/export/html/template.generated.d.ts +0 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
- package/dist/types/modes/components/status-line.d.ts +0 -77
- package/dist/types/slash-commands/headless-plan.d.ts +0 -3
- package/dist/types/stt/setup.d.ts +0 -18
- package/scripts/generate-template.ts +0 -33
- package/src/discovery/context-files.ts +0 -49
- package/src/exa/factory.ts +0 -60
- package/src/exa/render.ts +0 -244
- package/src/exa/researcher.ts +0 -36
- package/src/exa/search.ts +0 -47
- package/src/exa/websets.ts +0 -248
- package/src/export/html/template.generated.ts +0 -2
- package/src/modes/components/session-observer-overlay.ts +0 -852
- package/src/slash-commands/headless-plan.ts +0 -142
- package/src/stt/setup.ts +0 -52
- package/src/stt/transcribe.py +0 -70
- /package/dist/types/extensibility/{legacy-pi-coding-agent-shim.d.ts → legacy-package-agent-shim.d.ts} +0 -0
- /package/src/extensibility/{legacy-pi-coding-agent-shim.ts → legacy-package-agent-shim.ts} +0 -0
package/src/task/executor.ts
CHANGED
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import type { AgentEvent, AgentIdentity, AgentTelemetryConfig, ThinkingLevel } from "@prometheus-ai/agent-core";
|
|
9
9
|
import { recordHandoff, resolveTelemetry } from "@prometheus-ai/agent-core";
|
|
10
|
-
import {
|
|
10
|
+
import type { Usage } from "@prometheus-ai/ai";
|
|
11
|
+
import { logger, popLoopPhase, prompt, pushLoopPhase, untilAborted } from "@prometheus-ai/utils";
|
|
12
|
+
import type { Rule } from "../capability/rule";
|
|
11
13
|
import { ModelRegistry } from "../config/model-registry";
|
|
12
14
|
import { resolveModelOverrideWithAuthFallback } from "../config/model-resolver";
|
|
13
15
|
import type { PromptTemplate } from "../config/prompt-templates";
|
|
14
16
|
import { Settings } from "../config/settings";
|
|
15
17
|
import { SETTINGS_SCHEMA, type SettingPath } from "../config/settings-schema";
|
|
18
|
+
import type { ToolPathWithSource } from "../extensibility/custom-tools";
|
|
16
19
|
import type { CustomTool } from "../extensibility/custom-tools/types";
|
|
17
20
|
import { runExtensionCompact, runExtensionSetModel } from "../extensibility/extensions/compact-handler";
|
|
18
21
|
import { getSessionSlashCommands } from "../extensibility/extensions/get-commands-handler";
|
|
@@ -24,8 +27,9 @@ import type { MCPManager } from "../mcp/manager";
|
|
|
24
27
|
import type { MnemopiSessionState } from "../mnemopi/state";
|
|
25
28
|
import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prompt.md" with { type: "text" };
|
|
26
29
|
import submitReminderTemplate from "../prompts/system/subagent-yield-reminder.md" with { type: "text" };
|
|
30
|
+
import { AgentLifecycleManager } from "../registry/agent-lifecycle";
|
|
27
31
|
import { AgentRegistry } from "../registry/agent-registry";
|
|
28
|
-
import { createAgentSession, discoverAuthStorage } from "../sdk";
|
|
32
|
+
import { type CreateAgentSessionOptions, createAgentSession, discoverAuthStorage } from "../sdk";
|
|
29
33
|
import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
|
|
30
34
|
import type { ArtifactManager } from "../session/artifacts";
|
|
31
35
|
import type { AuthStorage } from "../session/auth-storage";
|
|
@@ -33,8 +37,13 @@ import { SKILL_PROMPT_MESSAGE_TYPE } from "../session/messages";
|
|
|
33
37
|
import { SessionManager } from "../session/session-manager";
|
|
34
38
|
import { truncateTail } from "../session/streaming-output";
|
|
35
39
|
import type { ContextFileEntry } from "../tools";
|
|
40
|
+
import { isIrcEnabled } from "../tools/irc";
|
|
36
41
|
import { normalizeSchema } from "../tools/jtd-to-json-schema";
|
|
37
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
buildOutputValidator,
|
|
44
|
+
type OutputValidator,
|
|
45
|
+
summarizeValidationFailure,
|
|
46
|
+
} from "../tools/output-schema-validator";
|
|
38
47
|
|
|
39
48
|
import { type ReportFindingDetails, toReviewFinding } from "../tools/review";
|
|
40
49
|
import { ToolAbortError } from "../tools/tool-errors";
|
|
@@ -47,7 +56,9 @@ import {
|
|
|
47
56
|
type AgentProgress,
|
|
48
57
|
MAX_OUTPUT_BYTES,
|
|
49
58
|
MAX_OUTPUT_LINES,
|
|
59
|
+
oneLineLabel,
|
|
50
60
|
type ReviewFinding,
|
|
61
|
+
resolveSubagentDisplayName,
|
|
51
62
|
type SingleResult,
|
|
52
63
|
TASK_SUBAGENT_EVENT_CHANNEL,
|
|
53
64
|
TASK_SUBAGENT_LIFECYCLE_CHANNEL,
|
|
@@ -57,6 +68,30 @@ import {
|
|
|
57
68
|
|
|
58
69
|
const MCP_CALL_TIMEOUT_MS = 60_000;
|
|
59
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Soft per-agent request budgets (assistant requests per run). When a subagent
|
|
73
|
+
* crosses its budget it receives ONE steering notice asking it to wrap up; at
|
|
74
|
+
* 1.5x the budget the run is aborted gracefully so partial output is salvaged.
|
|
75
|
+
* The `default` key applies to agents without an explicit entry and can be
|
|
76
|
+
* overridden via the `task.softRequestBudget` setting (0 disables the guard).
|
|
77
|
+
*/
|
|
78
|
+
export const SOFT_REQUEST_BUDGET: Record<string, number> = {
|
|
79
|
+
explore: 40,
|
|
80
|
+
quick_task: 40,
|
|
81
|
+
default: 90,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** Steering notice injected once when a subagent crosses its soft request budget. */
|
|
85
|
+
export function buildBudgetNotice(requests: number): string {
|
|
86
|
+
return `[budget notice] You have used ${requests} requests in this run. Wrap up now: finish the current step and yield your final report.`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Flatten whitespace and clip salvage text for the cancelled-child summary line. */
|
|
90
|
+
function formatSalvageSnippet(text: string, maxLength = 500): string {
|
|
91
|
+
const flattened = text.replace(/\s+/g, " ").trim();
|
|
92
|
+
return flattened.length > maxLength ? `${flattened.slice(0, maxLength - 1)}…` : flattened;
|
|
93
|
+
}
|
|
94
|
+
|
|
60
95
|
/** Agent event types to forward for progress tracking. */
|
|
61
96
|
const agentEventTypes = new Set<AgentEvent["type"]>([
|
|
62
97
|
"agent_start",
|
|
@@ -88,9 +123,16 @@ function normalizeModelPatterns(value: string | string[] | undefined): string[]
|
|
|
88
123
|
function renderIrcPeerRoster(selfId: string): string {
|
|
89
124
|
const peers = AgentRegistry.global()
|
|
90
125
|
.list()
|
|
91
|
-
.filter(ref => ref.id !== selfId &&
|
|
92
|
-
if (peers.length === 0) return "- (no other
|
|
93
|
-
|
|
126
|
+
.filter(ref => ref.id !== selfId && ref.status !== "aborted");
|
|
127
|
+
if (peers.length === 0) return "- (no other agents)";
|
|
128
|
+
const lines = peers.map(
|
|
129
|
+
peer =>
|
|
130
|
+
`- \`${peer.id}\` — ${peer.displayName} (${peer.kind}, ${peer.status})${peer.activity ? `: ${peer.activity}` : ""}`,
|
|
131
|
+
);
|
|
132
|
+
if (peers.some(peer => peer.status === "idle" || peer.status === "parked")) {
|
|
133
|
+
lines.push("Idle/parked peers are not gone: messaging them wakes (or revives) them.");
|
|
134
|
+
}
|
|
135
|
+
return lines.join("\n");
|
|
94
136
|
}
|
|
95
137
|
|
|
96
138
|
function withAbortTimeout<T>(promise: Promise<T>, timeoutMs: number, signal?: AbortSignal): Promise<T> {
|
|
@@ -146,6 +188,7 @@ export interface ExecutorOptions {
|
|
|
146
188
|
agent: AgentDefinition;
|
|
147
189
|
task: string;
|
|
148
190
|
assignment?: string;
|
|
191
|
+
/** Shared background from the task call (`task.batch`), rendered into the subagent's system prompt. */
|
|
149
192
|
context?: string;
|
|
150
193
|
/**
|
|
151
194
|
* The session's active overall plan, handed off so subagents spawned during
|
|
@@ -154,8 +197,18 @@ export interface ExecutorOptions {
|
|
|
154
197
|
*/
|
|
155
198
|
planReference?: { path: string; content: string };
|
|
156
199
|
description?: string;
|
|
200
|
+
/** Specialist role/expertise for this spawn; drives the system-prompt preamble, display name, and telemetry identity. */
|
|
201
|
+
role?: string;
|
|
157
202
|
index: number;
|
|
158
203
|
id: string;
|
|
204
|
+
parentToolCallId?: string;
|
|
205
|
+
/**
|
|
206
|
+
* Spawn runs as a detached background job (parent turn not blocked on it).
|
|
207
|
+
* Rides the subagent lifecycle/progress payloads so HUD-style surfaces can
|
|
208
|
+
* skip spawns the transcript already renders inline. See
|
|
209
|
+
* {@link SubagentLifecyclePayload.detached}.
|
|
210
|
+
*/
|
|
211
|
+
detached?: boolean;
|
|
159
212
|
modelOverride?: string | string[];
|
|
160
213
|
/**
|
|
161
214
|
* Active model selector of the parent session, used as an auth-aware fallback
|
|
@@ -166,19 +219,38 @@ export interface ExecutorOptions {
|
|
|
166
219
|
outputSchema?: unknown;
|
|
167
220
|
/** Parent task recursion depth (0 = top-level, 1 = first child, etc.) */
|
|
168
221
|
taskDepth?: number;
|
|
222
|
+
/**
|
|
223
|
+
* Override the `task.maxRuntimeMs` wall-clock cap for this run. When provided
|
|
224
|
+
* it wins over the settings value; `0` disables the per-subagent wall-clock
|
|
225
|
+
* limit entirely. Used by the eval `agent()` bridge, whose parent cell
|
|
226
|
+
* watchdog is already suspended for the call's duration.
|
|
227
|
+
*/
|
|
228
|
+
maxRuntimeMs?: number;
|
|
169
229
|
enableLsp?: boolean;
|
|
170
230
|
signal?: AbortSignal;
|
|
171
231
|
onProgress?: (progress: AgentProgress) => void;
|
|
172
232
|
sessionFile?: string | null;
|
|
173
233
|
persistArtifacts?: boolean;
|
|
174
234
|
artifactsDir?: string;
|
|
175
|
-
/** Path to parent conversation context file */
|
|
176
|
-
contextFile?: string;
|
|
177
235
|
eventBus?: EventBus;
|
|
178
236
|
contextFiles?: ContextFileEntry[];
|
|
179
237
|
skills?: Skill[];
|
|
180
238
|
promptTemplates?: PromptTemplate[];
|
|
181
239
|
workspaceTree?: WorkspaceTree;
|
|
240
|
+
/** Parent-discovered rules, forwarded to skip rule discovery in the subagent. */
|
|
241
|
+
rules?: Rule[];
|
|
242
|
+
/**
|
|
243
|
+
* Parent's discovered extension source paths. Forwarded to skip the
|
|
244
|
+
* extension FS scan in the subagent; the subagent then re-binds each
|
|
245
|
+
* extension against its own `ExtensionAPI` (cwd, eventBus, runtime).
|
|
246
|
+
*/
|
|
247
|
+
preloadedExtensionPaths?: string[];
|
|
248
|
+
/**
|
|
249
|
+
* Parent's discovered custom-tool source paths. Forwarded to skip the
|
|
250
|
+
* `.prometheus/tools/` FS scan in the subagent; the subagent then re-binds each
|
|
251
|
+
* tool against its own `CustomToolAPI` (cwd, exec, pushPendingAction, UI).
|
|
252
|
+
*/
|
|
253
|
+
preloadedCustomToolPaths?: ToolPathWithSource[];
|
|
182
254
|
mcpManager?: MCPManager;
|
|
183
255
|
authStorage?: AuthStorage;
|
|
184
256
|
modelRegistry?: ModelRegistry;
|
|
@@ -249,21 +321,40 @@ function extractCompletionData(parsed: unknown): unknown {
|
|
|
249
321
|
return parsed;
|
|
250
322
|
}
|
|
251
323
|
|
|
252
|
-
|
|
253
|
-
|
|
324
|
+
/**
|
|
325
|
+
* Resolve the final yielded payload, optionally splicing collected
|
|
326
|
+
* `report_finding` entries into a top-level `findings` array.
|
|
327
|
+
*
|
|
328
|
+
* Injection is suppressed when an active validator would reject the augmented
|
|
329
|
+
* payload (e.g. a caller-supplied schema with `additionalProperties: false`
|
|
330
|
+
* that does not declare `findings`). That keeps the in-tool yield validator
|
|
331
|
+
* (which only sees the raw, pre-injection data) in lockstep with this
|
|
332
|
+
* post-mortem validator — honoring the "accepted in-tool ⇒ accepted
|
|
333
|
+
* post-mortem" guarantee documented in `output-schema-validator.ts`. The
|
|
334
|
+
* dropped findings are still preserved verbatim in the agent's progress
|
|
335
|
+
* stream and JSONL artifact, so no information is lost when injection is
|
|
336
|
+
* suppressed.
|
|
337
|
+
*/
|
|
338
|
+
function normalizeCompleteData(
|
|
339
|
+
data: unknown,
|
|
340
|
+
reportFindings: ReviewFinding[] | undefined,
|
|
341
|
+
validator: OutputValidator | undefined,
|
|
342
|
+
): unknown {
|
|
343
|
+
const normalized = parseStringifiedJson(data ?? null);
|
|
254
344
|
if (
|
|
255
|
-
Array.isArray(reportFindings)
|
|
256
|
-
reportFindings.length
|
|
257
|
-
normalized
|
|
258
|
-
typeof normalized
|
|
259
|
-
|
|
345
|
+
!Array.isArray(reportFindings) ||
|
|
346
|
+
reportFindings.length === 0 ||
|
|
347
|
+
!normalized ||
|
|
348
|
+
typeof normalized !== "object" ||
|
|
349
|
+
Array.isArray(normalized)
|
|
260
350
|
) {
|
|
261
|
-
|
|
262
|
-
if (!("findings" in record)) {
|
|
263
|
-
normalized = { ...record, findings: reportFindings };
|
|
264
|
-
}
|
|
351
|
+
return normalized;
|
|
265
352
|
}
|
|
266
|
-
|
|
353
|
+
const record = normalized as Record<string, unknown>;
|
|
354
|
+
if ("findings" in record) return normalized;
|
|
355
|
+
const injected = { ...record, findings: reportFindings };
|
|
356
|
+
if (validator && !validator.validate(injected).success) return normalized;
|
|
357
|
+
return injected;
|
|
267
358
|
}
|
|
268
359
|
|
|
269
360
|
function resolveFallbackCompletion(rawOutput: string, outputSchema: unknown): { data: unknown } | null {
|
|
@@ -281,6 +372,15 @@ export interface YieldItem {
|
|
|
281
372
|
data?: unknown;
|
|
282
373
|
status?: "success" | "aborted";
|
|
283
374
|
error?: string;
|
|
375
|
+
/**
|
|
376
|
+
* Set by the in-tool yield validator when it exhausted its retry budget
|
|
377
|
+
* (MAX_SCHEMA_RETRIES) and accepted a schema-invalid payload anyway.
|
|
378
|
+
* `finalizeSubprocessOutput` honors this by serializing the payload and
|
|
379
|
+
* surfacing a stderr warning, instead of re-emitting `schema_violation`
|
|
380
|
+
* — which would silently swap the subagent's "accepted" view for a
|
|
381
|
+
* different, opaque error blob in the parent's view of the result.
|
|
382
|
+
*/
|
|
383
|
+
schemaOverridden?: boolean;
|
|
284
384
|
}
|
|
285
385
|
|
|
286
386
|
interface FinalizeSubprocessOutputArgs {
|
|
@@ -301,7 +401,8 @@ interface FinalizeSubprocessOutputResult {
|
|
|
301
401
|
abortedViaYield: boolean;
|
|
302
402
|
hasYield: boolean;
|
|
303
403
|
}
|
|
304
|
-
|
|
404
|
+
export const SUBAGENT_WARNING_SCHEMA_OVERRIDDEN =
|
|
405
|
+
"SYSTEM WARNING: Subagent exhausted schema-retry budget; result was accepted despite failing the output schema.";
|
|
305
406
|
export const SUBAGENT_WARNING_NULL_YIELD = "SYSTEM WARNING: Subagent called yield with null data.";
|
|
306
407
|
export const SUBAGENT_WARNING_MISSING_YIELD =
|
|
307
408
|
"SYSTEM WARNING: Subagent exited without calling yield tool after 3 reminders.";
|
|
@@ -353,30 +454,32 @@ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): Fi
|
|
|
353
454
|
if (submitData === null || submitData === undefined) {
|
|
354
455
|
rawOutput = rawOutput ? `${SUBAGENT_WARNING_NULL_YIELD}\n\n${rawOutput}` : SUBAGENT_WARNING_NULL_YIELD;
|
|
355
456
|
} else {
|
|
356
|
-
const completeData = normalizeCompleteData(submitData, reportFindings);
|
|
357
457
|
const { validator, error: schemaError } = buildOutputValidator(outputSchema);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
458
|
+
const overridden = lastYield?.schemaOverridden === true;
|
|
459
|
+
const completeData = normalizeCompleteData(submitData, reportFindings, validator);
|
|
460
|
+
const result =
|
|
461
|
+
schemaError || overridden
|
|
462
|
+
? { success: true as const }
|
|
463
|
+
: (validator?.validate(completeData) ?? { success: true as const });
|
|
464
|
+
if (!result.success) {
|
|
465
|
+
const summary = summarizeValidationFailure(result, completeData, validator?.requiredFields ?? []);
|
|
466
|
+
const outcome = buildSchemaViolationOutcome(summary, completeData);
|
|
467
|
+
rawOutput = outcome.rawOutput;
|
|
468
|
+
stderr = outcome.stderr;
|
|
469
|
+
exitCode = outcome.exitCode;
|
|
362
470
|
} else {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const
|
|
367
|
-
rawOutput =
|
|
368
|
-
stderr = outcome.stderr;
|
|
369
|
-
exitCode = outcome.exitCode;
|
|
370
|
-
} else {
|
|
371
|
-
try {
|
|
372
|
-
rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
|
|
373
|
-
} catch (err) {
|
|
374
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
375
|
-
rawOutput = `{"error":"Failed to serialize yield data: ${errorMessage}"}`;
|
|
376
|
-
}
|
|
377
|
-
exitCode = 0;
|
|
378
|
-
stderr = "";
|
|
471
|
+
try {
|
|
472
|
+
rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
|
|
473
|
+
} catch (err) {
|
|
474
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
475
|
+
rawOutput = `{"error":"Failed to serialize yield data: ${errorMessage}"}`;
|
|
379
476
|
}
|
|
477
|
+
exitCode = 0;
|
|
478
|
+
stderr = overridden
|
|
479
|
+
? SUBAGENT_WARNING_SCHEMA_OVERRIDDEN
|
|
480
|
+
: schemaError
|
|
481
|
+
? `invalid output schema: ${schemaError}`
|
|
482
|
+
: "";
|
|
380
483
|
}
|
|
381
484
|
}
|
|
382
485
|
}
|
|
@@ -386,8 +489,8 @@ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): Fi
|
|
|
386
489
|
const hasOutputSchema = normalizedSchema !== undefined && !schemaError;
|
|
387
490
|
const fallback = allowFallback ? resolveFallbackCompletion(rawOutput, outputSchema) : null;
|
|
388
491
|
if (fallback) {
|
|
389
|
-
const completeData = normalizeCompleteData(fallback.data, reportFindings);
|
|
390
492
|
const { validator } = buildOutputValidator(outputSchema);
|
|
493
|
+
const completeData = normalizeCompleteData(fallback.data, reportFindings, validator);
|
|
391
494
|
const result = validator?.validate(completeData) ?? { success: true as const };
|
|
392
495
|
if (!result.success) {
|
|
393
496
|
const summary = summarizeValidationFailure(result, completeData, validator?.requiredFields ?? []);
|
|
@@ -481,7 +584,7 @@ function getUsageTokens(usage: unknown): number {
|
|
|
481
584
|
/**
|
|
482
585
|
* Create proxy tools that reuse the parent's MCP connections.
|
|
483
586
|
*/
|
|
484
|
-
function createMCPProxyTools(mcpManager: MCPManager): CustomTool[] {
|
|
587
|
+
export function createMCPProxyTools(mcpManager: MCPManager): CustomTool[] {
|
|
485
588
|
return mcpManager.getTools().map(tool => {
|
|
486
589
|
const mcpTool = tool as { mcpToolName?: string; mcpServerName?: string };
|
|
487
590
|
return {
|
|
@@ -531,7 +634,10 @@ function createMCPProxyTools(mcpManager: MCPManager): CustomTool[] {
|
|
|
531
634
|
});
|
|
532
635
|
}
|
|
533
636
|
|
|
534
|
-
function createSubagentSettings(
|
|
637
|
+
export function createSubagentSettings(
|
|
638
|
+
baseSettings: Settings,
|
|
639
|
+
overrides?: Partial<Record<SettingPath, unknown>>,
|
|
640
|
+
): Settings {
|
|
535
641
|
const snapshot: Partial<Record<SettingPath, unknown>> = {};
|
|
536
642
|
for (const key of Object.keys(SETTINGS_SCHEMA) as SettingPath[]) {
|
|
537
643
|
snapshot[key] = baseSettings.get(key);
|
|
@@ -549,28 +655,68 @@ function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Reco
|
|
|
549
655
|
});
|
|
550
656
|
}
|
|
551
657
|
|
|
658
|
+
type AbortReason = "signal" | "terminate" | "timeout" | "budget";
|
|
659
|
+
|
|
660
|
+
/** Inputs for the run monitor driving one subagent assignment. */
|
|
661
|
+
interface RunMonitorArgs {
|
|
662
|
+
index: number;
|
|
663
|
+
id: string;
|
|
664
|
+
agent: AgentDefinition;
|
|
665
|
+
task: string;
|
|
666
|
+
assignment?: string;
|
|
667
|
+
description?: string;
|
|
668
|
+
modelOverride?: string | string[];
|
|
669
|
+
signal?: AbortSignal;
|
|
670
|
+
onProgress?: (progress: AgentProgress) => void;
|
|
671
|
+
eventBus?: EventBus;
|
|
672
|
+
parentToolCallId?: string;
|
|
673
|
+
detached?: boolean;
|
|
674
|
+
sessionFile?: string;
|
|
675
|
+
/** Soft assistant-request budget; 0 disables the guard. */
|
|
676
|
+
softRequestBudget: number;
|
|
677
|
+
/** Wall-clock cap in ms; 0 disables the timer. */
|
|
678
|
+
maxRuntimeMs: number;
|
|
679
|
+
}
|
|
680
|
+
|
|
552
681
|
/**
|
|
553
|
-
*
|
|
682
|
+
* The run-monitoring core of {@link runSubprocess}: progress tracking, event
|
|
683
|
+
* processing, abort/budget machinery, usage accumulation, and output capture
|
|
684
|
+
* for one assignment run.
|
|
554
685
|
*/
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
686
|
+
interface SubagentRunMonitor {
|
|
687
|
+
readonly progress: AgentProgress;
|
|
688
|
+
/** Fires when the run was asked to stop (caller signal, timeout, budget, terminate). */
|
|
689
|
+
readonly abortSignal: AbortSignal;
|
|
690
|
+
readonly accumulatedUsage: Usage;
|
|
691
|
+
hasUsage(): boolean;
|
|
692
|
+
yieldCalled(): boolean;
|
|
693
|
+
runtimeLimitExceeded(): boolean;
|
|
694
|
+
/** True when the abort carries a precise external reason (signal / wall-clock / budget). */
|
|
695
|
+
hasExplicitAbortReason(): boolean;
|
|
696
|
+
/** Whether the (attempted) abort counts as a cancelled run rather than an internal failure. */
|
|
697
|
+
isAbortedRun(): boolean;
|
|
698
|
+
requestAbort(reason: AbortReason): void;
|
|
699
|
+
resolveSignalAbortReason(): string;
|
|
700
|
+
resolveAbortReasonText(): string;
|
|
701
|
+
setActiveSession(session: AgentSession | null): void;
|
|
702
|
+
/** Return and clear the active session reference. */
|
|
703
|
+
takeActiveSession(): AgentSession | null;
|
|
704
|
+
/** Subscribe the monitor to a session's events. Returns the unsubscribe function. */
|
|
705
|
+
attach(session: AgentSession): () => void;
|
|
706
|
+
/** Best-effort capture of the last assistant text for cancelled-run salvage. */
|
|
707
|
+
captureSalvage(session: AgentSession): void;
|
|
708
|
+
lastAssistantSalvageText(): string | undefined;
|
|
709
|
+
/** Final raw output: end-of-run assistant text when available, else accumulated chunks. */
|
|
710
|
+
rawOutput(): string;
|
|
711
|
+
scheduleProgress(flush?: boolean): void;
|
|
712
|
+
/** Stop processing events and clear listeners/timers. Call once the run settled. */
|
|
713
|
+
finish(): void;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function createSubagentRunMonitor(args: RunMonitorArgs): SubagentRunMonitor {
|
|
717
|
+
const { index, id, agent, task, assignment, signal, onProgress, softRequestBudget, maxRuntimeMs } = args;
|
|
571
718
|
const startTime = Date.now();
|
|
572
719
|
|
|
573
|
-
// Initialize progress
|
|
574
720
|
const progress: AgentProgress = {
|
|
575
721
|
index,
|
|
576
722
|
id,
|
|
@@ -579,106 +725,23 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
579
725
|
status: "running",
|
|
580
726
|
task,
|
|
581
727
|
assignment,
|
|
582
|
-
description:
|
|
728
|
+
description: args.description,
|
|
583
729
|
lastIntent: undefined,
|
|
584
730
|
recentTools: [],
|
|
585
731
|
recentOutput: [],
|
|
586
732
|
toolCount: 0,
|
|
733
|
+
requests: 0,
|
|
587
734
|
tokens: 0,
|
|
588
735
|
cost: 0,
|
|
589
736
|
durationMs: 0,
|
|
590
|
-
modelOverride,
|
|
737
|
+
modelOverride: args.modelOverride,
|
|
591
738
|
};
|
|
592
739
|
|
|
593
|
-
// Check if already aborted
|
|
594
|
-
if (signal?.aborted) {
|
|
595
|
-
return {
|
|
596
|
-
index,
|
|
597
|
-
id,
|
|
598
|
-
agent: agent.name,
|
|
599
|
-
agentSource: agent.source,
|
|
600
|
-
task,
|
|
601
|
-
assignment,
|
|
602
|
-
description: options.description,
|
|
603
|
-
exitCode: 1,
|
|
604
|
-
output: "",
|
|
605
|
-
stderr: "Cancelled before start",
|
|
606
|
-
truncated: false,
|
|
607
|
-
durationMs: 0,
|
|
608
|
-
tokens: 0,
|
|
609
|
-
modelOverride,
|
|
610
|
-
error: "Cancelled before start",
|
|
611
|
-
aborted: true,
|
|
612
|
-
abortReason: "Cancelled before start",
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
// Set up artifact paths and write input file upfront if artifacts dir provided
|
|
617
|
-
let subtaskSessionFile: string | undefined;
|
|
618
|
-
if (options.artifactsDir) {
|
|
619
|
-
subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
const settings = options.settings ?? Settings.isolated();
|
|
623
|
-
const subagentSettings = createSubagentSettings(
|
|
624
|
-
settings,
|
|
625
|
-
agent.readSummarize === false ? { "read.summarize.enabled": false } : undefined,
|
|
626
|
-
);
|
|
627
|
-
const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
|
|
628
|
-
const maxRuntimeMs = Math.max(0, Math.trunc(Number(settings.get("task.maxRuntimeMs") ?? 0) || 0));
|
|
629
|
-
const parentDepth = options.taskDepth ?? 0;
|
|
630
|
-
const childDepth = parentDepth + 1;
|
|
631
|
-
const atMaxDepth = maxRecursionDepth >= 0 && childDepth >= maxRecursionDepth;
|
|
632
|
-
|
|
633
|
-
// Add tools if specified
|
|
634
|
-
let toolNames: string[] | undefined;
|
|
635
|
-
if (agent.tools && agent.tools.length > 0) {
|
|
636
|
-
toolNames = agent.tools;
|
|
637
|
-
// Auto-include task tool if spawns defined but task not in tools
|
|
638
|
-
if (agent.spawns !== undefined && !toolNames.includes("task") && !atMaxDepth) {
|
|
639
|
-
toolNames = [...toolNames, "task"];
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
if (atMaxDepth && toolNames?.includes("task")) {
|
|
644
|
-
toolNames = toolNames.filter(name => name !== "task");
|
|
645
|
-
}
|
|
646
|
-
// IRC is always available; the COOP prompt section advertises it, so a restricted
|
|
647
|
-
// whitelist must still carry `irc` for the subagent to actually use it.
|
|
648
|
-
if (toolNames && !toolNames.includes("irc")) {
|
|
649
|
-
toolNames = [...toolNames, "irc"];
|
|
650
|
-
}
|
|
651
|
-
if (toolNames?.includes("exec")) {
|
|
652
|
-
const allowEvalPy = settings.get("eval.py") ?? true;
|
|
653
|
-
const allowEvalJs = settings.get("eval.js") ?? true;
|
|
654
|
-
const expanded = toolNames.filter(name => name !== "exec");
|
|
655
|
-
if (allowEvalPy || allowEvalJs) expanded.push("eval");
|
|
656
|
-
expanded.push("bash");
|
|
657
|
-
toolNames = Array.from(new Set(expanded));
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
const modelPatterns = normalizeModelPatterns(modelOverride ?? agent.model);
|
|
661
|
-
const sessionFile = subtaskSessionFile ?? null;
|
|
662
|
-
const spawnsEnv = atMaxDepth
|
|
663
|
-
? ""
|
|
664
|
-
: agent.spawns === undefined
|
|
665
|
-
? ""
|
|
666
|
-
: agent.spawns === "*"
|
|
667
|
-
? "*"
|
|
668
|
-
: agent.spawns.join(",");
|
|
669
|
-
|
|
670
|
-
const lspEnabled = enableLsp ?? true;
|
|
671
|
-
const ircEnabled = subagentSettings.get("irc.enabled") === true;
|
|
672
|
-
const contextFileForPrompt = ircEnabled ? undefined : options.contextFile;
|
|
673
|
-
const skipPythonPreflight = Array.isArray(toolNames) && !toolNames.includes("eval");
|
|
674
|
-
|
|
675
740
|
const outputChunks: string[] = [];
|
|
676
741
|
const finalOutputChunks: string[] = [];
|
|
677
742
|
const RECENT_OUTPUT_TAIL_BYTES = 8 * 1024;
|
|
678
743
|
let recentOutputTail = "";
|
|
679
|
-
let stderr = "";
|
|
680
744
|
let resolved = false;
|
|
681
|
-
type AbortReason = "signal" | "terminate" | "timeout";
|
|
682
745
|
let abortSent = false;
|
|
683
746
|
let abortReason: AbortReason | undefined;
|
|
684
747
|
let runtimeLimitExceeded = false;
|
|
@@ -687,11 +750,10 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
687
750
|
const abortController = new AbortController();
|
|
688
751
|
const abortSignal = abortController.signal;
|
|
689
752
|
let activeSession: AgentSession | null = null;
|
|
690
|
-
let unsubscribe: (() => void) | null = null;
|
|
691
753
|
let yieldCalled = false;
|
|
692
754
|
|
|
693
755
|
// Accumulate usage incrementally from message_end events (no memory for streaming events)
|
|
694
|
-
const accumulatedUsage = {
|
|
756
|
+
const accumulatedUsage: Usage = {
|
|
695
757
|
input: 0,
|
|
696
758
|
output: 0,
|
|
697
759
|
cacheRead: 0,
|
|
@@ -700,11 +762,17 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
700
762
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
701
763
|
};
|
|
702
764
|
let hasUsage = false;
|
|
765
|
+
let budgetSteerSent = false;
|
|
766
|
+
let budgetLimitExceeded = false;
|
|
767
|
+
let lastAssistantSalvageText: string | undefined;
|
|
703
768
|
|
|
704
769
|
const requestAbort = (reason: AbortReason) => {
|
|
705
770
|
if (reason === "timeout") {
|
|
706
771
|
runtimeLimitExceeded = true;
|
|
707
772
|
}
|
|
773
|
+
if (reason === "budget") {
|
|
774
|
+
budgetLimitExceeded = true;
|
|
775
|
+
}
|
|
708
776
|
if (abortSent) {
|
|
709
777
|
if (reason === "signal" && abortReason !== "signal" && abortReason !== "timeout") {
|
|
710
778
|
abortReason = "signal";
|
|
@@ -721,11 +789,14 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
721
789
|
};
|
|
722
790
|
|
|
723
791
|
// Handle abort signal
|
|
724
|
-
const onAbort = () => {
|
|
725
|
-
if (!resolved) requestAbort("signal");
|
|
726
|
-
};
|
|
727
792
|
if (signal) {
|
|
728
|
-
signal.addEventListener(
|
|
793
|
+
signal.addEventListener(
|
|
794
|
+
"abort",
|
|
795
|
+
() => {
|
|
796
|
+
if (!resolved) requestAbort("signal");
|
|
797
|
+
},
|
|
798
|
+
{ once: true, signal: listenerSignal },
|
|
799
|
+
);
|
|
729
800
|
}
|
|
730
801
|
|
|
731
802
|
// Wall-clock hard limit. Defense-in-depth for the case where a provider stream
|
|
@@ -761,6 +832,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
761
832
|
if (runtimeLimitExceeded) {
|
|
762
833
|
return `Subagent runtime limit exceeded (task.maxRuntimeMs=${maxRuntimeMs})`;
|
|
763
834
|
}
|
|
835
|
+
if (budgetLimitExceeded) {
|
|
836
|
+
return `Soft request budget exceeded (${progress.requests} requests; budget ${softRequestBudget})`;
|
|
837
|
+
}
|
|
764
838
|
return resolveSignalAbortReason();
|
|
765
839
|
};
|
|
766
840
|
const PROGRESS_COALESCE_MS = 150;
|
|
@@ -770,15 +844,20 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
770
844
|
const emitProgressNow = () => {
|
|
771
845
|
progress.durationMs = Date.now() - startTime;
|
|
772
846
|
onProgress?.({ ...progress });
|
|
773
|
-
|
|
774
|
-
|
|
847
|
+
const activityGist =
|
|
848
|
+
progress.lastIntent ?? (progress.currentTool ? `running ${progress.currentTool}` : undefined);
|
|
849
|
+
if (activityGist) AgentRegistry.global().setActivity(id, activityGist);
|
|
850
|
+
if (args.eventBus) {
|
|
851
|
+
args.eventBus.emit(TASK_SUBAGENT_PROGRESS_CHANNEL, {
|
|
775
852
|
index,
|
|
776
853
|
agent: agent.name,
|
|
777
854
|
agentSource: agent.source,
|
|
778
855
|
task,
|
|
856
|
+
parentToolCallId: args.parentToolCallId,
|
|
857
|
+
detached: args.detached,
|
|
779
858
|
assignment,
|
|
780
859
|
progress: { ...progress },
|
|
781
|
-
sessionFile:
|
|
860
|
+
sessionFile: args.sessionFile,
|
|
782
861
|
});
|
|
783
862
|
}
|
|
784
863
|
lastProgressEmitMs = Date.now();
|
|
@@ -858,20 +937,16 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
858
937
|
progress.recentOutput = [];
|
|
859
938
|
};
|
|
860
939
|
|
|
940
|
+
const emitSubagentEvent = (event: AgentSessionEvent) => {
|
|
941
|
+
if (!args.eventBus) return;
|
|
942
|
+
args.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
|
|
943
|
+
id,
|
|
944
|
+
event,
|
|
945
|
+
});
|
|
946
|
+
};
|
|
947
|
+
|
|
861
948
|
const processEvent = (event: AgentEvent) => {
|
|
862
949
|
if (resolved) return;
|
|
863
|
-
|
|
864
|
-
if (options.eventBus) {
|
|
865
|
-
options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
|
|
866
|
-
index,
|
|
867
|
-
agent: agent.name,
|
|
868
|
-
agentSource: agent.source,
|
|
869
|
-
task,
|
|
870
|
-
assignment,
|
|
871
|
-
event,
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
|
|
875
950
|
const now = Date.now();
|
|
876
951
|
let flushProgress = false;
|
|
877
952
|
|
|
@@ -1016,6 +1091,26 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1016
1091
|
case "message_end": {
|
|
1017
1092
|
// Extract text from assistant and toolResult messages (not user prompts)
|
|
1018
1093
|
const role = event.message?.role;
|
|
1094
|
+
if (role === "assistant") {
|
|
1095
|
+
progress.requests += 1;
|
|
1096
|
+
if (softRequestBudget > 0 && !abortSent) {
|
|
1097
|
+
if (progress.requests >= softRequestBudget * 1.5) {
|
|
1098
|
+
requestAbort("budget");
|
|
1099
|
+
} else if (!budgetSteerSent && progress.requests >= softRequestBudget) {
|
|
1100
|
+
budgetSteerSent = true;
|
|
1101
|
+
const steerSession = activeSession;
|
|
1102
|
+
if (steerSession) {
|
|
1103
|
+
void steerSession
|
|
1104
|
+
.sendUserMessage(buildBudgetNotice(progress.requests), { deliverAs: "steer" })
|
|
1105
|
+
.catch(err => {
|
|
1106
|
+
logger.warn("Subagent budget steer failed", {
|
|
1107
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1108
|
+
});
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1019
1114
|
if (role === "assistant") {
|
|
1020
1115
|
const messageContent =
|
|
1021
1116
|
getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content;
|
|
@@ -1085,98 +1180,653 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1085
1180
|
scheduleProgress(flushProgress);
|
|
1086
1181
|
};
|
|
1087
1182
|
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1183
|
+
const attach = (session: AgentSession): (() => void) =>
|
|
1184
|
+
session.subscribe(event => {
|
|
1185
|
+
emitSubagentEvent(event);
|
|
1186
|
+
if (event.type === "auto_retry_start") {
|
|
1187
|
+
progress.retryState = {
|
|
1188
|
+
attempt: event.attempt,
|
|
1189
|
+
maxAttempts: event.maxAttempts,
|
|
1190
|
+
delayMs: event.delayMs,
|
|
1191
|
+
errorMessage: event.errorMessage,
|
|
1192
|
+
startedAtMs: Date.now(),
|
|
1193
|
+
};
|
|
1194
|
+
progress.retryFailure = undefined;
|
|
1195
|
+
scheduleProgress(true);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
if (event.type === "auto_retry_end") {
|
|
1199
|
+
const attempt = progress.retryState?.attempt ?? event.attempt;
|
|
1200
|
+
progress.retryState = undefined;
|
|
1201
|
+
if (!event.success) {
|
|
1202
|
+
progress.retryFailure = {
|
|
1203
|
+
attempt,
|
|
1204
|
+
errorMessage: event.finalError ?? "Auto-retry failed",
|
|
1205
|
+
};
|
|
1105
1206
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1207
|
+
scheduleProgress(true);
|
|
1208
|
+
return;
|
|
1108
1209
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
const onAbort = () => {
|
|
1210
|
+
if (isAgentEvent(event)) {
|
|
1211
|
+
// Breadcrumb the synchronous subagent event handling so the loop
|
|
1212
|
+
// watchdog can attribute any block to this in-process subagent.
|
|
1213
|
+
pushLoopPhase(`subagent:${id}`);
|
|
1114
1214
|
try {
|
|
1115
|
-
|
|
1215
|
+
processEvent(event);
|
|
1116
1216
|
} catch (err) {
|
|
1117
|
-
|
|
1217
|
+
logger.error("Subagent event processing failed", {
|
|
1218
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1219
|
+
});
|
|
1220
|
+
requestAbort("terminate");
|
|
1221
|
+
} finally {
|
|
1222
|
+
popLoopPhase();
|
|
1118
1223
|
}
|
|
1119
|
-
};
|
|
1120
|
-
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
1121
|
-
try {
|
|
1122
|
-
return await Promise.race([promise, abortPromise]);
|
|
1123
|
-
} finally {
|
|
1124
|
-
abortSignal.removeEventListener("abort", onAbort);
|
|
1125
1224
|
}
|
|
1126
|
-
};
|
|
1225
|
+
});
|
|
1127
1226
|
|
|
1227
|
+
const captureSalvage = (session: AgentSession): void => {
|
|
1228
|
+
// Best-effort salvage: capture the last assistant text so
|
|
1229
|
+
// cancelled/aborted children can surface "last activity" instead of
|
|
1230
|
+
// "(no output)".
|
|
1128
1231
|
try {
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
"options.authStorage and options.modelRegistry.authStorage must be the same instance when both are provided",
|
|
1139
|
-
);
|
|
1140
|
-
}
|
|
1141
|
-
checkAbort();
|
|
1142
|
-
if (!registryFromParent) {
|
|
1143
|
-
await awaitAbortable(modelRegistry.refresh());
|
|
1144
|
-
} else {
|
|
1145
|
-
logger.debug("runSubagent: reusing parent modelRegistry; skipping refresh");
|
|
1232
|
+
const lastContent = session.getLastAssistantMessage()?.content;
|
|
1233
|
+
if (Array.isArray(lastContent)) {
|
|
1234
|
+
const text = lastContent
|
|
1235
|
+
.map(block => (block.type === "text" && typeof block.text === "string" ? block.text : ""))
|
|
1236
|
+
.filter(Boolean)
|
|
1237
|
+
.join("\n");
|
|
1238
|
+
if (text.trim()) {
|
|
1239
|
+
lastAssistantSalvageText = text;
|
|
1240
|
+
}
|
|
1146
1241
|
}
|
|
1147
|
-
|
|
1242
|
+
} catch {
|
|
1243
|
+
// Salvage is best-effort; partial sessions may not implement it
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1148
1246
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1247
|
+
return {
|
|
1248
|
+
progress,
|
|
1249
|
+
abortSignal,
|
|
1250
|
+
accumulatedUsage,
|
|
1251
|
+
hasUsage: () => hasUsage,
|
|
1252
|
+
yieldCalled: () => yieldCalled,
|
|
1253
|
+
runtimeLimitExceeded: () => runtimeLimitExceeded,
|
|
1254
|
+
hasExplicitAbortReason: () => abortReason === "signal" || runtimeLimitExceeded || budgetLimitExceeded,
|
|
1255
|
+
isAbortedRun: () =>
|
|
1256
|
+
abortReason === "signal" || runtimeLimitExceeded || budgetLimitExceeded || abortReason === undefined,
|
|
1257
|
+
requestAbort,
|
|
1258
|
+
resolveSignalAbortReason,
|
|
1259
|
+
resolveAbortReasonText,
|
|
1260
|
+
setActiveSession: session => {
|
|
1261
|
+
activeSession = session;
|
|
1262
|
+
},
|
|
1263
|
+
takeActiveSession: () => {
|
|
1264
|
+
const session = activeSession;
|
|
1265
|
+
activeSession = null;
|
|
1266
|
+
return session;
|
|
1267
|
+
},
|
|
1268
|
+
attach,
|
|
1269
|
+
captureSalvage,
|
|
1270
|
+
lastAssistantSalvageText: () => lastAssistantSalvageText,
|
|
1271
|
+
rawOutput: () => (finalOutputChunks.length > 0 ? finalOutputChunks.join("") : outputChunks.join("")),
|
|
1272
|
+
scheduleProgress,
|
|
1273
|
+
finish: () => {
|
|
1274
|
+
resolved = true;
|
|
1275
|
+
listenerController.abort();
|
|
1276
|
+
if (runtimeTimeoutId !== undefined) {
|
|
1277
|
+
clearTimeout(runtimeTimeoutId);
|
|
1278
|
+
runtimeTimeoutId = undefined;
|
|
1172
1279
|
}
|
|
1173
|
-
if (
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
: `${model.provider}/${model.id}`;
|
|
1280
|
+
if (progressTimeoutId) {
|
|
1281
|
+
clearTimeout(progressTimeoutId);
|
|
1282
|
+
progressTimeoutId = null;
|
|
1177
1283
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1284
|
+
},
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
interface DriveOutcome {
|
|
1289
|
+
exitCode: number;
|
|
1290
|
+
error?: string;
|
|
1291
|
+
aborted: boolean;
|
|
1292
|
+
abortReasonText?: string;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
const MAX_YIELD_RETRIES = 3;
|
|
1296
|
+
|
|
1297
|
+
/**
|
|
1298
|
+
* Drive one assignment through a live session: send the prompt, wait for idle,
|
|
1299
|
+
* remind the agent to `yield` (up to {@link MAX_YIELD_RETRIES} times), then
|
|
1300
|
+
* classify the terminal assistant state.
|
|
1301
|
+
*/
|
|
1302
|
+
async function driveSessionToYield(
|
|
1303
|
+
session: AgentSession,
|
|
1304
|
+
monitor: SubagentRunMonitor,
|
|
1305
|
+
task: string,
|
|
1306
|
+
): Promise<DriveOutcome> {
|
|
1307
|
+
const abortSignal = monitor.abortSignal;
|
|
1308
|
+
let exitCode = 0;
|
|
1309
|
+
let error: string | undefined;
|
|
1310
|
+
let aborted = false;
|
|
1311
|
+
let abortReasonText: string | undefined;
|
|
1312
|
+
const checkAbort = () => {
|
|
1313
|
+
if (abortSignal.aborted) {
|
|
1314
|
+
aborted = monitor.isAbortedRun();
|
|
1315
|
+
if (aborted) {
|
|
1316
|
+
abortReasonText ??= monitor.resolveAbortReasonText();
|
|
1317
|
+
}
|
|
1318
|
+
exitCode = 1;
|
|
1319
|
+
throw new ToolAbortError();
|
|
1320
|
+
}
|
|
1321
|
+
};
|
|
1322
|
+
const awaitAbortable = async <T>(promise: Promise<T>): Promise<T> => {
|
|
1323
|
+
checkAbort();
|
|
1324
|
+
const { promise: abortPromise, reject } = Promise.withResolvers<never>();
|
|
1325
|
+
const onAbort = () => {
|
|
1326
|
+
try {
|
|
1327
|
+
checkAbort();
|
|
1328
|
+
} catch (err) {
|
|
1329
|
+
reject(err);
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
1333
|
+
try {
|
|
1334
|
+
return await Promise.race([promise, abortPromise]);
|
|
1335
|
+
} finally {
|
|
1336
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
try {
|
|
1341
|
+
await awaitAbortable(session.prompt(task, { attribution: "agent" }));
|
|
1342
|
+
await awaitAbortable(session.waitForIdle());
|
|
1343
|
+
|
|
1344
|
+
const reminderToolChoice = buildNamedToolChoice("yield", session.model);
|
|
1345
|
+
|
|
1346
|
+
let retryCount = 0;
|
|
1347
|
+
while (!monitor.yieldCalled() && retryCount < MAX_YIELD_RETRIES && !abortSignal.aborted) {
|
|
1348
|
+
// Skip reminders when the model returned a terminal error (e.g.
|
|
1349
|
+
// rate-limit cap hit, auth failure). Re-prompting would just
|
|
1350
|
+
// hit the same wall, multiplying the failure noise without
|
|
1351
|
+
// any chance of producing a yield.
|
|
1352
|
+
const lastBeforeReminder = session.getLastAssistantMessage();
|
|
1353
|
+
if (lastBeforeReminder?.stopReason === "error") break;
|
|
1354
|
+
try {
|
|
1355
|
+
retryCount++;
|
|
1356
|
+
const reminder = prompt.render(submitReminderTemplate, {
|
|
1357
|
+
retryCount,
|
|
1358
|
+
maxRetries: MAX_YIELD_RETRIES,
|
|
1359
|
+
});
|
|
1360
|
+
|
|
1361
|
+
const isFinalRetry = retryCount >= MAX_YIELD_RETRIES;
|
|
1362
|
+
await awaitAbortable(
|
|
1363
|
+
session.prompt(reminder, {
|
|
1364
|
+
attribution: "agent",
|
|
1365
|
+
synthetic: true,
|
|
1366
|
+
...(isFinalRetry && reminderToolChoice ? { toolChoice: reminderToolChoice } : {}),
|
|
1367
|
+
}),
|
|
1368
|
+
);
|
|
1369
|
+
await awaitAbortable(session.waitForIdle());
|
|
1370
|
+
} catch (err) {
|
|
1371
|
+
if (abortSignal.aborted || err instanceof ToolAbortError) {
|
|
1372
|
+
// Benign control-flow exit — user cancel (^C) or compaction aborting
|
|
1373
|
+
// pending operations both surface here as ToolAbortError. The outer
|
|
1374
|
+
// catch and finally already mark the run aborted; logging at ERROR
|
|
1375
|
+
// would spam operator dashboards with non-failures.
|
|
1376
|
+
logger.debug("Subagent prompt aborted");
|
|
1377
|
+
} else {
|
|
1378
|
+
logger.error("Subagent prompt failed", {
|
|
1379
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
await awaitAbortable(session.waitForIdle());
|
|
1386
|
+
|
|
1387
|
+
const lastAssistant = session.getLastAssistantMessage();
|
|
1388
|
+
if (lastAssistant) {
|
|
1389
|
+
if (lastAssistant.stopReason === "aborted") {
|
|
1390
|
+
aborted = monitor.isAbortedRun();
|
|
1391
|
+
if (aborted) {
|
|
1392
|
+
// A real caller signal or the wall-clock timer carries a precise
|
|
1393
|
+
// reason (signal.reason / "runtime limit exceeded"). An internal
|
|
1394
|
+
// turn abort does NOT — prefer the assistant message's own
|
|
1395
|
+
// errorMessage ("Request was aborted" or a specific stream error)
|
|
1396
|
+
// over the misleading "Cancelled by caller".
|
|
1397
|
+
abortReasonText ??= monitor.hasExplicitAbortReason()
|
|
1398
|
+
? monitor.resolveAbortReasonText()
|
|
1399
|
+
: lastAssistant.errorMessage?.trim() || monitor.resolveAbortReasonText();
|
|
1400
|
+
}
|
|
1401
|
+
exitCode = 1;
|
|
1402
|
+
} else if (lastAssistant.stopReason === "error") {
|
|
1403
|
+
exitCode = 1;
|
|
1404
|
+
error ??= lastAssistant.errorMessage || "Subagent failed";
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
} catch (err) {
|
|
1408
|
+
exitCode = 1;
|
|
1409
|
+
if (!abortSignal.aborted) {
|
|
1410
|
+
error = err instanceof Error ? err.stack || err.message : String(err);
|
|
1411
|
+
}
|
|
1412
|
+
} finally {
|
|
1413
|
+
if (abortSignal.aborted) {
|
|
1414
|
+
aborted = monitor.isAbortedRun();
|
|
1415
|
+
if (aborted) {
|
|
1416
|
+
abortReasonText ??= monitor.resolveAbortReasonText();
|
|
1417
|
+
}
|
|
1418
|
+
if (exitCode === 0) exitCode = 1;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
return { exitCode, error, aborted, abortReasonText };
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
interface FinalizeRunArgs {
|
|
1426
|
+
monitor: SubagentRunMonitor;
|
|
1427
|
+
done: { exitCode: number; error?: string; aborted?: boolean; abortReason?: string; durationMs: number };
|
|
1428
|
+
index: number;
|
|
1429
|
+
id: string;
|
|
1430
|
+
agent: AgentDefinition;
|
|
1431
|
+
task: string;
|
|
1432
|
+
assignment?: string;
|
|
1433
|
+
description?: string;
|
|
1434
|
+
modelOverride?: string | string[];
|
|
1435
|
+
outputSchema?: unknown;
|
|
1436
|
+
signal?: AbortSignal;
|
|
1437
|
+
artifactsDir?: string;
|
|
1438
|
+
eventBus?: EventBus;
|
|
1439
|
+
parentToolCallId?: string;
|
|
1440
|
+
detached?: boolean;
|
|
1441
|
+
sessionFile?: string;
|
|
1442
|
+
startTime: number;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/**
|
|
1446
|
+
* Turn a settled run into a {@link SingleResult}: resolve the yield payload via
|
|
1447
|
+
* {@link finalizeSubprocessOutput}, salvage cancelled-run output, write the
|
|
1448
|
+
* `<id>.md` output artifact, flush final progress, and emit the lifecycle end
|
|
1449
|
+
* event.
|
|
1450
|
+
*/
|
|
1451
|
+
async function finalizeRunResult(args: FinalizeRunArgs): Promise<SingleResult> {
|
|
1452
|
+
const { monitor, done, index, id, agent, task, assignment, signal, modelOverride } = args;
|
|
1453
|
+
const progress = monitor.progress;
|
|
1454
|
+
let exitCode = done.exitCode;
|
|
1455
|
+
let stderr = done.error ?? "";
|
|
1456
|
+
|
|
1457
|
+
// Use final output if available, otherwise accumulated output
|
|
1458
|
+
let rawOutput = monitor.rawOutput();
|
|
1459
|
+
const yieldItems = progress.extractedToolData?.yield as YieldItem[] | undefined;
|
|
1460
|
+
const reportFindingDetails = progress.extractedToolData?.report_finding as ReportFindingDetails[] | undefined;
|
|
1461
|
+
const reportFindings: ReviewFinding[] | undefined = reportFindingDetails?.map(toReviewFinding);
|
|
1462
|
+
// Breadcrumb the synchronous yield-payload shaping (O(rawOutput)) so a block
|
|
1463
|
+
// here is attributed to this subagent rather than logged as "unknown".
|
|
1464
|
+
pushLoopPhase(`subagent:${id}`);
|
|
1465
|
+
let finalized: FinalizeSubprocessOutputResult;
|
|
1466
|
+
try {
|
|
1467
|
+
finalized = finalizeSubprocessOutput({
|
|
1468
|
+
rawOutput,
|
|
1469
|
+
exitCode,
|
|
1470
|
+
stderr,
|
|
1471
|
+
doneAborted: Boolean(done.aborted),
|
|
1472
|
+
signalAborted: Boolean(signal?.aborted),
|
|
1473
|
+
yieldItems,
|
|
1474
|
+
reportFindings,
|
|
1475
|
+
outputSchema: args.outputSchema,
|
|
1476
|
+
});
|
|
1477
|
+
} finally {
|
|
1478
|
+
popLoopPhase();
|
|
1479
|
+
}
|
|
1480
|
+
rawOutput = finalized.rawOutput;
|
|
1481
|
+
exitCode = finalized.exitCode;
|
|
1482
|
+
stderr = finalized.stderr;
|
|
1483
|
+
// Salvage for cancelled/aborted children that produced no completed output:
|
|
1484
|
+
// surface the last assistant text + stats instead of "(no output)" so the
|
|
1485
|
+
// parent doesn't redo work the child already finished.
|
|
1486
|
+
const salvageText = monitor.lastAssistantSalvageText();
|
|
1487
|
+
if (
|
|
1488
|
+
(done.aborted || signal?.aborted || monitor.runtimeLimitExceeded()) &&
|
|
1489
|
+
!rawOutput.trim() &&
|
|
1490
|
+
salvageText !== undefined
|
|
1491
|
+
) {
|
|
1492
|
+
rawOutput = `[cancelled after ${progress.requests} req, ${progress.tokens} tok — last activity: "${formatSalvageSnippet(salvageText)}"]`;
|
|
1493
|
+
}
|
|
1494
|
+
const lastYield = yieldItems?.[yieldItems.length - 1];
|
|
1495
|
+
const yieldAbortReason = lastYield?.status === "aborted" ? lastYield.error || "Subagent aborted task" : undefined;
|
|
1496
|
+
const { abortedViaYield, hasYield } = finalized;
|
|
1497
|
+
const { content: truncatedOutput, truncated } = truncateTail(rawOutput, {
|
|
1498
|
+
maxBytes: MAX_OUTPUT_BYTES,
|
|
1499
|
+
maxLines: MAX_OUTPUT_LINES,
|
|
1500
|
+
});
|
|
1501
|
+
|
|
1502
|
+
// Write output artifact (input and jsonl already written in real-time)
|
|
1503
|
+
// Compute output metadata for agent:// URL integration
|
|
1504
|
+
let outputMeta: { lineCount: number; charCount: number } | undefined;
|
|
1505
|
+
let outputPath: string | undefined;
|
|
1506
|
+
if (args.artifactsDir) {
|
|
1507
|
+
outputPath = path.join(args.artifactsDir, `${id}.md`);
|
|
1508
|
+
try {
|
|
1509
|
+
await Bun.write(outputPath, rawOutput);
|
|
1510
|
+
outputMeta = {
|
|
1511
|
+
lineCount: rawOutput.split("\n").length,
|
|
1512
|
+
charCount: rawOutput.length,
|
|
1513
|
+
};
|
|
1514
|
+
} catch {
|
|
1515
|
+
// Non-fatal
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// Update final progress. A wall-clock timeout always wins: if the runtime
|
|
1520
|
+
// limit fired we report aborted/failed regardless of whether a yield landed
|
|
1521
|
+
// while we were tearing the session down. The yield data is still surfaced
|
|
1522
|
+
// to the caller via `progress.extractedToolData`, but the exit status must
|
|
1523
|
+
// reflect the timeout so on-call doesn't mistake a stuck run for success.
|
|
1524
|
+
const runtimeLimitExceeded = monitor.runtimeLimitExceeded();
|
|
1525
|
+
if (runtimeLimitExceeded && exitCode === 0) {
|
|
1526
|
+
exitCode = 1;
|
|
1527
|
+
}
|
|
1528
|
+
const wasAborted =
|
|
1529
|
+
runtimeLimitExceeded || abortedViaYield || (!hasYield && (done.aborted || signal?.aborted || false));
|
|
1530
|
+
const finalAbortReason = wasAborted
|
|
1531
|
+
? runtimeLimitExceeded
|
|
1532
|
+
? monitor.resolveAbortReasonText()
|
|
1533
|
+
: abortedViaYield
|
|
1534
|
+
? yieldAbortReason
|
|
1535
|
+
: (done.abortReason ??
|
|
1536
|
+
(signal?.aborted ? monitor.resolveSignalAbortReason() : monitor.resolveAbortReasonText()))
|
|
1537
|
+
: undefined;
|
|
1538
|
+
progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
|
|
1539
|
+
monitor.scheduleProgress(true);
|
|
1540
|
+
|
|
1541
|
+
// Emit lifecycle end event after finalization so yield status is reflected
|
|
1542
|
+
if (args.eventBus) {
|
|
1543
|
+
args.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
|
|
1544
|
+
id,
|
|
1545
|
+
agent: agent.name,
|
|
1546
|
+
parentToolCallId: args.parentToolCallId,
|
|
1547
|
+
detached: args.detached,
|
|
1548
|
+
agentSource: agent.source,
|
|
1549
|
+
description: args.description,
|
|
1550
|
+
status: progress.status as "completed" | "failed" | "aborted",
|
|
1551
|
+
sessionFile: args.sessionFile,
|
|
1552
|
+
index,
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
return {
|
|
1557
|
+
index,
|
|
1558
|
+
id,
|
|
1559
|
+
agent: agent.name,
|
|
1560
|
+
agentSource: agent.source,
|
|
1561
|
+
task,
|
|
1562
|
+
assignment,
|
|
1563
|
+
description: args.description,
|
|
1564
|
+
lastIntent: progress.lastIntent,
|
|
1565
|
+
exitCode,
|
|
1566
|
+
output: truncatedOutput,
|
|
1567
|
+
stderr,
|
|
1568
|
+
truncated: Boolean(truncated),
|
|
1569
|
+
durationMs: Date.now() - args.startTime,
|
|
1570
|
+
tokens: progress.tokens,
|
|
1571
|
+
requests: progress.requests,
|
|
1572
|
+
contextTokens: progress.contextTokens,
|
|
1573
|
+
contextWindow: progress.contextWindow,
|
|
1574
|
+
modelOverride,
|
|
1575
|
+
resolvedModel: progress.resolvedModel,
|
|
1576
|
+
error: exitCode !== 0 && stderr ? stderr : undefined,
|
|
1577
|
+
aborted: wasAborted,
|
|
1578
|
+
abortReason: finalAbortReason,
|
|
1579
|
+
usage: monitor.hasUsage() ? monitor.accumulatedUsage : undefined,
|
|
1580
|
+
outputPath,
|
|
1581
|
+
extractedToolData: progress.extractedToolData,
|
|
1582
|
+
retryFailure: progress.retryFailure,
|
|
1583
|
+
outputMeta,
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
/**
|
|
1588
|
+
* Run a single agent in-process.
|
|
1589
|
+
*/
|
|
1590
|
+
export async function runSubprocess(options: ExecutorOptions): Promise<SingleResult> {
|
|
1591
|
+
const {
|
|
1592
|
+
cwd,
|
|
1593
|
+
agent,
|
|
1594
|
+
task,
|
|
1595
|
+
assignment,
|
|
1596
|
+
index,
|
|
1597
|
+
id,
|
|
1598
|
+
worktree,
|
|
1599
|
+
modelOverride,
|
|
1600
|
+
thinkingLevel,
|
|
1601
|
+
outputSchema,
|
|
1602
|
+
enableLsp,
|
|
1603
|
+
signal,
|
|
1604
|
+
onProgress,
|
|
1605
|
+
} = options;
|
|
1606
|
+
const startTime = Date.now();
|
|
1607
|
+
|
|
1608
|
+
// Check if already aborted
|
|
1609
|
+
if (signal?.aborted) {
|
|
1610
|
+
return {
|
|
1611
|
+
index,
|
|
1612
|
+
id,
|
|
1613
|
+
agent: agent.name,
|
|
1614
|
+
agentSource: agent.source,
|
|
1615
|
+
task,
|
|
1616
|
+
assignment,
|
|
1617
|
+
description: options.description,
|
|
1618
|
+
exitCode: 1,
|
|
1619
|
+
output: "",
|
|
1620
|
+
stderr: "Cancelled before start",
|
|
1621
|
+
truncated: false,
|
|
1622
|
+
durationMs: 0,
|
|
1623
|
+
tokens: 0,
|
|
1624
|
+
requests: 0,
|
|
1625
|
+
modelOverride,
|
|
1626
|
+
error: "Cancelled before start",
|
|
1627
|
+
aborted: true,
|
|
1628
|
+
abortReason: "Cancelled before start",
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
// Set up artifact paths and write input file upfront if artifacts dir provided
|
|
1633
|
+
let subtaskSessionFile: string | undefined;
|
|
1634
|
+
if (options.artifactsDir) {
|
|
1635
|
+
subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
const settings = options.settings ?? Settings.isolated();
|
|
1639
|
+
const subagentSettings = createSubagentSettings(
|
|
1640
|
+
settings,
|
|
1641
|
+
agent.readSummarize === false ? { "read.summarize.enabled": false } : undefined,
|
|
1642
|
+
);
|
|
1643
|
+
const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
|
|
1644
|
+
// Tailored specialist identity for this spawn. `subagentRole` is the full
|
|
1645
|
+
// (trimmed) role text fed to the system-prompt preamble; `subagentDisplayName`
|
|
1646
|
+
// is the label-normalized form the registry/roster show, falling back to the
|
|
1647
|
+
// agent type name when no role was given.
|
|
1648
|
+
const subagentRole = options.role?.trim() || undefined;
|
|
1649
|
+
const subagentDisplayName = resolveSubagentDisplayName(options.role, agent.name);
|
|
1650
|
+
const maxRuntimeMs = Math.max(
|
|
1651
|
+
0,
|
|
1652
|
+
Math.trunc(Number(options.maxRuntimeMs ?? settings.get("task.maxRuntimeMs") ?? 0) || 0),
|
|
1653
|
+
);
|
|
1654
|
+
// TTL before an adopted idle subagent is parked by the lifecycle manager.
|
|
1655
|
+
// <= 0 disables parking (the session stays live until process teardown).
|
|
1656
|
+
const agentIdleTtlMs = Math.trunc(Number(settings.get("task.agentIdleTtlMs") ?? 420_000) || 0);
|
|
1657
|
+
const configuredDefaultBudget = Math.max(
|
|
1658
|
+
0,
|
|
1659
|
+
Math.trunc(Number(settings.get("task.softRequestBudget") ?? SOFT_REQUEST_BUDGET.default) || 0),
|
|
1660
|
+
);
|
|
1661
|
+
const softRequestBudget =
|
|
1662
|
+
configuredDefaultBudget === 0 ? 0 : (SOFT_REQUEST_BUDGET[agent.name] ?? configuredDefaultBudget);
|
|
1663
|
+
const parentDepth = options.taskDepth ?? 0;
|
|
1664
|
+
const childDepth = parentDepth + 1;
|
|
1665
|
+
const atMaxDepth = maxRecursionDepth >= 0 && childDepth >= maxRecursionDepth;
|
|
1666
|
+
|
|
1667
|
+
// Add tools if specified
|
|
1668
|
+
let toolNames: string[] | undefined;
|
|
1669
|
+
if (agent.tools && agent.tools.length > 0) {
|
|
1670
|
+
toolNames = agent.tools;
|
|
1671
|
+
// Auto-include task tool if spawns defined but task not in tools
|
|
1672
|
+
if (agent.spawns !== undefined && !toolNames.includes("task") && !atMaxDepth) {
|
|
1673
|
+
toolNames = [...toolNames, "task"];
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
if (atMaxDepth && toolNames?.includes("task")) {
|
|
1678
|
+
toolNames = toolNames.filter(name => name !== "task");
|
|
1679
|
+
}
|
|
1680
|
+
// IRC is always available; the COOP prompt section advertises it, so a restricted
|
|
1681
|
+
// whitelist must still carry `irc` for the subagent to actually use it.
|
|
1682
|
+
if (toolNames && !toolNames.includes("irc")) {
|
|
1683
|
+
toolNames = [...toolNames, "irc"];
|
|
1684
|
+
}
|
|
1685
|
+
if (toolNames?.includes("exec")) {
|
|
1686
|
+
const allowEvalPy = settings.get("eval.py") ?? true;
|
|
1687
|
+
const allowEvalJs = settings.get("eval.js") ?? true;
|
|
1688
|
+
const expanded = toolNames.filter(name => name !== "exec");
|
|
1689
|
+
if (allowEvalPy || allowEvalJs) expanded.push("eval");
|
|
1690
|
+
expanded.push("bash");
|
|
1691
|
+
toolNames = Array.from(new Set(expanded));
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
const modelPatterns = normalizeModelPatterns(modelOverride ?? agent.model);
|
|
1695
|
+
const sessionFile = subtaskSessionFile ?? null;
|
|
1696
|
+
const spawnsEnv = atMaxDepth
|
|
1697
|
+
? ""
|
|
1698
|
+
: agent.spawns === undefined
|
|
1699
|
+
? ""
|
|
1700
|
+
: agent.spawns === "*"
|
|
1701
|
+
? "*"
|
|
1702
|
+
: agent.spawns.join(",");
|
|
1703
|
+
|
|
1704
|
+
const lspEnabled = enableLsp ?? true;
|
|
1705
|
+
const ircEnabled = isIrcEnabled(subagentSettings, childDepth);
|
|
1706
|
+
const skipPythonPreflight = Array.isArray(toolNames) && !toolNames.includes("eval");
|
|
1707
|
+
|
|
1708
|
+
const monitor = createSubagentRunMonitor({
|
|
1709
|
+
index,
|
|
1710
|
+
id,
|
|
1711
|
+
agent,
|
|
1712
|
+
task,
|
|
1713
|
+
assignment,
|
|
1714
|
+
description: options.description,
|
|
1715
|
+
modelOverride,
|
|
1716
|
+
signal,
|
|
1717
|
+
onProgress,
|
|
1718
|
+
eventBus: options.eventBus,
|
|
1719
|
+
parentToolCallId: options.parentToolCallId,
|
|
1720
|
+
detached: options.detached,
|
|
1721
|
+
sessionFile: subtaskSessionFile,
|
|
1722
|
+
softRequestBudget,
|
|
1723
|
+
maxRuntimeMs,
|
|
1724
|
+
});
|
|
1725
|
+
const progress = monitor.progress;
|
|
1726
|
+
let unsubscribe: (() => void) | null = null;
|
|
1727
|
+
let reviveSession: (() => Promise<AgentSession>) | null = null;
|
|
1728
|
+
// Adopted (kept-alive) subagents flip registry status from session events on
|
|
1729
|
+
// later turns: revive/wake → running, turn drained → idle. The subscription
|
|
1730
|
+
// intentionally survives this run; a disposed session emits nothing, so it
|
|
1731
|
+
// needs no teardown.
|
|
1732
|
+
const installRegistryStatusSync = (target: AgentSession): void => {
|
|
1733
|
+
target.subscribe(event => {
|
|
1734
|
+
if (event.type === "agent_start") {
|
|
1735
|
+
AgentRegistry.global().setStatus(id, "running");
|
|
1736
|
+
} else if (event.type === "agent_end") {
|
|
1737
|
+
AgentRegistry.global().setStatus(id, "idle");
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
};
|
|
1741
|
+
|
|
1742
|
+
const runSubagent = async (): Promise<{
|
|
1743
|
+
exitCode: number;
|
|
1744
|
+
error?: string;
|
|
1745
|
+
aborted?: boolean;
|
|
1746
|
+
abortReason?: string;
|
|
1747
|
+
durationMs: number;
|
|
1748
|
+
}> => {
|
|
1749
|
+
const sessionAbortController = new AbortController();
|
|
1750
|
+
const abortSignal = monitor.abortSignal;
|
|
1751
|
+
let exitCode = 0;
|
|
1752
|
+
let error: string | undefined;
|
|
1753
|
+
let aborted = false;
|
|
1754
|
+
let abortReasonText: string | undefined;
|
|
1755
|
+
const checkAbort = () => {
|
|
1756
|
+
if (abortSignal.aborted) {
|
|
1757
|
+
throw new ToolAbortError();
|
|
1758
|
+
}
|
|
1759
|
+
};
|
|
1760
|
+
const awaitAbortable = async <T>(promise: Promise<T>): Promise<T> => {
|
|
1761
|
+
checkAbort();
|
|
1762
|
+
const { promise: abortPromise, reject } = Promise.withResolvers<never>();
|
|
1763
|
+
const onAbort = () => {
|
|
1764
|
+
try {
|
|
1765
|
+
checkAbort();
|
|
1766
|
+
} catch (err) {
|
|
1767
|
+
reject(err);
|
|
1768
|
+
}
|
|
1769
|
+
};
|
|
1770
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
1771
|
+
try {
|
|
1772
|
+
return await Promise.race([promise, abortPromise]);
|
|
1773
|
+
} finally {
|
|
1774
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
1775
|
+
}
|
|
1776
|
+
};
|
|
1777
|
+
|
|
1778
|
+
try {
|
|
1779
|
+
checkAbort();
|
|
1780
|
+
// Pin authStorage to modelRegistry.authStorage — mirrors the createAgentSession invariant.
|
|
1781
|
+
const registryFromParent = options.modelRegistry !== undefined;
|
|
1782
|
+
const modelRegistry =
|
|
1783
|
+
options.modelRegistry ??
|
|
1784
|
+
new ModelRegistry(options.authStorage ?? (await awaitAbortable(discoverAuthStorage())));
|
|
1785
|
+
const authStorage = modelRegistry.authStorage;
|
|
1786
|
+
if (options.authStorage && options.authStorage !== authStorage) {
|
|
1787
|
+
throw new Error(
|
|
1788
|
+
"options.authStorage and options.modelRegistry.authStorage must be the same instance when both are provided",
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1791
|
+
checkAbort();
|
|
1792
|
+
if (!registryFromParent) {
|
|
1793
|
+
await awaitAbortable(modelRegistry.refresh());
|
|
1794
|
+
} else {
|
|
1795
|
+
logger.debug("runSubagent: reusing parent modelRegistry; skipping refresh");
|
|
1796
|
+
}
|
|
1797
|
+
checkAbort();
|
|
1798
|
+
|
|
1799
|
+
const {
|
|
1800
|
+
model,
|
|
1801
|
+
thinkingLevel: resolvedThinkingLevel,
|
|
1802
|
+
explicitThinkingLevel,
|
|
1803
|
+
authFallbackUsed,
|
|
1804
|
+
} = await awaitAbortable(
|
|
1805
|
+
resolveModelOverrideWithAuthFallback(
|
|
1806
|
+
modelPatterns,
|
|
1807
|
+
options.parentActiveModelPattern,
|
|
1808
|
+
modelRegistry,
|
|
1809
|
+
settings,
|
|
1810
|
+
),
|
|
1811
|
+
);
|
|
1812
|
+
if (authFallbackUsed && model) {
|
|
1813
|
+
logger.warn("Subagent model has no working credentials; falling back to parent session model", {
|
|
1814
|
+
requested: modelPatterns,
|
|
1815
|
+
parentModel: options.parentActiveModelPattern,
|
|
1816
|
+
resolvedProvider: model.provider,
|
|
1817
|
+
resolvedModel: model.id,
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
if (model?.contextWindow && model.contextWindow > 0) {
|
|
1821
|
+
progress.contextWindow = model.contextWindow;
|
|
1822
|
+
}
|
|
1823
|
+
if (model) {
|
|
1824
|
+
progress.resolvedModel = explicitThinkingLevel
|
|
1825
|
+
? `${model.provider}/${model.id}:${resolvedThinkingLevel}`
|
|
1826
|
+
: `${model.provider}/${model.id}`;
|
|
1827
|
+
}
|
|
1828
|
+
const effectiveThinkingLevel = explicitThinkingLevel
|
|
1829
|
+
? resolvedThinkingLevel
|
|
1180
1830
|
: (thinkingLevel ?? resolvedThinkingLevel);
|
|
1181
1831
|
|
|
1182
1832
|
const sessionManager = sessionFile
|
|
@@ -1195,7 +1845,11 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1195
1845
|
// carry the subagent's own agent identity, and use the subagent's
|
|
1196
1846
|
// own session id for `gen_ai.conversation.id`.
|
|
1197
1847
|
const subagentAgentIdentity: AgentIdentity | undefined = options.parentTelemetry
|
|
1198
|
-
? {
|
|
1848
|
+
? {
|
|
1849
|
+
id,
|
|
1850
|
+
name: subagentDisplayName,
|
|
1851
|
+
description: subagentRole ? oneLineLabel(subagentRole) : agent.description,
|
|
1852
|
+
}
|
|
1199
1853
|
: undefined;
|
|
1200
1854
|
const subagentTelemetry: AgentTelemetryConfig | undefined =
|
|
1201
1855
|
options.parentTelemetry && subagentAgentIdentity
|
|
@@ -1221,64 +1875,99 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1221
1875
|
|
|
1222
1876
|
const { normalized: normalizedOutputSchema } = normalizeSchema(outputSchema);
|
|
1223
1877
|
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1878
|
+
// Captured by the lifecycle reviver: rebuilding an equivalent session from
|
|
1879
|
+
// the same JSONL file re-invokes createAgentSession with the exact options
|
|
1880
|
+
// of the original run (same agent id, tools, model, system prompt,
|
|
1881
|
+
// artifacts dir) — only the SessionManager differs.
|
|
1882
|
+
const buildSubagentSessionOptions = (sessionManagerForRun: SessionManager): CreateAgentSessionOptions => ({
|
|
1883
|
+
cwd: worktree ?? cwd,
|
|
1884
|
+
authStorage,
|
|
1885
|
+
modelRegistry,
|
|
1886
|
+
settings: subagentSettings,
|
|
1887
|
+
model,
|
|
1888
|
+
thinkingLevel: effectiveThinkingLevel,
|
|
1889
|
+
toolNames,
|
|
1890
|
+
outputSchema,
|
|
1891
|
+
requireYieldTool: true,
|
|
1892
|
+
contextFiles: options.contextFiles,
|
|
1893
|
+
skills: options.skills,
|
|
1894
|
+
promptTemplates: options.promptTemplates,
|
|
1895
|
+
workspaceTree: options.workspaceTree,
|
|
1896
|
+
rules: options.rules,
|
|
1897
|
+
preloadedExtensionPaths: options.preloadedExtensionPaths,
|
|
1898
|
+
preloadedCustomToolPaths: options.preloadedCustomToolPaths,
|
|
1899
|
+
systemPrompt: defaultPrompt => {
|
|
1900
|
+
const subagentPrompt = prompt.render(subagentSystemPromptTemplate, {
|
|
1901
|
+
agent: agent.systemPrompt,
|
|
1902
|
+
role: subagentRole ? oneLineLabel(subagentRole) : "",
|
|
1903
|
+
context: options.context?.trim() ?? "",
|
|
1904
|
+
planReference: options.planReference?.content ?? "",
|
|
1905
|
+
planReferencePath: options.planReference?.path ?? "",
|
|
1906
|
+
worktree: worktree ?? "",
|
|
1907
|
+
outputSchema: normalizedOutputSchema,
|
|
1908
|
+
ircPeers: ircEnabled ? renderIrcPeerRoster(id) : "",
|
|
1909
|
+
ircSelfId: ircEnabled ? id : "",
|
|
1910
|
+
});
|
|
1911
|
+
return defaultPrompt.length === 0
|
|
1912
|
+
? [subagentPrompt]
|
|
1913
|
+
: [...defaultPrompt.slice(0, -1), subagentPrompt, defaultPrompt[defaultPrompt.length - 1]];
|
|
1914
|
+
},
|
|
1915
|
+
sessionManager: sessionManagerForRun,
|
|
1916
|
+
hasUI: false,
|
|
1917
|
+
spawns: spawnsEnv,
|
|
1918
|
+
taskDepth: childDepth,
|
|
1919
|
+
parentHindsightSessionState: options.parentHindsightSessionState,
|
|
1920
|
+
parentMnemopiSessionState: options.parentMnemopiSessionState,
|
|
1921
|
+
parentTaskPrefix: id,
|
|
1922
|
+
agentId: id,
|
|
1923
|
+
agentDisplayName: subagentDisplayName,
|
|
1924
|
+
enableLsp: lspEnabled,
|
|
1925
|
+
skipPythonPreflight,
|
|
1926
|
+
enableMCP,
|
|
1927
|
+
mcpManager: options.mcpManager,
|
|
1928
|
+
customTools: mcpProxyTools.length > 0 ? mcpProxyTools : undefined,
|
|
1929
|
+
localProtocolOptions: options.localProtocolOptions,
|
|
1930
|
+
telemetry: subagentTelemetry,
|
|
1931
|
+
parentEvalSessionId: options.parentEvalSessionId,
|
|
1932
|
+
});
|
|
1274
1933
|
|
|
1275
|
-
|
|
1934
|
+
const sessionPromise = createAgentSession(buildSubagentSessionOptions(sessionManager));
|
|
1935
|
+
let session: AgentSession;
|
|
1936
|
+
try {
|
|
1937
|
+
({ session } = await awaitAbortable(sessionPromise));
|
|
1938
|
+
} catch (err) {
|
|
1939
|
+
// Abort raced session startup. The session may still resolve later
|
|
1940
|
+
// holding live LSP/MCP child processes — dispose it when it does so
|
|
1941
|
+
// a cancelled subagent cannot leak them.
|
|
1942
|
+
void sessionPromise.then(created => created.session.dispose()).catch(() => {});
|
|
1943
|
+
throw err;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
monitor.setActiveSession(session);
|
|
1947
|
+
installRegistryStatusSync(session);
|
|
1948
|
+
if (sessionFile !== null && worktree === undefined) {
|
|
1949
|
+
// Lifecycle reviver: park closed the JSONL writer, so reopening takes
|
|
1950
|
+
// the single-writer lock cleanly and restores the full message history
|
|
1951
|
+
// (createAgentSession → agent.replaceMessages). Isolated runs are not
|
|
1952
|
+
// resumable (worktree is merged + cleaned) and never get a reviver.
|
|
1953
|
+
reviveSession = async () => {
|
|
1954
|
+
const reopened = await SessionManager.open(sessionFile);
|
|
1955
|
+
if (options.parentArtifactManager) {
|
|
1956
|
+
reopened.adoptArtifactManager(options.parentArtifactManager);
|
|
1957
|
+
}
|
|
1958
|
+
const { session: revived } = await createAgentSession(buildSubagentSessionOptions(reopened));
|
|
1959
|
+
installRegistryStatusSync(revived);
|
|
1960
|
+
return revived;
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1276
1963
|
|
|
1277
1964
|
// Emit lifecycle start event
|
|
1278
1965
|
if (options.eventBus) {
|
|
1279
1966
|
options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
|
|
1280
1967
|
id,
|
|
1281
1968
|
agent: agent.name,
|
|
1969
|
+
parentToolCallId: options.parentToolCallId,
|
|
1970
|
+
detached: options.detached,
|
|
1282
1971
|
agentSource: agent.source,
|
|
1283
1972
|
description: options.description,
|
|
1284
1973
|
status: "started",
|
|
@@ -1316,16 +2005,19 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1316
2005
|
}
|
|
1317
2006
|
|
|
1318
2007
|
const extensionRunner = session.extensionRunner;
|
|
1319
|
-
const pendingExtensionMessages: Promise<
|
|
2008
|
+
const pendingExtensionMessages: Promise<unknown>[] = [];
|
|
1320
2009
|
if (extensionRunner) {
|
|
1321
2010
|
extensionRunner.initialize(
|
|
1322
2011
|
{
|
|
1323
2012
|
sendMessage: (message, options) => {
|
|
1324
|
-
const sendPromise = session
|
|
1325
|
-
|
|
1326
|
-
|
|
2013
|
+
const sendPromise = session
|
|
2014
|
+
.sendCustomMessage(message, options)
|
|
2015
|
+
.then(() => undefined)
|
|
2016
|
+
.catch(e => {
|
|
2017
|
+
logger.error("Extension sendMessage failed", {
|
|
2018
|
+
error: e instanceof Error ? e.message : String(e),
|
|
2019
|
+
});
|
|
1327
2020
|
});
|
|
1328
|
-
});
|
|
1329
2021
|
pendingExtensionMessages.push(sendPromise);
|
|
1330
2022
|
},
|
|
1331
2023
|
sendUserMessage: (content, options) => {
|
|
@@ -1375,43 +2067,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1375
2067
|
}
|
|
1376
2068
|
}
|
|
1377
2069
|
|
|
1378
|
-
|
|
1379
|
-
unsubscribe = session.subscribe(event => {
|
|
1380
|
-
if (event.type === "auto_retry_start") {
|
|
1381
|
-
progress.retryState = {
|
|
1382
|
-
attempt: event.attempt,
|
|
1383
|
-
maxAttempts: event.maxAttempts,
|
|
1384
|
-
delayMs: event.delayMs,
|
|
1385
|
-
errorMessage: event.errorMessage,
|
|
1386
|
-
startedAtMs: Date.now(),
|
|
1387
|
-
};
|
|
1388
|
-
progress.retryFailure = undefined;
|
|
1389
|
-
scheduleProgress(true);
|
|
1390
|
-
return;
|
|
1391
|
-
}
|
|
1392
|
-
if (event.type === "auto_retry_end") {
|
|
1393
|
-
const attempt = progress.retryState?.attempt ?? event.attempt;
|
|
1394
|
-
progress.retryState = undefined;
|
|
1395
|
-
if (!event.success) {
|
|
1396
|
-
progress.retryFailure = {
|
|
1397
|
-
attempt,
|
|
1398
|
-
errorMessage: event.finalError ?? "Auto-retry failed",
|
|
1399
|
-
};
|
|
1400
|
-
}
|
|
1401
|
-
scheduleProgress(true);
|
|
1402
|
-
return;
|
|
1403
|
-
}
|
|
1404
|
-
if (isAgentEvent(event)) {
|
|
1405
|
-
try {
|
|
1406
|
-
processEvent(event);
|
|
1407
|
-
} catch (err) {
|
|
1408
|
-
logger.error("Subagent event processing failed", {
|
|
1409
|
-
error: err instanceof Error ? err.message : String(err),
|
|
1410
|
-
});
|
|
1411
|
-
requestAbort("terminate");
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
});
|
|
2070
|
+
unsubscribe = monitor.attach(session);
|
|
1415
2071
|
|
|
1416
2072
|
checkAbort();
|
|
1417
2073
|
// Autoload skills via sendCustomMessage (same mechanic as /skill:<name>)
|
|
@@ -1429,69 +2085,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1429
2085
|
);
|
|
1430
2086
|
}
|
|
1431
2087
|
}
|
|
1432
|
-
await awaitAbortable(session.prompt(task, { attribution: "agent" }));
|
|
1433
|
-
await awaitAbortable(session.waitForIdle());
|
|
1434
|
-
|
|
1435
|
-
const reminderToolChoice = buildNamedToolChoice("yield", session.model);
|
|
1436
|
-
|
|
1437
|
-
let retryCount = 0;
|
|
1438
|
-
while (!yieldCalled && retryCount < MAX_YIELD_RETRIES && !abortSignal.aborted) {
|
|
1439
|
-
// Skip reminders when the model returned a terminal error (e.g.
|
|
1440
|
-
// rate-limit cap hit, auth failure). Re-prompting would just
|
|
1441
|
-
// hit the same wall, multiplying the failure noise without
|
|
1442
|
-
// any chance of producing a yield.
|
|
1443
|
-
const lastBeforeReminder = session.getLastAssistantMessage();
|
|
1444
|
-
if (lastBeforeReminder?.stopReason === "error") break;
|
|
1445
|
-
try {
|
|
1446
|
-
retryCount++;
|
|
1447
|
-
const reminder = prompt.render(submitReminderTemplate, {
|
|
1448
|
-
retryCount,
|
|
1449
|
-
maxRetries: MAX_YIELD_RETRIES,
|
|
1450
|
-
});
|
|
1451
|
-
|
|
1452
|
-
const isFinalRetry = retryCount >= MAX_YIELD_RETRIES;
|
|
1453
|
-
await awaitAbortable(
|
|
1454
|
-
session.prompt(reminder, {
|
|
1455
|
-
attribution: "agent",
|
|
1456
|
-
...(isFinalRetry && reminderToolChoice ? { toolChoice: reminderToolChoice } : {}),
|
|
1457
|
-
}),
|
|
1458
|
-
);
|
|
1459
|
-
await awaitAbortable(session.waitForIdle());
|
|
1460
|
-
} catch (err) {
|
|
1461
|
-
if (abortSignal.aborted || err instanceof ToolAbortError) {
|
|
1462
|
-
// Benign control-flow exit — user cancel (^C) or compaction aborting
|
|
1463
|
-
// pending operations both surface here as ToolAbortError. The outer
|
|
1464
|
-
// catch and finally already mark the run aborted; logging at ERROR
|
|
1465
|
-
// would spam operator dashboards with non-failures.
|
|
1466
|
-
logger.debug("Subagent prompt aborted", {
|
|
1467
|
-
reason: abortReason ?? "signal",
|
|
1468
|
-
});
|
|
1469
|
-
} else {
|
|
1470
|
-
logger.error("Subagent prompt failed", {
|
|
1471
|
-
error: err instanceof Error ? err.message : String(err),
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
|
|
1477
|
-
await awaitAbortable(session.waitForIdle());
|
|
1478
|
-
if (!yieldCalled && !abortSignal.aborted) {
|
|
1479
|
-
exitCode = 0;
|
|
1480
|
-
}
|
|
1481
2088
|
|
|
1482
|
-
const
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
abortReasonText ??= resolveAbortReasonText();
|
|
1488
|
-
}
|
|
1489
|
-
exitCode = 1;
|
|
1490
|
-
} else if (lastAssistant.stopReason === "error") {
|
|
1491
|
-
exitCode = 1;
|
|
1492
|
-
error ??= lastAssistant.errorMessage || "Subagent failed";
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
2089
|
+
const outcome = await driveSessionToYield(session, monitor, task);
|
|
2090
|
+
exitCode = outcome.exitCode;
|
|
2091
|
+
error = outcome.error;
|
|
2092
|
+
aborted = outcome.aborted;
|
|
2093
|
+
abortReasonText = outcome.abortReasonText;
|
|
1495
2094
|
} catch (err) {
|
|
1496
2095
|
exitCode = 1;
|
|
1497
2096
|
if (!abortSignal.aborted) {
|
|
@@ -1499,9 +2098,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1499
2098
|
}
|
|
1500
2099
|
} finally {
|
|
1501
2100
|
if (abortSignal.aborted) {
|
|
1502
|
-
aborted =
|
|
2101
|
+
aborted = monitor.isAbortedRun();
|
|
1503
2102
|
if (aborted) {
|
|
1504
|
-
abortReasonText ??= resolveAbortReasonText();
|
|
2103
|
+
abortReasonText ??= monitor.resolveAbortReasonText();
|
|
1505
2104
|
}
|
|
1506
2105
|
if (exitCode === 0) exitCode = 1;
|
|
1507
2106
|
}
|
|
@@ -1514,13 +2113,39 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1514
2113
|
}
|
|
1515
2114
|
unsubscribe = null;
|
|
1516
2115
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
2116
|
+
const session = monitor.takeActiveSession();
|
|
2117
|
+
if (session) {
|
|
2118
|
+
monitor.captureSalvage(session);
|
|
2119
|
+
const registry = AgentRegistry.global();
|
|
2120
|
+
if (aborted) {
|
|
2121
|
+
// Hard abort (caller signal / wall-clock / budget): terminal teardown.
|
|
2122
|
+
registry.setStatus(id, "aborted");
|
|
2123
|
+
try {
|
|
2124
|
+
await untilAborted(AbortSignal.timeout(5000), () => session.dispose());
|
|
2125
|
+
} catch {
|
|
2126
|
+
// Ignore cleanup errors
|
|
2127
|
+
}
|
|
2128
|
+
} else if (worktree !== undefined) {
|
|
2129
|
+
// Isolated run: the worktree is merged + cleaned after the run, so
|
|
2130
|
+
// the session is not resumable. Park the ref WITHOUT adopting — the
|
|
2131
|
+
// transcript stays reachable (history://), but ensureLive will throw.
|
|
2132
|
+
// Status must flip to "parked" before dispose so the sdk dispose
|
|
2133
|
+
// wrapper skips unregister.
|
|
2134
|
+
registry.setStatus(id, "parked");
|
|
2135
|
+
try {
|
|
2136
|
+
await untilAborted(AbortSignal.timeout(5000), () => session.dispose());
|
|
2137
|
+
} catch {
|
|
2138
|
+
// Ignore cleanup errors
|
|
2139
|
+
}
|
|
2140
|
+
registry.detachSession(id);
|
|
2141
|
+
} else {
|
|
2142
|
+
// Keep-alive: finished and failed subagents both stay interrogable.
|
|
2143
|
+
// The lifecycle manager owns idle-TTL parking + revival from here on.
|
|
2144
|
+
registry.setStatus(id, "idle");
|
|
2145
|
+
AgentLifecycleManager.global().adopt(id, {
|
|
2146
|
+
idleTtlMs: agentIdleTtlMs,
|
|
2147
|
+
revive: reviveSession ?? undefined,
|
|
2148
|
+
});
|
|
1524
2149
|
}
|
|
1525
2150
|
}
|
|
1526
2151
|
}
|
|
@@ -1535,125 +2160,25 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1535
2160
|
};
|
|
1536
2161
|
|
|
1537
2162
|
const done = await runSubagent();
|
|
1538
|
-
|
|
1539
|
-
listenerController.abort();
|
|
1540
|
-
if (runtimeTimeoutId !== undefined) {
|
|
1541
|
-
clearTimeout(runtimeTimeoutId);
|
|
1542
|
-
runtimeTimeoutId = undefined;
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
if (progressTimeoutId) {
|
|
1546
|
-
clearTimeout(progressTimeoutId);
|
|
1547
|
-
progressTimeoutId = null;
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
let exitCode = done.exitCode;
|
|
1551
|
-
if (done.error) {
|
|
1552
|
-
stderr = done.error;
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
// Use final output if available, otherwise accumulated output
|
|
1556
|
-
let rawOutput = finalOutputChunks.length > 0 ? finalOutputChunks.join("") : outputChunks.join("");
|
|
1557
|
-
const yieldItems = progress.extractedToolData?.yield as YieldItem[] | undefined;
|
|
1558
|
-
const reportFindingDetails = progress.extractedToolData?.report_finding as ReportFindingDetails[] | undefined;
|
|
1559
|
-
const reportFindings: ReviewFinding[] | undefined = reportFindingDetails?.map(toReviewFinding);
|
|
1560
|
-
const finalized = finalizeSubprocessOutput({
|
|
1561
|
-
rawOutput,
|
|
1562
|
-
exitCode,
|
|
1563
|
-
stderr,
|
|
1564
|
-
doneAborted: Boolean(done.aborted),
|
|
1565
|
-
signalAborted: Boolean(signal?.aborted),
|
|
1566
|
-
yieldItems,
|
|
1567
|
-
reportFindings,
|
|
1568
|
-
outputSchema,
|
|
1569
|
-
});
|
|
1570
|
-
rawOutput = finalized.rawOutput;
|
|
1571
|
-
exitCode = finalized.exitCode;
|
|
1572
|
-
stderr = finalized.stderr;
|
|
1573
|
-
const lastYield = yieldItems?.[yieldItems.length - 1];
|
|
1574
|
-
const yieldAbortReason = lastYield?.status === "aborted" ? lastYield.error || "Subagent aborted task" : undefined;
|
|
1575
|
-
const { abortedViaYield, hasYield } = finalized;
|
|
1576
|
-
const { content: truncatedOutput, truncated } = truncateTail(rawOutput, {
|
|
1577
|
-
maxBytes: MAX_OUTPUT_BYTES,
|
|
1578
|
-
maxLines: MAX_OUTPUT_LINES,
|
|
1579
|
-
});
|
|
1580
|
-
|
|
1581
|
-
// Write output artifact (input and jsonl already written in real-time)
|
|
1582
|
-
// Compute output metadata for agent:// URL integration
|
|
1583
|
-
let outputMeta: { lineCount: number; charCount: number } | undefined;
|
|
1584
|
-
let outputPath: string | undefined;
|
|
1585
|
-
if (options.artifactsDir) {
|
|
1586
|
-
outputPath = path.join(options.artifactsDir, `${id}.md`);
|
|
1587
|
-
try {
|
|
1588
|
-
await Bun.write(outputPath, rawOutput);
|
|
1589
|
-
outputMeta = {
|
|
1590
|
-
lineCount: rawOutput.split("\n").length,
|
|
1591
|
-
charCount: rawOutput.length,
|
|
1592
|
-
};
|
|
1593
|
-
} catch {
|
|
1594
|
-
// Non-fatal
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
// Update final progress. A wall-clock timeout always wins: if the runtime
|
|
1599
|
-
// limit fired we report aborted/failed regardless of whether a yield landed
|
|
1600
|
-
// while we were tearing the session down. The yield data is still surfaced
|
|
1601
|
-
// to the caller via `progress.extractedToolData`, but the exit status must
|
|
1602
|
-
// reflect the timeout so on-call doesn't mistake a stuck run for success.
|
|
1603
|
-
if (runtimeLimitExceeded && exitCode === 0) {
|
|
1604
|
-
exitCode = 1;
|
|
1605
|
-
}
|
|
1606
|
-
const wasAborted =
|
|
1607
|
-
runtimeLimitExceeded || abortedViaYield || (!hasYield && (done.aborted || signal?.aborted || false));
|
|
1608
|
-
const finalAbortReason = wasAborted
|
|
1609
|
-
? runtimeLimitExceeded
|
|
1610
|
-
? resolveAbortReasonText()
|
|
1611
|
-
: abortedViaYield
|
|
1612
|
-
? yieldAbortReason
|
|
1613
|
-
: (done.abortReason ?? (signal?.aborted ? resolveSignalAbortReason() : resolveAbortReasonText()))
|
|
1614
|
-
: undefined;
|
|
1615
|
-
progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
|
|
1616
|
-
scheduleProgress(true);
|
|
2163
|
+
monitor.finish();
|
|
1617
2164
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
id,
|
|
1622
|
-
agent: agent.name,
|
|
1623
|
-
agentSource: agent.source,
|
|
1624
|
-
description: options.description,
|
|
1625
|
-
status: progress.status as "completed" | "failed" | "aborted",
|
|
1626
|
-
sessionFile: subtaskSessionFile,
|
|
1627
|
-
index,
|
|
1628
|
-
});
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
return {
|
|
2165
|
+
return finalizeRunResult({
|
|
2166
|
+
monitor,
|
|
2167
|
+
done,
|
|
1632
2168
|
index,
|
|
1633
2169
|
id,
|
|
1634
|
-
agent
|
|
1635
|
-
agentSource: agent.source,
|
|
2170
|
+
agent,
|
|
1636
2171
|
task,
|
|
1637
2172
|
assignment,
|
|
1638
2173
|
description: options.description,
|
|
1639
|
-
lastIntent: progress.lastIntent,
|
|
1640
|
-
exitCode,
|
|
1641
|
-
output: truncatedOutput,
|
|
1642
|
-
stderr,
|
|
1643
|
-
truncated: Boolean(truncated),
|
|
1644
|
-
durationMs: Date.now() - startTime,
|
|
1645
|
-
tokens: progress.tokens,
|
|
1646
|
-
contextTokens: progress.contextTokens,
|
|
1647
|
-
contextWindow: progress.contextWindow,
|
|
1648
2174
|
modelOverride,
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
};
|
|
2175
|
+
outputSchema,
|
|
2176
|
+
signal,
|
|
2177
|
+
artifactsDir: options.artifactsDir,
|
|
2178
|
+
eventBus: options.eventBus,
|
|
2179
|
+
parentToolCallId: options.parentToolCallId,
|
|
2180
|
+
detached: options.detached,
|
|
2181
|
+
sessionFile: subtaskSessionFile,
|
|
2182
|
+
startTime,
|
|
2183
|
+
});
|
|
1659
2184
|
}
|