@prometheus-ai/agent 0.5.3 → 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 +39 -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/gateway-cli.d.ts +4 -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/gateway.d.ts +3 -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 +1211 -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/gateway/adapters/telegram/access.d.ts +4 -1
- package/dist/types/gateway/adapters/telegram/setup-api.d.ts +1 -1
- package/dist/types/gateway/adapters/telegram/webhook.d.ts +1 -1
- package/dist/types/gateway/types.d.ts +1 -1
- 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/gateway-cli.ts +32 -2
- 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/gateway.ts +4 -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 +1445 -382
- 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/gateway/adapters/telegram/access.ts +39 -4
- package/src/gateway/adapters/telegram/normalize.ts +16 -1
- package/src/gateway/adapters/telegram/setup-api.ts +7 -1
- package/src/gateway/adapters/telegram/webhook.ts +26 -5
- package/src/gateway/context.ts +9 -1
- package/src/gateway/types.ts +1 -1
- 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 +11 -9
- 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/telegram.ts +77 -22
- 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/index.ts
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
* - .prometheus/agents/*.md (project-level)
|
|
8
8
|
*
|
|
9
9
|
* Supports:
|
|
10
|
-
* - Single agent
|
|
11
|
-
* -
|
|
10
|
+
* - Single agent spawn per call (parallelism = parallel task calls)
|
|
11
|
+
* - Batch spawning + shared context per call when `task.batch` is enabled
|
|
12
|
+
* - Background execution through AsyncJobManager when `async.enabled` is enabled
|
|
12
13
|
* - Progress tracking via JSON events
|
|
13
14
|
* - Session artifacts for debugging
|
|
14
15
|
*/
|
|
16
|
+
|
|
15
17
|
import * as fs from "node:fs/promises";
|
|
16
18
|
import * as os from "node:os";
|
|
17
19
|
import path from "node:path";
|
|
@@ -27,29 +29,34 @@ import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.m
|
|
|
27
29
|
import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
|
|
28
30
|
import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
|
|
29
31
|
import { truncateForPrompt } from "../tools/approval";
|
|
32
|
+
import { isIrcEnabled } from "../tools/irc";
|
|
30
33
|
import { formatBytes, formatDuration } from "../tools/render-utils";
|
|
31
34
|
import {
|
|
32
35
|
type AgentDefinition,
|
|
33
36
|
type AgentProgress,
|
|
37
|
+
canSpawnAtDepth,
|
|
34
38
|
getTaskSchema,
|
|
35
39
|
type SingleResult,
|
|
40
|
+
type TaskItem,
|
|
36
41
|
type TaskParams,
|
|
37
42
|
type TaskToolDetails,
|
|
38
43
|
type TaskToolSchemaInstance,
|
|
39
44
|
} from "./types";
|
|
40
45
|
// Import review tools for side effects (registers subagent tool handlers)
|
|
41
46
|
import "../tools/review";
|
|
47
|
+
import type { AsyncJobManager } from "../async";
|
|
42
48
|
import type { LocalProtocolOptions } from "../internal-urls";
|
|
43
49
|
import { loadOverallPlanReference } from "../plan-mode/plan-handoff";
|
|
50
|
+
import { AgentRegistry } from "../registry/agent-registry";
|
|
44
51
|
import { generateCommitMessage } from "../utils/commit-message-generator";
|
|
45
52
|
import * as git from "../utils/git";
|
|
46
|
-
import { discoverAgents, getAgent } from "./discovery";
|
|
53
|
+
import { type DiscoveryResult, discoverAgents, getAgent } from "./discovery";
|
|
47
54
|
import { runSubprocess } from "./executor";
|
|
55
|
+
import { generateTaskName } from "./name-generator";
|
|
48
56
|
import { AgentOutputManager } from "./output-manager";
|
|
49
57
|
import { mapWithConcurrencyLimit, Semaphore } from "./parallel";
|
|
50
58
|
import { renderResult, renderCall as renderTaskCall } from "./render";
|
|
51
59
|
import { repairTaskParams } from "./repair-args";
|
|
52
|
-
import { getTaskSimpleModeCapabilities, type TaskSimpleMode } from "./simple-mode";
|
|
53
60
|
import {
|
|
54
61
|
applyNestedPatches,
|
|
55
62
|
captureBaseline,
|
|
@@ -65,12 +72,12 @@ import {
|
|
|
65
72
|
type WorktreeBaseline,
|
|
66
73
|
} from "./worktree";
|
|
67
74
|
|
|
68
|
-
function renderSubagentUserPrompt(assignment: string
|
|
75
|
+
function renderSubagentUserPrompt(assignment: string): string {
|
|
69
76
|
return prompt.render(subagentUserPromptTemplate, {
|
|
70
77
|
assignment: assignment.trim(),
|
|
71
|
-
independentMode: simpleMode === "independent",
|
|
72
78
|
});
|
|
73
79
|
}
|
|
80
|
+
|
|
74
81
|
function createUsageTotals(): Usage {
|
|
75
82
|
return {
|
|
76
83
|
input: 0,
|
|
@@ -119,6 +126,7 @@ export type {
|
|
|
119
126
|
AgentDefinition,
|
|
120
127
|
AgentProgress,
|
|
121
128
|
SingleResult,
|
|
129
|
+
SubagentEventPayload,
|
|
122
130
|
SubagentLifecyclePayload,
|
|
123
131
|
SubagentProgressPayload,
|
|
124
132
|
TaskParams,
|
|
@@ -158,10 +166,23 @@ export const READ_ONLY_TOOL_NAMES: ReadonlySet<string> = new Set([
|
|
|
158
166
|
"search_tool_bm25",
|
|
159
167
|
]);
|
|
160
168
|
|
|
169
|
+
const PLAN_MODE_AGENT_TOOL_ALLOWLIST: ReadonlySet<string> = new Set(["ast_grep", "report_finding"]);
|
|
170
|
+
|
|
161
171
|
export function isReadOnlyAgent(agent: AgentDefinition): boolean {
|
|
162
172
|
return !!agent.tools?.length && agent.tools.every(tool => READ_ONLY_TOOL_NAMES.has(tool));
|
|
163
173
|
}
|
|
164
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Preview text for a child result. Falls back to "(no output)" — annotated
|
|
177
|
+
* with the request count when the child actually did work, so the parent can
|
|
178
|
+
* tell a no-op child from one that burned requests before being cancelled.
|
|
179
|
+
*/
|
|
180
|
+
export function formatResultOutputFallback(result: Pick<SingleResult, "output" | "stderr" | "requests">): string {
|
|
181
|
+
const base = result.output.trim() || result.stderr.trim();
|
|
182
|
+
if (base) return base;
|
|
183
|
+
return result.requests > 0 ? `(no output) after ${result.requests} req` : "(no output)";
|
|
184
|
+
}
|
|
185
|
+
|
|
165
186
|
/**
|
|
166
187
|
* Render the tool description from a cached agent list and current settings.
|
|
167
188
|
*/
|
|
@@ -169,9 +190,9 @@ function renderDescription(
|
|
|
169
190
|
agents: AgentDefinition[],
|
|
170
191
|
maxConcurrency: number,
|
|
171
192
|
isolationEnabled: boolean,
|
|
172
|
-
asyncEnabled: boolean,
|
|
173
193
|
disabledAgents: string[],
|
|
174
|
-
|
|
194
|
+
batchEnabled: boolean,
|
|
195
|
+
asyncEnabled: boolean,
|
|
175
196
|
ircEnabled: boolean,
|
|
176
197
|
parentSpawns: string,
|
|
177
198
|
): string {
|
|
@@ -193,19 +214,14 @@ function renderDescription(
|
|
|
193
214
|
description: agent.description,
|
|
194
215
|
readOnly: isReadOnlyAgent(agent),
|
|
195
216
|
}));
|
|
196
|
-
const { contextEnabled, customSchemaEnabled } = getTaskSimpleModeCapabilities(simpleMode);
|
|
197
217
|
return prompt.render(taskDescriptionTemplate, {
|
|
198
218
|
agents: renderedAgents,
|
|
199
219
|
spawningDisabled,
|
|
200
220
|
MAX_CONCURRENCY: maxConcurrency,
|
|
201
221
|
isolationEnabled,
|
|
222
|
+
batchEnabled,
|
|
202
223
|
asyncEnabled,
|
|
203
|
-
contextEnabled,
|
|
204
|
-
customSchemaEnabled,
|
|
205
224
|
ircEnabled,
|
|
206
|
-
defaultMode: simpleMode === "default",
|
|
207
|
-
schemaFreeMode: simpleMode === "schema-free",
|
|
208
|
-
independentMode: simpleMode === "independent",
|
|
209
225
|
});
|
|
210
226
|
}
|
|
211
227
|
|
|
@@ -216,28 +232,173 @@ function createTaskModeError(text: string): AgentToolResult<TaskToolDetails> {
|
|
|
216
232
|
};
|
|
217
233
|
}
|
|
218
234
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
235
|
+
/**
|
|
236
|
+
* Reject fields the current configuration does not accept. `schema` is never
|
|
237
|
+
* accepted (structured output comes from the agent definition's `output`
|
|
238
|
+
* frontmatter, the inherited session schema, or an eval-workflow
|
|
239
|
+
* `agent(..., schema)` call); `tasks`/`context` require `task.batch`.
|
|
240
|
+
*/
|
|
241
|
+
function validateShapeParams(batchEnabled: boolean, params: TaskParams): string | undefined {
|
|
242
|
+
if ((params as Record<string, unknown>).schema !== undefined) {
|
|
243
|
+
return "The task tool does not accept `schema`. Rely on the selected agent definition's `output` schema or the inherited session schema; workflows needing ad-hoc structured output use eval `agent(prompt, schema)`.";
|
|
224
244
|
}
|
|
225
|
-
if (!
|
|
226
|
-
|
|
245
|
+
if (!batchEnabled) {
|
|
246
|
+
const disallowed = (["tasks", "context"] as const).filter(field => params[field] !== undefined);
|
|
247
|
+
if (disallowed.length > 0) {
|
|
248
|
+
return `task.batch is disabled, so the task tool does not accept ${disallowed.map(f => `\`${f}\``).join(" or ")}. Spawn one agent per call with \`assignment\`, or enable the task.batch setting.`;
|
|
249
|
+
}
|
|
227
250
|
}
|
|
228
|
-
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Validate the spawn parameter contract against the wire shapes. `agent` is
|
|
256
|
+
* always required. With `task.batch` the model-facing shape is
|
|
257
|
+
* `{ agent, context, tasks[] }` — `tasks` non-empty with per-item assignments
|
|
258
|
+
* and unique ids, `context` non-empty, no top-level `assignment` alongside.
|
|
259
|
+
* The flat `{ agent, ...item }` form stays accepted at runtime under either
|
|
260
|
+
* setting (internal callers, stale transcripts). Returns a problem
|
|
261
|
+
* description, or undefined when valid.
|
|
262
|
+
*/
|
|
263
|
+
function validateSpawnParams(params: TaskParams, batchEnabled: boolean): string | undefined {
|
|
264
|
+
const agent = typeof params.agent === "string" ? params.agent.trim() : "";
|
|
265
|
+
if (!agent) {
|
|
266
|
+
return "Missing `agent`. Provide an agent type to spawn.";
|
|
267
|
+
}
|
|
268
|
+
const hasAssignment = typeof params.assignment === "string" && params.assignment.trim() !== "";
|
|
269
|
+
const tasks = params.tasks;
|
|
270
|
+
if (batchEnabled && tasks !== undefined) {
|
|
271
|
+
if (!Array.isArray(tasks) || tasks.length === 0) {
|
|
272
|
+
return "Missing `tasks`. Provide at least one task item ({ id?, description?, assignment }).";
|
|
273
|
+
}
|
|
274
|
+
if (hasAssignment) {
|
|
275
|
+
return "Top-level `assignment` is not part of the batch shape. Put the work in `tasks[]` items.";
|
|
276
|
+
}
|
|
277
|
+
for (let i = 0; i < tasks.length; i++) {
|
|
278
|
+
const item = tasks[i];
|
|
279
|
+
if (!item || typeof item.assignment !== "string" || item.assignment.trim() === "") {
|
|
280
|
+
return `Task ${i + 1}${item?.id ? ` (\`${item.id}\`)` : ""} is missing \`assignment\`. Every task needs complete, self-contained instructions.`;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const seen = new Map<string, string>();
|
|
284
|
+
for (const item of tasks) {
|
|
285
|
+
const id = item.id?.trim();
|
|
286
|
+
if (!id) continue;
|
|
287
|
+
const key = id.toLowerCase();
|
|
288
|
+
const existing = seen.get(key);
|
|
289
|
+
if (existing !== undefined) {
|
|
290
|
+
return `Duplicate task id ${existing === id ? `\`${id}\`` : `\`${existing}\` / \`${id}\``}. Provided ids must be unique within a call (case-insensitive).`;
|
|
291
|
+
}
|
|
292
|
+
seen.set(key, id);
|
|
293
|
+
}
|
|
294
|
+
if (typeof params.context !== "string" || params.context.trim() === "") {
|
|
295
|
+
return "Missing `context`. Provide the shared background for this batch — goal, constraints, and any contract the tasks share.";
|
|
296
|
+
}
|
|
229
297
|
return undefined;
|
|
230
298
|
}
|
|
299
|
+
if (!hasAssignment) {
|
|
300
|
+
return batchEnabled
|
|
301
|
+
? "Missing `tasks`. Provide a `tasks` array (one subagent per item) with a shared `context`."
|
|
302
|
+
: "Missing `assignment`. Provide complete, self-contained instructions for the agent.";
|
|
303
|
+
}
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
231
306
|
|
|
232
|
-
|
|
233
|
-
|
|
307
|
+
/**
|
|
308
|
+
* Normalize a validated call into its spawn list: the `tasks[]` batch when
|
|
309
|
+
* provided, otherwise the single top-level spawn.
|
|
310
|
+
*/
|
|
311
|
+
function resolveSpawnItems(params: TaskParams): TaskItem[] {
|
|
312
|
+
if (Array.isArray(params.tasks) && params.tasks.length > 0) {
|
|
313
|
+
return params.tasks;
|
|
234
314
|
}
|
|
315
|
+
return [{ id: params.id, description: params.description, role: params.role, assignment: params.assignment }];
|
|
316
|
+
}
|
|
235
317
|
|
|
236
|
-
|
|
237
|
-
|
|
318
|
+
/**
|
|
319
|
+
* Per-spawn params handed to the executor path: top-level call fields with the
|
|
320
|
+
* item's identity substituted in. `tasks` never leaks into a spawn; the shared
|
|
321
|
+
* `context` rides along unchanged. Keys are only materialized when present —
|
|
322
|
+
* `#runSpawn` distinguishes an absent `isolated` from an explicit one. The
|
|
323
|
+
* item's `isolated` (batch form) wins over the top-level flag (flat form).
|
|
324
|
+
*/
|
|
325
|
+
function spawnParamsFor(params: TaskParams, item: TaskItem): TaskParams {
|
|
326
|
+
const spawn: TaskParams = { agent: params.agent };
|
|
327
|
+
if (item.id !== undefined) spawn.id = item.id;
|
|
328
|
+
if (item.description !== undefined) spawn.description = item.description;
|
|
329
|
+
if (item.role !== undefined) spawn.role = item.role;
|
|
330
|
+
if (item.assignment !== undefined) spawn.assignment = item.assignment;
|
|
331
|
+
if (params.context !== undefined) spawn.context = params.context;
|
|
332
|
+
if (item.isolated !== undefined) {
|
|
333
|
+
spawn.isolated = item.isolated;
|
|
334
|
+
} else if ("isolated" in params) {
|
|
335
|
+
spawn.isolated = params.isolated;
|
|
238
336
|
}
|
|
337
|
+
return spawn;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** Generic worker agents whose output sharpens with a tailored `role` rather than the bare type. */
|
|
341
|
+
const GENERIC_SPAWN_AGENTS: ReadonlySet<string> = new Set(["task", "quick_task"]);
|
|
239
342
|
|
|
240
|
-
|
|
343
|
+
/**
|
|
344
|
+
* Advisory — never a rejection — nudging the spawner toward tailored
|
|
345
|
+
* specialists when it spawns generic role-less workers and still holds spawn
|
|
346
|
+
* capacity (DepthCapacity: it currently has the `task` tool). Fires when a
|
|
347
|
+
* generic `task`/`quick_task` spawn carries no `role`, or when one call clones
|
|
348
|
+
* the same agent ≥2× all without roles. Returns undefined when no nudge applies.
|
|
349
|
+
*/
|
|
350
|
+
export function buildSpecializationAdvisory(
|
|
351
|
+
agentName: string | undefined,
|
|
352
|
+
items: TaskItem[],
|
|
353
|
+
depthCapacity: boolean,
|
|
354
|
+
): string | undefined {
|
|
355
|
+
if (!depthCapacity) return undefined;
|
|
356
|
+
const rolelessCount = items.filter(item => !item.role?.trim()).length;
|
|
357
|
+
if (rolelessCount === 0) return undefined;
|
|
358
|
+
const generic = agentName !== undefined && GENERIC_SPAWN_AGENTS.has(agentName);
|
|
359
|
+
const cloned = items.length >= 2 && rolelessCount === items.length;
|
|
360
|
+
if (!generic && !cloned) return undefined;
|
|
361
|
+
const label = agentName ?? "task";
|
|
362
|
+
return (
|
|
363
|
+
`Tip: spawned ${rolelessCount} \`${label}\` worker${rolelessCount === 1 ? "" : "s"} without a \`role\`. ` +
|
|
364
|
+
`Tailored specialists outperform generic workers — give each spawn a \`role\` naming its expertise ` +
|
|
365
|
+
`(e.g. "Auth-flow security reviewer"). Depth budget remains, so decompose into named specialists ` +
|
|
366
|
+
`rather than cloning one generic worker.`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Sentinel for async jobs whose subagent finished with a failing result; progress is already updated. */
|
|
371
|
+
class TaskJobError extends Error {}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Process-level memo for create-time agent discovery, keyed by resolved cwd.
|
|
375
|
+
*
|
|
376
|
+
* `TaskTool.create` runs for every (sub)agent session in this process and the
|
|
377
|
+
* walk-up + plugin-registry scan in `discoverAgents` is identical for a given
|
|
378
|
+
* cwd, so repeat creations reuse the first scan. Execution-time discovery
|
|
379
|
+
* (`#runSpawn`) intentionally stays fresh. The memo also tracks the live
|
|
380
|
+
* `discoverAgents` binding: test spies swap that binding, which invalidates
|
|
381
|
+
* the memo automatically.
|
|
382
|
+
*/
|
|
383
|
+
const discoveryMemo = new Map<string, Promise<DiscoveryResult>>();
|
|
384
|
+
let discoveryMemoFn: typeof discoverAgents | undefined;
|
|
385
|
+
|
|
386
|
+
function discoverAgentsForCreate(cwd: string): Promise<DiscoveryResult> {
|
|
387
|
+
const fn = discoverAgents;
|
|
388
|
+
if (discoveryMemoFn !== fn) {
|
|
389
|
+
discoveryMemoFn = fn;
|
|
390
|
+
discoveryMemo.clear();
|
|
391
|
+
}
|
|
392
|
+
const key = path.resolve(cwd);
|
|
393
|
+
let pending = discoveryMemo.get(key);
|
|
394
|
+
if (!pending) {
|
|
395
|
+
pending = fn(cwd);
|
|
396
|
+
discoveryMemo.set(key, pending);
|
|
397
|
+
pending.catch(() => {
|
|
398
|
+
if (discoveryMemo.get(key) === pending) discoveryMemo.delete(key);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
return pending;
|
|
241
402
|
}
|
|
242
403
|
|
|
243
404
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -247,8 +408,9 @@ function validateTaskModeParams(simpleMode: TaskSimpleMode, params: TaskParams):
|
|
|
247
408
|
/**
|
|
248
409
|
* Task tool - Delegate tasks to specialized agents.
|
|
249
410
|
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
411
|
+
* Each call spawns one subagent — or, with `task.batch`, one per `tasks[]`
|
|
412
|
+
* item. When `async.enabled` is on, spawns run as AsyncJobManager jobs; when
|
|
413
|
+
* disabled, the tool blocks until every spawn finishes.
|
|
252
414
|
*/
|
|
253
415
|
export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetails, Theme> {
|
|
254
416
|
readonly name = "task";
|
|
@@ -259,11 +421,30 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
259
421
|
if (typeof params.agent === "string") {
|
|
260
422
|
lines.push(`Agent: ${truncateForPrompt(params.agent)}`);
|
|
261
423
|
}
|
|
424
|
+
if (typeof params.role === "string" && params.role.trim()) {
|
|
425
|
+
lines.push(`Role: ${truncateForPrompt(params.role)}`);
|
|
426
|
+
}
|
|
427
|
+
if (typeof params.id === "string" && params.id.trim()) {
|
|
428
|
+
lines.push(`Task: ${truncateForPrompt(params.id)}`);
|
|
429
|
+
}
|
|
430
|
+
if (typeof params.assignment === "string") {
|
|
431
|
+
lines.push(`Assignment:\n${truncateForPrompt(params.assignment)}`);
|
|
432
|
+
}
|
|
433
|
+
if (typeof params.context === "string" && params.context.trim()) {
|
|
434
|
+
lines.push(`Context:\n${truncateForPrompt(params.context)}`);
|
|
435
|
+
}
|
|
262
436
|
const tasks = Array.isArray(params.tasks) ? params.tasks : [];
|
|
263
437
|
const firstTask = tasks[0];
|
|
264
438
|
if (firstTask) {
|
|
265
|
-
|
|
266
|
-
|
|
439
|
+
if (typeof firstTask.id === "string" && firstTask.id.trim()) {
|
|
440
|
+
lines.push(`Task: ${truncateForPrompt(firstTask.id)}`);
|
|
441
|
+
}
|
|
442
|
+
if (typeof firstTask.role === "string" && firstTask.role.trim()) {
|
|
443
|
+
lines.push(`Role: ${truncateForPrompt(firstTask.role)}`);
|
|
444
|
+
}
|
|
445
|
+
if (typeof firstTask.assignment === "string") {
|
|
446
|
+
lines.push(`Assignment:\n${truncateForPrompt(firstTask.assignment)}`);
|
|
447
|
+
}
|
|
267
448
|
if (tasks.length > 1) {
|
|
268
449
|
lines.push(`+${tasks.length - 1} more task${tasks.length === 2 ? "" : "s"}`);
|
|
269
450
|
}
|
|
@@ -271,16 +452,26 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
271
452
|
return lines;
|
|
272
453
|
};
|
|
273
454
|
readonly label = "Task";
|
|
274
|
-
readonly summary = "Spawn
|
|
455
|
+
readonly summary = "Spawn subagents to complete delegated tasks";
|
|
275
456
|
readonly strict = true;
|
|
276
457
|
readonly loadMode = "discoverable";
|
|
277
458
|
readonly renderResult = renderResult;
|
|
459
|
+
// Suppress the streaming call preview once a (partial or final) result exists
|
|
460
|
+
// so the task renders as ONE block that transitions in place — not a pending
|
|
461
|
+
// call frame stacked above the result frame. Mirrors `taskToolRenderer`.
|
|
462
|
+
readonly mergeCallAndResult = true;
|
|
278
463
|
readonly #discoveredAgents: AgentDefinition[];
|
|
279
464
|
readonly #blockedAgent: string | undefined;
|
|
465
|
+
/**
|
|
466
|
+
* One semaphore per TaskTool instance (i.e. per session): bounds concurrent
|
|
467
|
+
* subagents across parallel `task` calls within the session. Sized from
|
|
468
|
+
* `task.maxConcurrency` at first use; later setting changes do not resize it.
|
|
469
|
+
*/
|
|
470
|
+
#spawnSemaphore: Semaphore | undefined;
|
|
280
471
|
|
|
281
472
|
get parameters(): TaskToolSchemaInstance {
|
|
282
473
|
const isolationEnabled = this.session.settings.get("task.isolation.mode") !== "none";
|
|
283
|
-
return getTaskSchema({ isolationEnabled,
|
|
474
|
+
return getTaskSchema({ isolationEnabled, batchEnabled: this.#isBatchEnabled() });
|
|
284
475
|
}
|
|
285
476
|
|
|
286
477
|
renderCall(args: unknown, options: Parameters<typeof renderTaskCall>[1], theme: Theme) {
|
|
@@ -296,10 +487,10 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
296
487
|
this.#discoveredAgents,
|
|
297
488
|
maxConcurrency,
|
|
298
489
|
isolationMode !== "none",
|
|
299
|
-
this.session.settings.get("async.enabled"),
|
|
300
490
|
disabledAgents,
|
|
301
|
-
this.#
|
|
302
|
-
this.session.settings.get("
|
|
491
|
+
this.#isBatchEnabled(),
|
|
492
|
+
this.session.settings.get("async.enabled"),
|
|
493
|
+
isIrcEnabled(this.session.settings, this.session.taskDepth ?? 0),
|
|
303
494
|
this.session.getSessionSpawns() ?? "*",
|
|
304
495
|
);
|
|
305
496
|
}
|
|
@@ -311,326 +502,488 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
311
502
|
this.#discoveredAgents = discoveredAgents;
|
|
312
503
|
}
|
|
313
504
|
|
|
314
|
-
#
|
|
315
|
-
return this.session.settings.get("task.
|
|
505
|
+
#isBatchEnabled(): boolean {
|
|
506
|
+
return this.session.settings.get("task.batch");
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
#getSpawnSemaphore(): Semaphore {
|
|
510
|
+
this.#spawnSemaphore ??= new Semaphore(this.session.settings.get("task.maxConcurrency"));
|
|
511
|
+
return this.#spawnSemaphore;
|
|
316
512
|
}
|
|
317
513
|
|
|
318
514
|
/**
|
|
319
515
|
* Create a TaskTool instance with async agent discovery.
|
|
320
516
|
*/
|
|
321
517
|
static async create(session: ToolSession): Promise<TaskTool> {
|
|
322
|
-
const { agents } = await
|
|
518
|
+
const { agents } = await discoverAgentsForCreate(session.cwd);
|
|
323
519
|
return new TaskTool(session, agents);
|
|
324
520
|
}
|
|
325
521
|
|
|
326
522
|
async execute(
|
|
327
|
-
|
|
523
|
+
toolCallId: string,
|
|
328
524
|
rawParams: unknown,
|
|
329
525
|
signal?: AbortSignal,
|
|
330
526
|
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
|
|
331
527
|
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
332
528
|
const params = repairTaskParams(rawParams as TaskParams);
|
|
333
|
-
const
|
|
334
|
-
const validationError =
|
|
529
|
+
const batchEnabled = this.#isBatchEnabled();
|
|
530
|
+
const validationError = validateShapeParams(batchEnabled, params) ?? validateSpawnParams(params, batchEnabled);
|
|
335
531
|
if (validationError) {
|
|
336
532
|
return createTaskModeError(validationError);
|
|
337
533
|
}
|
|
338
534
|
|
|
339
|
-
const
|
|
535
|
+
const spawnItems = resolveSpawnItems(params);
|
|
340
536
|
const selectedAgent = this.#discoveredAgents.find(agent => agent.name === params.agent);
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
537
|
+
const asyncEnabled = this.session.settings.get("async.enabled");
|
|
538
|
+
const manager = asyncEnabled ? this.session.asyncJobManager : undefined;
|
|
539
|
+
const depthCapacity = canSpawnAtDepth(
|
|
540
|
+
this.session.settings.get("task.maxRecursionDepth") ?? 2,
|
|
541
|
+
this.session.taskDepth ?? 0,
|
|
542
|
+
);
|
|
543
|
+
const advisory = buildSpecializationAdvisory(params.agent, spawnItems, depthCapacity);
|
|
544
|
+
const withAdvisory = (result: AgentToolResult<TaskToolDetails>): AgentToolResult<TaskToolDetails> => {
|
|
545
|
+
if (!advisory) return result;
|
|
546
|
+
const textPart = result.content.find(part => part.type === "text");
|
|
547
|
+
if (textPart && typeof textPart.text === "string") {
|
|
548
|
+
textPart.text = `${textPart.text}\n\n${advisory}`;
|
|
549
|
+
} else {
|
|
550
|
+
result.content.push({ type: "text", text: advisory });
|
|
551
|
+
}
|
|
552
|
+
return result;
|
|
553
|
+
};
|
|
554
|
+
if (!asyncEnabled || !manager || selectedAgent?.blocking === true) {
|
|
555
|
+
// Sync fallback: async execution disabled, orphaned host that never
|
|
556
|
+
// wired a job manager, or an agent definition that declares
|
|
557
|
+
// `blocking: true`. The session-scoped semaphore still bounds fan-out
|
|
558
|
+
// across parallel task calls.
|
|
559
|
+
if (asyncEnabled && !manager) {
|
|
560
|
+
logger.warn("task: no AsyncJobManager registered; falling back to sync execution");
|
|
561
|
+
}
|
|
562
|
+
return withAdvisory(await this.#executeSyncFanout(toolCallId, params, spawnItems, signal, onUpdate));
|
|
358
563
|
}
|
|
359
564
|
|
|
565
|
+
// Resolve agent ids up front so the immediate result can name them.
|
|
360
566
|
const outputManager =
|
|
361
567
|
this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
|
|
362
|
-
const
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const
|
|
368
|
-
const assignment =
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
568
|
+
const agentLabel = params.agent ?? "task";
|
|
569
|
+
const agentSource = selectedAgent?.source ?? "bundled";
|
|
570
|
+
const spawns: Array<{ agentId: string; item: TaskItem; progress: AgentProgress }> = [];
|
|
571
|
+
for (let index = 0; index < spawnItems.length; index++) {
|
|
572
|
+
const item = spawnItems[index];
|
|
573
|
+
const agentId = await outputManager.allocate(item.id?.trim() || generateTaskName());
|
|
574
|
+
const assignment = (item.assignment ?? "").trim();
|
|
575
|
+
spawns.push({
|
|
576
|
+
agentId,
|
|
577
|
+
item,
|
|
578
|
+
progress: {
|
|
579
|
+
index,
|
|
580
|
+
id: agentId,
|
|
581
|
+
agent: agentLabel,
|
|
582
|
+
agentSource,
|
|
583
|
+
status: "pending",
|
|
584
|
+
task: renderSubagentUserPrompt(assignment),
|
|
585
|
+
assignment,
|
|
586
|
+
description: item.description,
|
|
587
|
+
recentTools: [],
|
|
588
|
+
recentOutput: [],
|
|
589
|
+
toolCount: 0,
|
|
590
|
+
requests: 0,
|
|
591
|
+
tokens: 0,
|
|
592
|
+
cost: 0,
|
|
593
|
+
durationMs: 0,
|
|
594
|
+
},
|
|
384
595
|
});
|
|
385
596
|
}
|
|
386
597
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
.map(progress => structuredClone(progress));
|
|
396
|
-
};
|
|
397
|
-
|
|
598
|
+
// Aggregate async state for the one tool call: every spawn's job reports
|
|
599
|
+
// into the shared progress snapshot; the call stays "running" until all
|
|
600
|
+
// jobs settle, then turns "failed" if any spawn failed. The single-spawn
|
|
601
|
+
// case passes the job's own suggestion through (pre-batch behavior).
|
|
602
|
+
const single = spawns.length === 1;
|
|
603
|
+
let settledCount = 0;
|
|
604
|
+
let failedCount = 0;
|
|
605
|
+
let primaryJobId = spawns[0].agentId;
|
|
398
606
|
const buildAsyncDetails = (state: "running" | "completed" | "failed", jobId: string): TaskToolDetails => ({
|
|
399
607
|
projectAgentsDir: null,
|
|
400
608
|
results: [],
|
|
401
609
|
totalDurationMs: 0,
|
|
402
|
-
progress:
|
|
403
|
-
async: {
|
|
610
|
+
progress: spawns.map(spawn => ({ ...spawn.progress })),
|
|
611
|
+
async: {
|
|
612
|
+
state: single ? state : settledCount < spawns.length ? "running" : failedCount > 0 ? "failed" : "completed",
|
|
613
|
+
jobId: single ? jobId : primaryJobId,
|
|
614
|
+
type: "task",
|
|
615
|
+
},
|
|
404
616
|
});
|
|
405
617
|
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
details: buildAsyncDetails(state, primaryJobId),
|
|
411
|
-
});
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
const maxConcurrency = this.session.settings.get("task.maxConcurrency");
|
|
415
|
-
const semaphore = new Semaphore(maxConcurrency);
|
|
416
|
-
|
|
417
|
-
for (let i = 0; i < taskItems.length; i++) {
|
|
418
|
-
const taskItem = taskItems[i];
|
|
419
|
-
if (signal?.aborted) {
|
|
420
|
-
failedSchedules.push(`${taskItem.id}: cancelled before scheduling`);
|
|
421
|
-
const progress = progressByTaskId.get(taskItem.id);
|
|
422
|
-
if (progress) {
|
|
423
|
-
progress.status = "aborted";
|
|
424
|
-
}
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const uniqueId = uniqueIds[i];
|
|
429
|
-
const singleParams: TaskParams = { ...params, tasks: [taskItem] };
|
|
430
|
-
const label = uniqueId;
|
|
618
|
+
const ircEnabled = isIrcEnabled(this.session.settings, this.session.taskDepth ?? 0);
|
|
619
|
+
const started: Array<{ agentId: string; jobId: string; description?: string }> = [];
|
|
620
|
+
const failedSchedules: string[] = [];
|
|
621
|
+
for (const spawn of spawns) {
|
|
431
622
|
try {
|
|
432
|
-
const jobId =
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
throw new Error("Aborted before execution");
|
|
445
|
-
}
|
|
446
|
-
if (progress) {
|
|
447
|
-
progress.status = "running";
|
|
448
|
-
}
|
|
449
|
-
await reportProgress(
|
|
450
|
-
`Running background task ${taskItem.id}...`,
|
|
451
|
-
buildAsyncDetails("running", startedJobs[0]?.jobId ?? label) as unknown as Record<string, unknown>,
|
|
452
|
-
);
|
|
453
|
-
try {
|
|
454
|
-
const result = await this.#executeSync(_toolCallId, singleParams, runSignal, undefined, [
|
|
455
|
-
uniqueId,
|
|
456
|
-
]);
|
|
457
|
-
const finalText = result.content.find(part => part.type === "text")?.text ?? "(no output)";
|
|
458
|
-
const singleResult = result.details?.results[0];
|
|
459
|
-
if (progress) {
|
|
460
|
-
progress.status = singleResult?.aborted
|
|
461
|
-
? "aborted"
|
|
462
|
-
: (singleResult?.exitCode ?? 0) === 0
|
|
463
|
-
? "completed"
|
|
464
|
-
: "failed";
|
|
465
|
-
progress.durationMs = singleResult?.durationMs ?? Math.max(0, Date.now() - startedAt);
|
|
466
|
-
progress.tokens = singleResult?.tokens ?? 0;
|
|
467
|
-
progress.contextTokens = singleResult?.contextTokens;
|
|
468
|
-
progress.contextWindow = singleResult?.contextWindow;
|
|
469
|
-
progress.cost = singleResult?.usage?.cost.total ?? 0;
|
|
470
|
-
progress.extractedToolData = singleResult?.extractedToolData;
|
|
471
|
-
progress.retryFailure = singleResult?.retryFailure;
|
|
472
|
-
progress.retryState = undefined;
|
|
473
|
-
}
|
|
474
|
-
completedJobs += 1;
|
|
475
|
-
if (singleResult && ((singleResult.aborted ?? false) || singleResult.exitCode !== 0)) {
|
|
476
|
-
failedJobs += 1;
|
|
477
|
-
}
|
|
478
|
-
const remaining = taskItems.length - completedJobs;
|
|
479
|
-
const isDone = remaining === 0;
|
|
480
|
-
await reportProgress(
|
|
481
|
-
isDone
|
|
482
|
-
? `Background task batch complete: ${completedJobs}/${taskItems.length} finished.`
|
|
483
|
-
: `Background task batch progress: ${completedJobs}/${taskItems.length} finished (${remaining} running).`,
|
|
484
|
-
buildAsyncDetails(
|
|
485
|
-
isDone ? (failedJobs > 0 || failedSchedules.length > 0 ? "failed" : "completed") : "running",
|
|
486
|
-
startedJobs[0]?.jobId ?? label,
|
|
487
|
-
) as unknown as Record<string, unknown>,
|
|
488
|
-
);
|
|
489
|
-
if (isDone) {
|
|
490
|
-
emitAsyncUpdate(
|
|
491
|
-
failedJobs > 0 || failedSchedules.length > 0 ? "failed" : "completed",
|
|
492
|
-
`Background task batch complete: ${completedJobs}/${taskItems.length} finished.`,
|
|
493
|
-
);
|
|
494
|
-
}
|
|
495
|
-
return finalText;
|
|
496
|
-
} catch (error) {
|
|
497
|
-
if (progress) {
|
|
498
|
-
progress.status = "failed";
|
|
499
|
-
progress.durationMs = Math.max(0, Date.now() - startedAt);
|
|
500
|
-
}
|
|
501
|
-
completedJobs += 1;
|
|
502
|
-
failedJobs += 1;
|
|
503
|
-
const remaining = taskItems.length - completedJobs;
|
|
504
|
-
const isDone = remaining === 0;
|
|
505
|
-
await reportProgress(
|
|
506
|
-
isDone
|
|
507
|
-
? `Background task batch complete with failures: ${failedJobs} failed.`
|
|
508
|
-
: `Background task batch progress: ${completedJobs}/${taskItems.length} finished (${remaining} running).`,
|
|
509
|
-
buildAsyncDetails(
|
|
510
|
-
isDone ? "failed" : "running",
|
|
511
|
-
startedJobs[0]?.jobId ?? label,
|
|
512
|
-
) as unknown as Record<string, unknown>,
|
|
513
|
-
);
|
|
514
|
-
if (isDone) {
|
|
515
|
-
emitAsyncUpdate(
|
|
516
|
-
"failed",
|
|
517
|
-
`Background task batch complete with failures: ${failedJobs} failed.`,
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
throw error;
|
|
521
|
-
} finally {
|
|
522
|
-
semaphore.release();
|
|
523
|
-
}
|
|
524
|
-
},
|
|
525
|
-
{
|
|
526
|
-
id: label,
|
|
527
|
-
ownerId: this.session.getAgentId?.() ?? undefined,
|
|
528
|
-
onProgress: (text, details) => {
|
|
529
|
-
const progressDetails =
|
|
530
|
-
(details as TaskToolDetails | undefined) ??
|
|
531
|
-
buildAsyncDetails("running", startedJobs[0]?.jobId ?? label);
|
|
532
|
-
onUpdate?.({ content: [{ type: "text", text }], details: progressDetails });
|
|
533
|
-
},
|
|
623
|
+
const jobId = this.#registerSpawnJob({
|
|
624
|
+
manager,
|
|
625
|
+
toolCallId,
|
|
626
|
+
spawnParams: spawnParamsFor(params, spawn.item),
|
|
627
|
+
agentId: spawn.agentId,
|
|
628
|
+
progress: spawn.progress,
|
|
629
|
+
ircEnabled,
|
|
630
|
+
buildDetails: buildAsyncDetails,
|
|
631
|
+
onUpdate,
|
|
632
|
+
onSettled: failed => {
|
|
633
|
+
settledCount += 1;
|
|
634
|
+
if (failed) failedCount += 1;
|
|
534
635
|
},
|
|
535
|
-
);
|
|
536
|
-
|
|
636
|
+
});
|
|
637
|
+
if (started.length === 0) primaryJobId = jobId;
|
|
638
|
+
started.push({ agentId: spawn.agentId, jobId, description: spawn.item.description });
|
|
537
639
|
} catch (error) {
|
|
538
640
|
const message = error instanceof Error ? error.message : String(error);
|
|
539
|
-
failedSchedules.push(`${
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
641
|
+
failedSchedules.push(`${spawn.agentId}: ${message}`);
|
|
642
|
+
spawn.progress.status = "failed";
|
|
643
|
+
settledCount += 1;
|
|
644
|
+
failedCount += 1;
|
|
544
645
|
}
|
|
545
646
|
}
|
|
546
647
|
|
|
547
|
-
if (
|
|
548
|
-
const failureText = `Failed to start background task jobs: ${failedSchedules.join("; ")}`;
|
|
648
|
+
if (started.length === 0) {
|
|
549
649
|
return {
|
|
550
|
-
content: [
|
|
650
|
+
content: [
|
|
651
|
+
{
|
|
652
|
+
type: "text",
|
|
653
|
+
text: `Failed to start background task job${single ? "" : "s"}: ${failedSchedules.join("; ")}`,
|
|
654
|
+
},
|
|
655
|
+
],
|
|
551
656
|
details: { projectAgentsDir: null, results: [], totalDurationMs: 0 },
|
|
552
657
|
};
|
|
553
658
|
}
|
|
554
659
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
660
|
+
if (single) {
|
|
661
|
+
const { agentId, jobId, description } = started[0];
|
|
662
|
+
const coordinationHint = ircEnabled
|
|
663
|
+
? `DM \`${agentId}\` via \`irc\` to coordinate while it runs; use \`job\` only to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task.`
|
|
664
|
+
: `Use \`job\` to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task.`;
|
|
665
|
+
const descriptionSuffix = description ? ` — ${description}` : "";
|
|
666
|
+
onUpdate?.({
|
|
667
|
+
content: [{ type: "text", text: `Spawned agent \`${agentId}\`...` }],
|
|
668
|
+
details: buildAsyncDetails("running", jobId),
|
|
669
|
+
});
|
|
670
|
+
return withAdvisory({
|
|
671
|
+
content: [
|
|
672
|
+
{
|
|
673
|
+
type: "text",
|
|
674
|
+
text: `Spawned agent \`${agentId}\` (job \`${jobId}\`)${descriptionSuffix}. The result will be delivered when it yields. ${coordinationHint}`,
|
|
675
|
+
},
|
|
676
|
+
],
|
|
677
|
+
details: buildAsyncDetails("running", jobId),
|
|
678
|
+
});
|
|
679
|
+
}
|
|
559
680
|
|
|
681
|
+
const coordinationHint = ircEnabled
|
|
682
|
+
? `DM these ids via \`irc\` to coordinate while they run; use \`job\` only to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task.`
|
|
683
|
+
: `Use \`job\` to inspect (\`list\`), wait (\`poll\`), or cancel a stuck task by id.`;
|
|
560
684
|
const scheduleFailureSummary =
|
|
561
685
|
failedSchedules.length > 0
|
|
562
|
-
? ` Failed to schedule ${failedSchedules.length}
|
|
686
|
+
? ` Failed to schedule ${failedSchedules.length} spawn${failedSchedules.length === 1 ? "" : "s"}: ${failedSchedules.join("; ")}.`
|
|
563
687
|
: "";
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
taskIdByItemId.set(taskItems[i].id, uniqueIds[i]);
|
|
569
|
-
}
|
|
570
|
-
const startedListing = startedJobs
|
|
571
|
-
.map(({ taskId, jobId }) => {
|
|
572
|
-
const id = taskIdByItemId.get(taskId) ?? taskId;
|
|
573
|
-
const desc = progressByTaskId.get(taskId)?.description;
|
|
574
|
-
const prefix = `- \`${id}\` (job \`${jobId}\`)`;
|
|
575
|
-
return desc ? `${prefix} — ${desc}` : prefix;
|
|
688
|
+
const startedListing = started
|
|
689
|
+
.map(({ agentId, jobId, description }) => {
|
|
690
|
+
const prefix = `- \`${agentId}\` (job \`${jobId}\`)`;
|
|
691
|
+
return description ? `${prefix} — ${description}` : prefix;
|
|
576
692
|
})
|
|
577
693
|
.join("\n");
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
:
|
|
581
|
-
|
|
582
|
-
return {
|
|
694
|
+
onUpdate?.({
|
|
695
|
+
content: [{ type: "text", text: `Spawned ${started.length} agents...` }],
|
|
696
|
+
details: buildAsyncDetails("running", primaryJobId),
|
|
697
|
+
});
|
|
698
|
+
return withAdvisory({
|
|
583
699
|
content: [
|
|
584
700
|
{
|
|
585
701
|
type: "text",
|
|
586
|
-
text: `
|
|
702
|
+
text: `Spawned ${started.length} background agents using ${agentLabel}.${scheduleFailureSummary} Each result will be delivered when that agent yields.\n${startedListing}\n${coordinationHint}`,
|
|
587
703
|
},
|
|
588
704
|
],
|
|
705
|
+
details: buildAsyncDetails("running", primaryJobId),
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Register one background job that runs a single spawn to completion and
|
|
711
|
+
* delivers its yield text. The job body mirrors the sync path; `buildDetails`
|
|
712
|
+
* supplies the (possibly batch-shared) progress snapshot and `onSettled`
|
|
713
|
+
* feeds the caller's aggregate counters.
|
|
714
|
+
*/
|
|
715
|
+
#registerSpawnJob(options: {
|
|
716
|
+
manager: AsyncJobManager;
|
|
717
|
+
toolCallId: string;
|
|
718
|
+
spawnParams: TaskParams;
|
|
719
|
+
agentId: string;
|
|
720
|
+
progress: AgentProgress;
|
|
721
|
+
ircEnabled: boolean;
|
|
722
|
+
buildDetails: (state: "running" | "completed" | "failed", jobId: string) => TaskToolDetails;
|
|
723
|
+
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>;
|
|
724
|
+
onSettled?: (failed: boolean) => void;
|
|
725
|
+
}): string {
|
|
726
|
+
const { manager, toolCallId, spawnParams, agentId, progress, ircEnabled, buildDetails, onUpdate, onSettled } =
|
|
727
|
+
options;
|
|
728
|
+
const buildFollowUpHint = (aborted: boolean): string => {
|
|
729
|
+
if (aborted) {
|
|
730
|
+
return `\n\n${agentId} was aborted — transcript at history://${agentId}`;
|
|
731
|
+
}
|
|
732
|
+
const followUp = ircEnabled ? "message it via `irc` to follow up; " : "";
|
|
733
|
+
return `\n\n${agentId} is now idle — ${followUp}transcript at history://${agentId}`;
|
|
734
|
+
};
|
|
735
|
+
return manager.register(
|
|
736
|
+
"task",
|
|
737
|
+
agentId,
|
|
738
|
+
async ({ jobId: ownJobId, signal: runSignal, reportProgress, markRunning }) => {
|
|
739
|
+
const startedAt = Date.now();
|
|
740
|
+
const semaphore = this.#getSpawnSemaphore();
|
|
741
|
+
await semaphore.acquire();
|
|
742
|
+
if (runSignal.aborted) {
|
|
743
|
+
semaphore.release();
|
|
744
|
+
progress.status = "aborted";
|
|
745
|
+
onSettled?.(true);
|
|
746
|
+
throw new Error("Aborted before execution");
|
|
747
|
+
}
|
|
748
|
+
markRunning();
|
|
749
|
+
progress.status = "running";
|
|
750
|
+
await reportProgress(
|
|
751
|
+
`Running background task ${agentId}...`,
|
|
752
|
+
buildDetails("running", ownJobId) as unknown as Record<string, unknown>,
|
|
753
|
+
);
|
|
754
|
+
try {
|
|
755
|
+
const result = await this.#executeSync(
|
|
756
|
+
toolCallId,
|
|
757
|
+
spawnParams,
|
|
758
|
+
runSignal,
|
|
759
|
+
undefined,
|
|
760
|
+
agentId,
|
|
761
|
+
progress.index,
|
|
762
|
+
true,
|
|
763
|
+
);
|
|
764
|
+
const finalText = result.content.find(part => part.type === "text")?.text ?? "(no output)";
|
|
765
|
+
const singleResult = result.details?.results[0];
|
|
766
|
+
// A missing result means the sync path failed at the tool level
|
|
767
|
+
// (results: []) — treat it as a failure, not success.
|
|
768
|
+
const resultFailed = !singleResult || (singleResult.aborted ?? false) || singleResult.exitCode !== 0;
|
|
769
|
+
progress.status = singleResult?.aborted ? "aborted" : resultFailed ? "failed" : "completed";
|
|
770
|
+
progress.durationMs = singleResult?.durationMs ?? Math.max(0, Date.now() - startedAt);
|
|
771
|
+
progress.tokens = singleResult?.tokens ?? 0;
|
|
772
|
+
progress.requests = singleResult?.requests ?? 0;
|
|
773
|
+
progress.contextTokens = singleResult?.contextTokens;
|
|
774
|
+
progress.contextWindow = singleResult?.contextWindow;
|
|
775
|
+
progress.cost = singleResult?.usage?.cost.total ?? 0;
|
|
776
|
+
progress.extractedToolData = singleResult?.extractedToolData;
|
|
777
|
+
progress.retryFailure = singleResult?.retryFailure;
|
|
778
|
+
progress.retryState = undefined;
|
|
779
|
+
onSettled?.(resultFailed);
|
|
780
|
+
const statusText = resultFailed
|
|
781
|
+
? `Background task ${agentId} failed.`
|
|
782
|
+
: `Background task ${agentId} complete.`;
|
|
783
|
+
await reportProgress(
|
|
784
|
+
statusText,
|
|
785
|
+
buildDetails(resultFailed ? "failed" : "completed", ownJobId) as unknown as Record<string, unknown>,
|
|
786
|
+
);
|
|
787
|
+
onUpdate?.({
|
|
788
|
+
content: [{ type: "text", text: statusText }],
|
|
789
|
+
details: buildDetails(resultFailed ? "failed" : "completed", ownJobId),
|
|
790
|
+
});
|
|
791
|
+
const deliveryText = `${finalText}${buildFollowUpHint(singleResult?.aborted === true)}`;
|
|
792
|
+
if (resultFailed) {
|
|
793
|
+
// Mark the job itself failed; the failed agent stays interrogable.
|
|
794
|
+
throw new TaskJobError(deliveryText);
|
|
795
|
+
}
|
|
796
|
+
return deliveryText;
|
|
797
|
+
} catch (error) {
|
|
798
|
+
if (error instanceof TaskJobError) {
|
|
799
|
+
throw error;
|
|
800
|
+
}
|
|
801
|
+
progress.status = "failed";
|
|
802
|
+
progress.durationMs = Math.max(0, Date.now() - startedAt);
|
|
803
|
+
onSettled?.(true);
|
|
804
|
+
const statusText = `Background task ${agentId} failed.`;
|
|
805
|
+
await reportProgress(statusText, buildDetails("failed", ownJobId) as unknown as Record<string, unknown>);
|
|
806
|
+
onUpdate?.({
|
|
807
|
+
content: [{ type: "text", text: statusText }],
|
|
808
|
+
details: buildDetails("failed", ownJobId),
|
|
809
|
+
});
|
|
810
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
811
|
+
const hint = AgentRegistry.global().get(agentId) ? buildFollowUpHint(false) : "";
|
|
812
|
+
throw new TaskJobError(`${message}${hint}`);
|
|
813
|
+
} finally {
|
|
814
|
+
semaphore.release();
|
|
815
|
+
}
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
id: agentId,
|
|
819
|
+
queued: true,
|
|
820
|
+
ownerId: this.session.getAgentId?.() ?? undefined,
|
|
821
|
+
onProgress: (text, details) => {
|
|
822
|
+
const progressDetails = (details as TaskToolDetails | undefined) ?? buildDetails("running", agentId);
|
|
823
|
+
onUpdate?.({ content: [{ type: "text", text }], details: progressDetails });
|
|
824
|
+
},
|
|
825
|
+
},
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* Sync fallback fan-out (no job manager, or a `blocking: true` agent): run
|
|
831
|
+
* every spawn to completion inline and merge the per-spawn payloads into a
|
|
832
|
+
* single tool result. The session-scoped semaphore still bounds concurrency
|
|
833
|
+
* across parallel task calls.
|
|
834
|
+
*/
|
|
835
|
+
async #executeSyncFanout(
|
|
836
|
+
toolCallId: string,
|
|
837
|
+
params: TaskParams,
|
|
838
|
+
spawnItems: TaskItem[],
|
|
839
|
+
signal?: AbortSignal,
|
|
840
|
+
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
|
|
841
|
+
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
842
|
+
const semaphore = this.#getSpawnSemaphore();
|
|
843
|
+
if (spawnItems.length === 1) {
|
|
844
|
+
await semaphore.acquire();
|
|
845
|
+
try {
|
|
846
|
+
return await this.#executeSync(
|
|
847
|
+
toolCallId,
|
|
848
|
+
spawnParamsFor(params, spawnItems[0]),
|
|
849
|
+
signal,
|
|
850
|
+
onUpdate,
|
|
851
|
+
undefined,
|
|
852
|
+
0,
|
|
853
|
+
);
|
|
854
|
+
} finally {
|
|
855
|
+
semaphore.release();
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
const startTime = Date.now();
|
|
860
|
+
const latestProgress = new Map<number, AgentProgress>();
|
|
861
|
+
const emitCombined = () => {
|
|
862
|
+
onUpdate?.({
|
|
863
|
+
content: [{ type: "text", text: `Running ${spawnItems.length} agents...` }],
|
|
864
|
+
details: {
|
|
865
|
+
projectAgentsDir: null,
|
|
866
|
+
results: [],
|
|
867
|
+
totalDurationMs: Date.now() - startTime,
|
|
868
|
+
progress: Array.from(latestProgress.entries())
|
|
869
|
+
.sort((a, b) => a[0] - b[0])
|
|
870
|
+
.map(([, progress]) => progress),
|
|
871
|
+
},
|
|
872
|
+
});
|
|
873
|
+
};
|
|
874
|
+
|
|
875
|
+
const { results: payloads } = await mapWithConcurrencyLimit(
|
|
876
|
+
spawnItems,
|
|
877
|
+
spawnItems.length,
|
|
878
|
+
async (item, index, workerSignal) => {
|
|
879
|
+
await semaphore.acquire();
|
|
880
|
+
try {
|
|
881
|
+
const itemOnUpdate: AgentToolUpdateCallback<TaskToolDetails> | undefined = onUpdate
|
|
882
|
+
? update => {
|
|
883
|
+
const progress = update.details?.progress?.[0];
|
|
884
|
+
if (progress) {
|
|
885
|
+
latestProgress.set(index, { ...progress, index });
|
|
886
|
+
emitCombined();
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
: undefined;
|
|
890
|
+
return await this.#executeSync(
|
|
891
|
+
toolCallId,
|
|
892
|
+
spawnParamsFor(params, item),
|
|
893
|
+
workerSignal,
|
|
894
|
+
itemOnUpdate,
|
|
895
|
+
undefined,
|
|
896
|
+
index,
|
|
897
|
+
);
|
|
898
|
+
} finally {
|
|
899
|
+
semaphore.release();
|
|
900
|
+
}
|
|
901
|
+
},
|
|
902
|
+
signal,
|
|
903
|
+
);
|
|
904
|
+
|
|
905
|
+
const results: SingleResult[] = [];
|
|
906
|
+
const contentParts: string[] = [];
|
|
907
|
+
const outputPaths: string[] = [];
|
|
908
|
+
const usageTotals = createUsageTotals();
|
|
909
|
+
let hasUsage = false;
|
|
910
|
+
let projectAgentsDir: string | null = null;
|
|
911
|
+
for (let index = 0; index < spawnItems.length; index++) {
|
|
912
|
+
const payload = payloads[index];
|
|
913
|
+
if (!payload) {
|
|
914
|
+
contentParts.push(`Task ${spawnItems[index].id?.trim() || `#${index + 1}`}: cancelled before start.`);
|
|
915
|
+
continue;
|
|
916
|
+
}
|
|
917
|
+
projectAgentsDir ??= payload.details?.projectAgentsDir ?? null;
|
|
918
|
+
const text = payload.content.find(part => part.type === "text")?.text;
|
|
919
|
+
if (text) contentParts.push(text);
|
|
920
|
+
for (const result of payload.details?.results ?? []) {
|
|
921
|
+
results.push({ ...result, index });
|
|
922
|
+
if (result.usage) {
|
|
923
|
+
addUsageTotals(usageTotals, result.usage);
|
|
924
|
+
hasUsage = true;
|
|
925
|
+
}
|
|
926
|
+
if (result.outputPath) outputPaths.push(result.outputPath);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
return {
|
|
931
|
+
content: [{ type: "text", text: contentParts.join("\n\n") }],
|
|
589
932
|
details: {
|
|
590
|
-
projectAgentsDir
|
|
591
|
-
results
|
|
592
|
-
totalDurationMs:
|
|
593
|
-
|
|
594
|
-
|
|
933
|
+
projectAgentsDir,
|
|
934
|
+
results,
|
|
935
|
+
totalDurationMs: Date.now() - startTime,
|
|
936
|
+
usage: hasUsage ? usageTotals : undefined,
|
|
937
|
+
outputPaths: outputPaths.length > 0 ? outputPaths : undefined,
|
|
595
938
|
},
|
|
596
939
|
};
|
|
597
940
|
}
|
|
598
941
|
|
|
942
|
+
/**
|
|
943
|
+
* Synchronous execution of one spawn. Used as the body of every
|
|
944
|
+
* async job and directly by the sync fallback (no job manager / blocking
|
|
945
|
+
* agent) and by in-process callers that need the result inline (e.g. the
|
|
946
|
+
* commit flow's analyze_files tool).
|
|
947
|
+
*/
|
|
599
948
|
async #executeSync(
|
|
600
|
-
|
|
949
|
+
toolCallId: string,
|
|
601
950
|
params: TaskParams,
|
|
602
951
|
signal?: AbortSignal,
|
|
603
952
|
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
|
|
604
|
-
|
|
953
|
+
preAllocatedId?: string,
|
|
954
|
+
spawnIndex = 0,
|
|
955
|
+
detached = false,
|
|
956
|
+
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
957
|
+
return this.#runSpawn(toolCallId, params, signal, onUpdate, preAllocatedId, spawnIndex, detached);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/** Spawn a fresh subagent and run it to completion. */
|
|
961
|
+
async #runSpawn(
|
|
962
|
+
toolCallId: string,
|
|
963
|
+
params: TaskParams,
|
|
964
|
+
signal?: AbortSignal,
|
|
965
|
+
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
|
|
966
|
+
preAllocatedId?: string,
|
|
967
|
+
spawnIndex = 0,
|
|
968
|
+
detached = false,
|
|
605
969
|
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
606
970
|
const startTime = Date.now();
|
|
607
971
|
const { agents, projectAgentsDir } = await discoverAgents(this.session.cwd);
|
|
608
|
-
const
|
|
609
|
-
const
|
|
610
|
-
const
|
|
611
|
-
const sharedContext = contextEnabled ? context?.trim() : undefined;
|
|
972
|
+
const agentName = params.agent ?? "";
|
|
973
|
+
const sharedContext = this.#isBatchEnabled() ? params.context?.trim() || undefined : undefined;
|
|
974
|
+
const assignment = (params.assignment ?? "").trim();
|
|
612
975
|
const isolationMode = this.session.settings.get("task.isolation.mode");
|
|
613
976
|
const isolationRequested = "isolated" in params ? params.isolated === true : false;
|
|
614
977
|
const isIsolated = isolationMode !== "none" && isolationRequested;
|
|
615
978
|
const mergeMode = this.session.settings.get("task.isolation.merge");
|
|
616
979
|
const commitStyle = this.session.settings.get("task.isolation.commits");
|
|
617
|
-
const maxConcurrency = this.session.settings.get("task.maxConcurrency");
|
|
618
980
|
const taskDepth = this.session.taskDepth ?? 0;
|
|
619
981
|
const subagentLspEnabled = (this.session.enableLsp ?? true) && this.session.settings.get("task.enableLsp");
|
|
620
982
|
|
|
621
983
|
if (isolationMode === "none" && "isolated" in params) {
|
|
622
984
|
return {
|
|
623
|
-
content: [
|
|
624
|
-
|
|
625
|
-
type: "text",
|
|
626
|
-
text: "Task isolation is disabled.",
|
|
627
|
-
},
|
|
628
|
-
],
|
|
629
|
-
details: {
|
|
630
|
-
projectAgentsDir,
|
|
631
|
-
results: [],
|
|
632
|
-
totalDurationMs: 0,
|
|
633
|
-
},
|
|
985
|
+
content: [{ type: "text", text: "Task isolation is disabled." }],
|
|
986
|
+
details: { projectAgentsDir, results: [], totalDurationMs: 0 },
|
|
634
987
|
};
|
|
635
988
|
}
|
|
636
989
|
|
|
@@ -639,17 +992,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
639
992
|
if (!agent) {
|
|
640
993
|
const available = agents.map(a => a.name).join(", ") || "none";
|
|
641
994
|
return {
|
|
642
|
-
content: [
|
|
643
|
-
|
|
644
|
-
type: "text",
|
|
645
|
-
text: `Unknown agent "${agentName}". Available: ${available}`,
|
|
646
|
-
},
|
|
647
|
-
],
|
|
648
|
-
details: {
|
|
649
|
-
projectAgentsDir,
|
|
650
|
-
results: [],
|
|
651
|
-
totalDurationMs: 0,
|
|
652
|
-
},
|
|
995
|
+
content: [{ type: "text", text: `Unknown agent "${agentName}". Available: ${available}` }],
|
|
996
|
+
details: { projectAgentsDir, results: [], totalDurationMs: 0 },
|
|
653
997
|
};
|
|
654
998
|
}
|
|
655
999
|
|
|
@@ -664,16 +1008,18 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
664
1008
|
text: `Agent "${agentName}" is disabled in settings. Enable it via /agents, or use a different agent type.${enabled.length > 0 ? ` Available: ${enabled.join(", ")}` : ""}`,
|
|
665
1009
|
},
|
|
666
1010
|
],
|
|
667
|
-
details: {
|
|
668
|
-
projectAgentsDir,
|
|
669
|
-
results: [],
|
|
670
|
-
totalDurationMs: 0,
|
|
671
|
-
},
|
|
1011
|
+
details: { projectAgentsDir, results: [], totalDurationMs: 0 },
|
|
672
1012
|
};
|
|
673
1013
|
}
|
|
674
1014
|
|
|
675
1015
|
const planModeState = this.session.getPlanModeState?.();
|
|
676
|
-
const
|
|
1016
|
+
const planModeBaseTools = ["read", "search", "find", "lsp", "web_search"];
|
|
1017
|
+
const planModeTools = [
|
|
1018
|
+
...planModeBaseTools,
|
|
1019
|
+
...(agent.tools ?? []).filter(
|
|
1020
|
+
tool => PLAN_MODE_AGENT_TOOL_ALLOWLIST.has(tool) && !planModeBaseTools.includes(tool),
|
|
1021
|
+
),
|
|
1022
|
+
];
|
|
677
1023
|
const effectiveAgent: typeof agent = planModeState?.enabled
|
|
678
1024
|
? {
|
|
679
1025
|
...agent,
|
|
@@ -696,78 +1042,10 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
696
1042
|
});
|
|
697
1043
|
const thinkingLevelOverride = effectiveAgent.thinkingLevel;
|
|
698
1044
|
|
|
699
|
-
// Output schema priority:
|
|
700
|
-
// task
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
: (effectiveAgent.output ?? this.session.outputSchema);
|
|
704
|
-
|
|
705
|
-
// Handle empty or missing tasks
|
|
706
|
-
if (!params.tasks || params.tasks.length === 0) {
|
|
707
|
-
return {
|
|
708
|
-
content: [
|
|
709
|
-
{
|
|
710
|
-
type: "text",
|
|
711
|
-
text: contextEnabled
|
|
712
|
-
? "No tasks provided. Use: { agent, context?, tasks: [{ id, description, assignment }, ...] }"
|
|
713
|
-
: "No tasks provided. Use: { agent, tasks: [{ id, description, assignment }, ...] }",
|
|
714
|
-
},
|
|
715
|
-
],
|
|
716
|
-
details: {
|
|
717
|
-
projectAgentsDir,
|
|
718
|
-
results: [],
|
|
719
|
-
totalDurationMs: 0,
|
|
720
|
-
},
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
const tasks = params.tasks;
|
|
725
|
-
const missingTaskIndexes: number[] = [];
|
|
726
|
-
const idIndexes = new Map<string, number[]>();
|
|
727
|
-
|
|
728
|
-
for (let i = 0; i < tasks.length; i++) {
|
|
729
|
-
const id = tasks[i]?.id;
|
|
730
|
-
if (typeof id !== "string" || id.trim() === "") {
|
|
731
|
-
missingTaskIndexes.push(i);
|
|
732
|
-
continue;
|
|
733
|
-
}
|
|
734
|
-
const normalizedId = id.toLowerCase();
|
|
735
|
-
const indexes = idIndexes.get(normalizedId);
|
|
736
|
-
if (indexes) {
|
|
737
|
-
indexes.push(i);
|
|
738
|
-
} else {
|
|
739
|
-
idIndexes.set(normalizedId, [i]);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
const duplicateIds: Array<{ id: string; indexes: number[] }> = [];
|
|
744
|
-
for (const [normalizedId, indexes] of idIndexes.entries()) {
|
|
745
|
-
if (indexes.length > 1) {
|
|
746
|
-
duplicateIds.push({
|
|
747
|
-
id: tasks[indexes[0]]?.id ?? normalizedId,
|
|
748
|
-
indexes,
|
|
749
|
-
});
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
if (missingTaskIndexes.length > 0 || duplicateIds.length > 0) {
|
|
754
|
-
const problems: string[] = [];
|
|
755
|
-
if (missingTaskIndexes.length > 0) {
|
|
756
|
-
problems.push(`Missing task ids at indexes: ${missingTaskIndexes.join(", ")}`);
|
|
757
|
-
}
|
|
758
|
-
if (duplicateIds.length > 0) {
|
|
759
|
-
const details = duplicateIds.map(entry => `${entry.id} (indexes ${entry.indexes.join(", ")})`).join("; ");
|
|
760
|
-
problems.push(`Duplicate task ids detected (case-insensitive): ${details}`);
|
|
761
|
-
}
|
|
762
|
-
return {
|
|
763
|
-
content: [{ type: "text", text: `Invalid tasks: ${problems.join(". ")}` }],
|
|
764
|
-
details: {
|
|
765
|
-
projectAgentsDir,
|
|
766
|
-
results: [],
|
|
767
|
-
totalDurationMs: 0,
|
|
768
|
-
},
|
|
769
|
-
};
|
|
770
|
-
}
|
|
1045
|
+
// Output schema priority: agent frontmatter > inherited parent session.
|
|
1046
|
+
// The task call itself never carries a schema; workflows needing ad-hoc
|
|
1047
|
+
// structured output go through eval agent(prompt, schema).
|
|
1048
|
+
const effectiveOutputSchema = effectiveAgent.output ?? this.session.outputSchema;
|
|
771
1049
|
|
|
772
1050
|
let repoRoot: string | null = null;
|
|
773
1051
|
let baseline: WorktreeBaseline | null = null;
|
|
@@ -778,17 +1056,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
778
1056
|
} catch (err) {
|
|
779
1057
|
const message = err instanceof Error ? err.message : String(err);
|
|
780
1058
|
return {
|
|
781
|
-
content: [
|
|
782
|
-
|
|
783
|
-
type: "text",
|
|
784
|
-
text: `Isolated task execution requires a git repository. ${message}`,
|
|
785
|
-
},
|
|
786
|
-
],
|
|
787
|
-
details: {
|
|
788
|
-
projectAgentsDir,
|
|
789
|
-
results: [],
|
|
790
|
-
totalDurationMs: Date.now() - startTime,
|
|
791
|
-
},
|
|
1059
|
+
content: [{ type: "text", text: `Isolated task execution requires a git repository. ${message}` }],
|
|
1060
|
+
details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
|
|
792
1061
|
};
|
|
793
1062
|
}
|
|
794
1063
|
}
|
|
@@ -821,23 +1090,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
821
1090
|
localProtocolOptions,
|
|
822
1091
|
);
|
|
823
1092
|
|
|
824
|
-
// Initialize progress tracking
|
|
825
|
-
const progressMap = new Map<number, AgentProgress>();
|
|
826
|
-
|
|
827
|
-
// Update callback
|
|
828
|
-
const emitProgress = () => {
|
|
829
|
-
const progress = Array.from(progressMap.values()).sort((a, b) => a.index - b.index);
|
|
830
|
-
onUpdate?.({
|
|
831
|
-
content: [{ type: "text", text: `Running ${params.tasks.length} agents...` }],
|
|
832
|
-
details: {
|
|
833
|
-
projectAgentsDir,
|
|
834
|
-
results: [],
|
|
835
|
-
totalDurationMs: Date.now() - startTime,
|
|
836
|
-
progress,
|
|
837
|
-
},
|
|
838
|
-
});
|
|
839
|
-
};
|
|
840
|
-
|
|
841
1093
|
try {
|
|
842
1094
|
// Check self-recursion prevention
|
|
843
1095
|
if (this.#blockedAgent && agentName === this.#blockedAgent) {
|
|
@@ -848,11 +1100,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
848
1100
|
text: `Cannot spawn ${this.#blockedAgent} agent from within itself (recursion prevention). Use a different agent type.`,
|
|
849
1101
|
},
|
|
850
1102
|
],
|
|
851
|
-
details: {
|
|
852
|
-
projectAgentsDir,
|
|
853
|
-
results: [],
|
|
854
|
-
totalDurationMs: Date.now() - startTime,
|
|
855
|
-
},
|
|
1103
|
+
details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
|
|
856
1104
|
};
|
|
857
1105
|
}
|
|
858
1106
|
|
|
@@ -869,36 +1117,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
869
1117
|
const allowed = parentSpawns === "" ? "none (spawns disabled for this agent)" : parentSpawns;
|
|
870
1118
|
return {
|
|
871
1119
|
content: [{ type: "text", text: `Cannot spawn '${agentName}'. Allowed: ${allowed}` }],
|
|
872
|
-
details: {
|
|
873
|
-
projectAgentsDir,
|
|
874
|
-
results: [],
|
|
875
|
-
totalDurationMs: Date.now() - startTime,
|
|
876
|
-
},
|
|
1120
|
+
details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
|
|
877
1121
|
};
|
|
878
1122
|
}
|
|
879
1123
|
|
|
880
|
-
// Write parent conversation context for subagents. When IRC is available,
|
|
881
|
-
// subagents should ask live peers instead of reading a stale markdown dump.
|
|
882
1124
|
await fs.mkdir(effectiveArtifactsDir, { recursive: true });
|
|
883
|
-
const shouldWriteConversationContext = this.session.settings.get("irc.enabled") !== true;
|
|
884
|
-
const compactContext = shouldWriteConversationContext ? this.session.getCompactContext?.() : undefined;
|
|
885
|
-
let contextFilePath: string | undefined;
|
|
886
|
-
if (compactContext) {
|
|
887
|
-
contextFilePath = path.join(effectiveArtifactsDir, "context.md");
|
|
888
|
-
await Bun.write(contextFilePath, compactContext);
|
|
889
|
-
}
|
|
890
1125
|
|
|
891
|
-
//
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
uniqueIds = preAllocatedIds;
|
|
1126
|
+
// Allocate a unique ID across the session to prevent artifact collisions
|
|
1127
|
+
let agentId: string;
|
|
1128
|
+
if (preAllocatedId) {
|
|
1129
|
+
agentId = preAllocatedId;
|
|
896
1130
|
} else {
|
|
897
1131
|
const outputManager =
|
|
898
1132
|
this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
|
|
899
|
-
|
|
1133
|
+
agentId = await outputManager.allocate(params.id?.trim() || generateTaskName());
|
|
900
1134
|
}
|
|
901
|
-
const tasksWithUniqueIds = tasks.map((t, i) => ({ ...t, id: uniqueIds[i] }));
|
|
902
1135
|
|
|
903
1136
|
const availableSkills = [...(this.session.skills ?? [])];
|
|
904
1137
|
// Resolve autoload skills from agent definition against available skills
|
|
@@ -915,76 +1148,104 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
915
1148
|
const parentEvalSessionId = this.session.getEvalSessionId?.() ?? undefined;
|
|
916
1149
|
const mcpManager = this.session.mcpManager ?? MCPManager.instance();
|
|
917
1150
|
|
|
918
|
-
//
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1151
|
+
// Progress tracking for the single agent
|
|
1152
|
+
let latestProgress: AgentProgress = {
|
|
1153
|
+
index: spawnIndex,
|
|
1154
|
+
id: agentId,
|
|
1155
|
+
agent: agentName,
|
|
1156
|
+
agentSource: agent.source,
|
|
1157
|
+
status: "pending",
|
|
1158
|
+
task: renderSubagentUserPrompt(assignment),
|
|
1159
|
+
assignment,
|
|
1160
|
+
recentTools: [],
|
|
1161
|
+
recentOutput: [],
|
|
1162
|
+
toolCount: 0,
|
|
1163
|
+
requests: 0,
|
|
1164
|
+
tokens: 0,
|
|
1165
|
+
cost: 0,
|
|
1166
|
+
durationMs: 0,
|
|
1167
|
+
modelOverride,
|
|
1168
|
+
description: params.description,
|
|
1169
|
+
};
|
|
1170
|
+
const emitProgress = () => {
|
|
1171
|
+
onUpdate?.({
|
|
1172
|
+
content: [{ type: "text", text: `Running agent ${agentId}...` }],
|
|
1173
|
+
details: {
|
|
1174
|
+
projectAgentsDir,
|
|
1175
|
+
results: [],
|
|
1176
|
+
totalDurationMs: Date.now() - startTime,
|
|
1177
|
+
progress: [latestProgress],
|
|
1178
|
+
},
|
|
938
1179
|
});
|
|
939
|
-
}
|
|
1180
|
+
};
|
|
940
1181
|
emitProgress();
|
|
941
1182
|
|
|
942
|
-
const
|
|
1183
|
+
const buildCommitMessageFn = () =>
|
|
1184
|
+
commitStyle === "ai" && this.session.modelRegistry
|
|
1185
|
+
? async (diff: string) => {
|
|
1186
|
+
return generateCommitMessage(
|
|
1187
|
+
diff,
|
|
1188
|
+
this.session.modelRegistry!,
|
|
1189
|
+
this.session.settings,
|
|
1190
|
+
this.session.getSessionId?.() ?? undefined,
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
: undefined;
|
|
1194
|
+
|
|
1195
|
+
const sharedRunOptions = {
|
|
1196
|
+
cwd: this.session.cwd,
|
|
1197
|
+
agent: effectiveAgent,
|
|
1198
|
+
task: renderSubagentUserPrompt(assignment),
|
|
1199
|
+
assignment,
|
|
1200
|
+
context: sharedContext,
|
|
1201
|
+
planReference,
|
|
1202
|
+
description: params.description,
|
|
1203
|
+
role: params.role,
|
|
1204
|
+
index: spawnIndex,
|
|
1205
|
+
parentToolCallId: toolCallId,
|
|
1206
|
+
detached,
|
|
1207
|
+
id: agentId,
|
|
1208
|
+
taskDepth,
|
|
1209
|
+
modelOverride,
|
|
1210
|
+
parentActiveModelPattern,
|
|
1211
|
+
thinkingLevel: thinkingLevelOverride,
|
|
1212
|
+
outputSchema: effectiveOutputSchema,
|
|
1213
|
+
sessionFile,
|
|
1214
|
+
persistArtifacts: !!artifactsDir,
|
|
1215
|
+
artifactsDir: effectiveArtifactsDir,
|
|
1216
|
+
enableLsp: subagentLspEnabled,
|
|
1217
|
+
signal,
|
|
1218
|
+
eventBus: this.session.eventBus,
|
|
1219
|
+
onProgress: (progress: AgentProgress) => {
|
|
1220
|
+
// Shallow snapshot; recentTools is mutated in place by the
|
|
1221
|
+
// executor, the rest is reassigned or immutable. A deep clone
|
|
1222
|
+
// here cost O(extractedToolData) per progress event.
|
|
1223
|
+
latestProgress = { ...progress, recentTools: progress.recentTools.slice() };
|
|
1224
|
+
emitProgress();
|
|
1225
|
+
},
|
|
1226
|
+
authStorage: this.session.authStorage,
|
|
1227
|
+
modelRegistry: this.session.modelRegistry,
|
|
1228
|
+
settings: this.session.settings,
|
|
1229
|
+
mcpManager,
|
|
1230
|
+
contextFiles,
|
|
1231
|
+
skills: availableSkills,
|
|
1232
|
+
autoloadSkills: resolvedAutoloadSkills,
|
|
1233
|
+
workspaceTree: this.session.workspaceTree,
|
|
1234
|
+
promptTemplates,
|
|
1235
|
+
rules: this.session.rules,
|
|
1236
|
+
preloadedExtensionPaths: this.session.extensionPaths,
|
|
1237
|
+
preloadedCustomToolPaths: this.session.customToolPaths,
|
|
1238
|
+
localProtocolOptions,
|
|
1239
|
+
parentArtifactManager,
|
|
1240
|
+
parentHindsightSessionState: this.session.getHindsightSessionState?.(),
|
|
1241
|
+
parentMnemopiSessionState: this.session.getMnemopiSessionState?.(),
|
|
1242
|
+
parentTelemetry: this.session.getTelemetry?.(),
|
|
1243
|
+
parentEvalSessionId,
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
const runTask = async (): Promise<SingleResult> => {
|
|
943
1247
|
if (!isIsolated) {
|
|
944
|
-
return runSubprocess(
|
|
945
|
-
cwd: this.session.cwd,
|
|
946
|
-
agent: effectiveAgent,
|
|
947
|
-
task: renderSubagentUserPrompt(task.assignment, simpleMode),
|
|
948
|
-
assignment: task.assignment.trim(),
|
|
949
|
-
context: sharedContext,
|
|
950
|
-
planReference,
|
|
951
|
-
description: task.description,
|
|
952
|
-
index,
|
|
953
|
-
id: task.id,
|
|
954
|
-
taskDepth,
|
|
955
|
-
modelOverride,
|
|
956
|
-
parentActiveModelPattern,
|
|
957
|
-
thinkingLevel: thinkingLevelOverride,
|
|
958
|
-
outputSchema: effectiveOutputSchema,
|
|
959
|
-
sessionFile,
|
|
960
|
-
persistArtifacts: !!artifactsDir,
|
|
961
|
-
artifactsDir: effectiveArtifactsDir,
|
|
962
|
-
contextFile: contextFilePath,
|
|
963
|
-
enableLsp: subagentLspEnabled,
|
|
964
|
-
signal,
|
|
965
|
-
eventBus: this.session.eventBus,
|
|
966
|
-
onProgress: progress => {
|
|
967
|
-
progressMap.set(index, {
|
|
968
|
-
...structuredClone(progress),
|
|
969
|
-
});
|
|
970
|
-
emitProgress();
|
|
971
|
-
},
|
|
972
|
-
authStorage: this.session.authStorage,
|
|
973
|
-
modelRegistry: this.session.modelRegistry,
|
|
974
|
-
settings: this.session.settings,
|
|
975
|
-
mcpManager,
|
|
976
|
-
contextFiles,
|
|
977
|
-
skills: availableSkills,
|
|
978
|
-
autoloadSkills: resolvedAutoloadSkills,
|
|
979
|
-
workspaceTree: this.session.workspaceTree,
|
|
980
|
-
promptTemplates,
|
|
981
|
-
localProtocolOptions,
|
|
982
|
-
parentArtifactManager,
|
|
983
|
-
parentHindsightSessionState: this.session.getHindsightSessionState?.(),
|
|
984
|
-
parentMnemopiSessionState: this.session.getMnemopiSessionState?.(),
|
|
985
|
-
parentTelemetry: this.session.getTelemetry?.(),
|
|
986
|
-
parentEvalSessionId,
|
|
987
|
-
});
|
|
1248
|
+
return runSubprocess(sharedRunOptions);
|
|
988
1249
|
}
|
|
989
1250
|
|
|
990
1251
|
const taskStart = Date.now();
|
|
@@ -995,73 +1256,25 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
995
1256
|
}
|
|
996
1257
|
const taskBaseline = structuredClone(baseline);
|
|
997
1258
|
|
|
998
|
-
isolationHandle = await ensureIsolation(repoRoot,
|
|
1259
|
+
isolationHandle = await ensureIsolation(repoRoot, agentId, preferredIsolationBackend);
|
|
999
1260
|
const isolationDir = isolationHandle.mergedDir;
|
|
1000
1261
|
|
|
1262
|
+
// Isolated runs re-discover extensions/custom tools inside the
|
|
1263
|
+
// worktree instead of reusing the parent's source paths.
|
|
1001
1264
|
const result = await runSubprocess({
|
|
1002
|
-
|
|
1265
|
+
...sharedRunOptions,
|
|
1003
1266
|
worktree: isolationDir,
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
assignment: task.assignment.trim(),
|
|
1007
|
-
context: sharedContext,
|
|
1008
|
-
planReference,
|
|
1009
|
-
description: task.description,
|
|
1010
|
-
index,
|
|
1011
|
-
id: task.id,
|
|
1012
|
-
taskDepth,
|
|
1013
|
-
modelOverride,
|
|
1014
|
-
parentActiveModelPattern,
|
|
1015
|
-
thinkingLevel: thinkingLevelOverride,
|
|
1016
|
-
outputSchema: effectiveOutputSchema,
|
|
1017
|
-
sessionFile,
|
|
1018
|
-
persistArtifacts: !!artifactsDir,
|
|
1019
|
-
artifactsDir: effectiveArtifactsDir,
|
|
1020
|
-
contextFile: contextFilePath,
|
|
1021
|
-
enableLsp: subagentLspEnabled,
|
|
1022
|
-
signal,
|
|
1023
|
-
eventBus: this.session.eventBus,
|
|
1024
|
-
onProgress: progress => {
|
|
1025
|
-
progressMap.set(index, {
|
|
1026
|
-
...structuredClone(progress),
|
|
1027
|
-
});
|
|
1028
|
-
emitProgress();
|
|
1029
|
-
},
|
|
1030
|
-
authStorage: this.session.authStorage,
|
|
1031
|
-
modelRegistry: this.session.modelRegistry,
|
|
1032
|
-
settings: this.session.settings,
|
|
1033
|
-
mcpManager,
|
|
1034
|
-
contextFiles,
|
|
1035
|
-
skills: availableSkills,
|
|
1036
|
-
autoloadSkills: resolvedAutoloadSkills,
|
|
1037
|
-
workspaceTree: this.session.workspaceTree,
|
|
1038
|
-
promptTemplates,
|
|
1039
|
-
localProtocolOptions,
|
|
1040
|
-
parentArtifactManager,
|
|
1041
|
-
parentHindsightSessionState: this.session.getHindsightSessionState?.(),
|
|
1042
|
-
parentMnemopiSessionState: this.session.getMnemopiSessionState?.(),
|
|
1043
|
-
parentTelemetry: this.session.getTelemetry?.(),
|
|
1044
|
-
parentEvalSessionId,
|
|
1267
|
+
preloadedExtensionPaths: undefined,
|
|
1268
|
+
preloadedCustomToolPaths: undefined,
|
|
1045
1269
|
});
|
|
1046
1270
|
if (mergeMode === "branch" && result.exitCode === 0) {
|
|
1047
1271
|
try {
|
|
1048
|
-
const commitMsg =
|
|
1049
|
-
commitStyle === "ai" && this.session.modelRegistry
|
|
1050
|
-
? async (diff: string) => {
|
|
1051
|
-
return generateCommitMessage(
|
|
1052
|
-
diff,
|
|
1053
|
-
this.session.modelRegistry!,
|
|
1054
|
-
this.session.settings,
|
|
1055
|
-
this.session.getSessionId?.() ?? undefined,
|
|
1056
|
-
);
|
|
1057
|
-
}
|
|
1058
|
-
: undefined;
|
|
1059
1272
|
const commitResult = await commitToBranch(
|
|
1060
1273
|
isolationDir,
|
|
1061
1274
|
taskBaseline,
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1275
|
+
agentId,
|
|
1276
|
+
params.description,
|
|
1277
|
+
buildCommitMessageFn(),
|
|
1065
1278
|
);
|
|
1066
1279
|
return {
|
|
1067
1280
|
...result,
|
|
@@ -1070,7 +1283,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1070
1283
|
};
|
|
1071
1284
|
} catch (mergeErr) {
|
|
1072
1285
|
// Agent succeeded but branch commit failed — clean up stale branch
|
|
1073
|
-
const branchName = `prometheus/task/${
|
|
1286
|
+
const branchName = `prometheus/task/${agentId}`;
|
|
1074
1287
|
await git.branch.tryDelete(repoRoot, branchName);
|
|
1075
1288
|
const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
1076
1289
|
return { ...result, error: `Merge failed: ${msg}` };
|
|
@@ -1079,7 +1292,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1079
1292
|
if (result.exitCode === 0) {
|
|
1080
1293
|
try {
|
|
1081
1294
|
const delta = await captureDeltaPatch(isolationDir, taskBaseline);
|
|
1082
|
-
const patchPath = path.join(effectiveArtifactsDir, `${
|
|
1295
|
+
const patchPath = path.join(effectiveArtifactsDir, `${agentId}.patch`);
|
|
1083
1296
|
await Bun.write(patchPath, delta.rootPatch);
|
|
1084
1297
|
return {
|
|
1085
1298
|
...result,
|
|
@@ -1094,21 +1307,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1094
1307
|
return result;
|
|
1095
1308
|
} catch (err) {
|
|
1096
1309
|
const message = err instanceof Error ? err.message : String(err);
|
|
1097
|
-
const assignment = task.assignment.trim();
|
|
1098
1310
|
return {
|
|
1099
|
-
index,
|
|
1100
|
-
id:
|
|
1311
|
+
index: spawnIndex,
|
|
1312
|
+
id: agentId,
|
|
1101
1313
|
agent: agent.name,
|
|
1102
1314
|
agentSource: agent.source,
|
|
1103
|
-
task: renderSubagentUserPrompt(assignment
|
|
1315
|
+
task: renderSubagentUserPrompt(assignment),
|
|
1104
1316
|
assignment,
|
|
1105
|
-
description:
|
|
1317
|
+
description: params.description,
|
|
1106
1318
|
exitCode: 1,
|
|
1107
1319
|
output: "",
|
|
1108
1320
|
stderr: message,
|
|
1109
1321
|
truncated: false,
|
|
1110
1322
|
durationMs: Date.now() - taskStart,
|
|
1111
1323
|
tokens: 0,
|
|
1324
|
+
requests: 0,
|
|
1112
1325
|
modelOverride,
|
|
1113
1326
|
error: message,
|
|
1114
1327
|
};
|
|
@@ -1119,142 +1332,68 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1119
1332
|
}
|
|
1120
1333
|
};
|
|
1121
1334
|
|
|
1122
|
-
|
|
1123
|
-
const { results: partialResults, aborted } = await mapWithConcurrencyLimit(
|
|
1124
|
-
tasksWithUniqueIds,
|
|
1125
|
-
maxConcurrency,
|
|
1126
|
-
runTask,
|
|
1127
|
-
signal,
|
|
1128
|
-
);
|
|
1129
|
-
|
|
1130
|
-
// Fill in skipped tasks (undefined entries from abort) with placeholder results
|
|
1131
|
-
const results: SingleResult[] = partialResults.map((result, index) => {
|
|
1132
|
-
if (result !== undefined) {
|
|
1133
|
-
return result;
|
|
1134
|
-
}
|
|
1135
|
-
const task = tasksWithUniqueIds[index];
|
|
1136
|
-
const assignment = task.assignment.trim();
|
|
1137
|
-
return {
|
|
1138
|
-
index,
|
|
1139
|
-
id: task.id,
|
|
1140
|
-
agent: agentName,
|
|
1141
|
-
agentSource: agent.source,
|
|
1142
|
-
task: renderSubagentUserPrompt(assignment, simpleMode),
|
|
1143
|
-
assignment,
|
|
1144
|
-
description: task.description,
|
|
1145
|
-
exitCode: 1,
|
|
1146
|
-
output: "",
|
|
1147
|
-
stderr: "Skipped (cancelled before start)",
|
|
1148
|
-
truncated: false,
|
|
1149
|
-
durationMs: 0,
|
|
1150
|
-
tokens: 0,
|
|
1151
|
-
modelOverride,
|
|
1152
|
-
error: "Cancelled before start",
|
|
1153
|
-
aborted: true,
|
|
1154
|
-
abortReason: "Cancelled before start",
|
|
1155
|
-
};
|
|
1156
|
-
});
|
|
1157
|
-
|
|
1158
|
-
// Aggregate usage from executor results (already accumulated incrementally)
|
|
1159
|
-
const aggregatedUsage = createUsageTotals();
|
|
1160
|
-
let hasAggregatedUsage = false;
|
|
1161
|
-
for (const result of results) {
|
|
1162
|
-
if (result.usage) {
|
|
1163
|
-
addUsageTotals(aggregatedUsage, result.usage);
|
|
1164
|
-
hasAggregatedUsage = true;
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Collect output paths (artifacts already written by executor in real-time)
|
|
1169
|
-
const outputPaths: string[] = [];
|
|
1170
|
-
const patchPaths: string[] = [];
|
|
1171
|
-
for (const result of results) {
|
|
1172
|
-
if (result.outputPath) {
|
|
1173
|
-
outputPaths.push(result.outputPath);
|
|
1174
|
-
}
|
|
1175
|
-
if (result.patchPath) {
|
|
1176
|
-
patchPaths.push(result.patchPath);
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1335
|
+
const result = await runTask();
|
|
1179
1336
|
|
|
1180
1337
|
let mergeSummary = "";
|
|
1181
1338
|
let changesApplied: boolean | null = null;
|
|
1182
1339
|
let hadAnyChanges = false;
|
|
1183
|
-
let
|
|
1340
|
+
let mergedBranchForNestedPatches = false;
|
|
1184
1341
|
if (isIsolated && repoRoot) {
|
|
1185
1342
|
try {
|
|
1186
1343
|
if (mergeMode === "branch") {
|
|
1187
|
-
|
|
1188
|
-
const branchEntries = results
|
|
1189
|
-
.filter(r => r.branchName && r.exitCode === 0 && !r.aborted)
|
|
1190
|
-
.map(r => ({ branchName: r.branchName!, taskId: r.id, description: r.description }));
|
|
1191
|
-
|
|
1192
|
-
if (branchEntries.length === 0) {
|
|
1344
|
+
if (!result.branchName || result.exitCode !== 0 || result.aborted) {
|
|
1193
1345
|
changesApplied = true;
|
|
1194
|
-
hadAnyChanges = false;
|
|
1195
1346
|
mergeSummary = "\n\nNo changes to apply.";
|
|
1196
1347
|
} else {
|
|
1197
|
-
const mergeResult = await mergeTaskBranches(repoRoot,
|
|
1198
|
-
|
|
1348
|
+
const mergeResult = await mergeTaskBranches(repoRoot, [
|
|
1349
|
+
{ branchName: result.branchName, taskId: result.id, description: result.description },
|
|
1350
|
+
]);
|
|
1351
|
+
mergedBranchForNestedPatches = mergeResult.merged.includes(result.branchName);
|
|
1199
1352
|
changesApplied = mergeResult.failed.length === 0;
|
|
1200
1353
|
hadAnyChanges = changesApplied && mergeResult.merged.length > 0;
|
|
1201
1354
|
|
|
1202
1355
|
if (changesApplied) {
|
|
1203
1356
|
mergeSummary = hadAnyChanges
|
|
1204
|
-
? `\n\nMerged
|
|
1357
|
+
? `\n\nMerged branch: ${result.branchName}`
|
|
1205
1358
|
: "\n\nNo changes to apply.";
|
|
1206
1359
|
} else {
|
|
1207
|
-
const mergedPart =
|
|
1208
|
-
mergeResult.merged.length > 0 ? `Merged: ${mergeResult.merged.join(", ")}.\n` : "";
|
|
1209
|
-
const failedPart = `Failed: ${mergeResult.failed.join(", ")}.`;
|
|
1210
1360
|
const conflictPart = mergeResult.conflict ? `\nConflict: ${mergeResult.conflict}` : "";
|
|
1211
|
-
mergeSummary = `\n\n<system-notification>Branch merge failed
|
|
1361
|
+
mergeSummary = `\n\n<system-notification>Branch merge failed: ${result.branchName}.${conflictPart}\nThe unmerged branch remains for manual resolution.</system-notification>`;
|
|
1362
|
+
}
|
|
1363
|
+
if (mergeResult.stashConflict) {
|
|
1364
|
+
mergeSummary += `\n\n<system-notification>${mergeResult.stashConflict}</system-notification>`;
|
|
1212
1365
|
}
|
|
1213
|
-
}
|
|
1214
1366
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1367
|
+
// Clean up the merged branch (keep failed ones for manual resolution)
|
|
1368
|
+
if (changesApplied) {
|
|
1369
|
+
await cleanupTaskBranches(repoRoot, [result.branchName]);
|
|
1370
|
+
}
|
|
1219
1371
|
}
|
|
1220
1372
|
} else {
|
|
1221
|
-
// Patch mode:
|
|
1222
|
-
|
|
1223
|
-
const
|
|
1224
|
-
if (
|
|
1373
|
+
// Patch mode: apply the patch from a successful run. A failed or
|
|
1374
|
+
// aborted run has nothing to apply and must not block the result.
|
|
1375
|
+
const succeeded = result.exitCode === 0 && !result.error && !result.aborted;
|
|
1376
|
+
if (!succeeded) {
|
|
1377
|
+
changesApplied = true;
|
|
1378
|
+
hadAnyChanges = false;
|
|
1379
|
+
} else if (!result.patchPath) {
|
|
1225
1380
|
changesApplied = false;
|
|
1226
1381
|
hadAnyChanges = false;
|
|
1227
1382
|
} else {
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
patchPath,
|
|
1231
|
-
size: (await fs.stat(patchPath)).size,
|
|
1232
|
-
})),
|
|
1233
|
-
);
|
|
1234
|
-
const nonEmptyPatches = patchStats.filter(patch => patch.size > 0).map(patch => patch.patchPath);
|
|
1235
|
-
if (nonEmptyPatches.length === 0) {
|
|
1383
|
+
const patchText = await Bun.file(result.patchPath).text();
|
|
1384
|
+
if (!patchText.trim()) {
|
|
1236
1385
|
changesApplied = true;
|
|
1237
1386
|
hadAnyChanges = false;
|
|
1238
1387
|
} else {
|
|
1239
|
-
const
|
|
1240
|
-
|
|
1241
|
-
)
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
} else {
|
|
1249
|
-
changesApplied = await git.patch.canApplyText(repoRoot, combinedPatch);
|
|
1250
|
-
if (changesApplied) {
|
|
1251
|
-
try {
|
|
1252
|
-
await git.patch.applyText(repoRoot, combinedPatch);
|
|
1253
|
-
hadAnyChanges = true;
|
|
1254
|
-
} catch {
|
|
1255
|
-
changesApplied = false;
|
|
1256
|
-
hadAnyChanges = false;
|
|
1257
|
-
}
|
|
1388
|
+
const normalized = patchText.endsWith("\n") ? patchText : `${patchText}\n`;
|
|
1389
|
+
changesApplied = await git.patch.canApplyText(repoRoot, normalized);
|
|
1390
|
+
if (changesApplied) {
|
|
1391
|
+
try {
|
|
1392
|
+
await git.patch.applyText(repoRoot, normalized);
|
|
1393
|
+
hadAnyChanges = true;
|
|
1394
|
+
} catch {
|
|
1395
|
+
changesApplied = false;
|
|
1396
|
+
hadAnyChanges = false;
|
|
1258
1397
|
}
|
|
1259
1398
|
}
|
|
1260
1399
|
}
|
|
@@ -1265,10 +1404,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1265
1404
|
} else {
|
|
1266
1405
|
const notification =
|
|
1267
1406
|
"<system-notification>Patches were not applied and must be handled manually.</system-notification>";
|
|
1268
|
-
const patchList =
|
|
1269
|
-
patchPaths.length > 0
|
|
1270
|
-
? `\n\nPatch artifacts:\n${patchPaths.map(patch => `- ${patch}`).join("\n")}`
|
|
1271
|
-
: "";
|
|
1407
|
+
const patchList = result.patchPath ? `\n\nPatch artifact:\n- ${result.patchPath}` : "";
|
|
1272
1408
|
mergeSummary = `\n\n${notification}${patchList}`;
|
|
1273
1409
|
}
|
|
1274
1410
|
}
|
|
@@ -1282,34 +1418,15 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1282
1418
|
|
|
1283
1419
|
// Apply nested repo patches (separate from parent git)
|
|
1284
1420
|
if (isIsolated && repoRoot && (mergeMode === "branch" || changesApplied !== false)) {
|
|
1285
|
-
const
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
if (!r.branchName || !mergedBranchesForNestedPatches) {
|
|
1294
|
-
return false;
|
|
1295
|
-
}
|
|
1296
|
-
return mergedBranchesForNestedPatches.has(r.branchName);
|
|
1297
|
-
})
|
|
1298
|
-
.flatMap(r => r.nestedPatches!);
|
|
1299
|
-
if (allNestedPatches.length > 0) {
|
|
1421
|
+
const nestedPatches = result.nestedPatches ?? [];
|
|
1422
|
+
const eligible =
|
|
1423
|
+
nestedPatches.length > 0 &&
|
|
1424
|
+
result.exitCode === 0 &&
|
|
1425
|
+
!result.aborted &&
|
|
1426
|
+
(mergeMode !== "branch" || mergedBranchForNestedPatches);
|
|
1427
|
+
if (eligible) {
|
|
1300
1428
|
try {
|
|
1301
|
-
|
|
1302
|
-
commitStyle === "ai" && this.session.modelRegistry
|
|
1303
|
-
? async (diff: string) => {
|
|
1304
|
-
return generateCommitMessage(
|
|
1305
|
-
diff,
|
|
1306
|
-
this.session.modelRegistry!,
|
|
1307
|
-
this.session.settings,
|
|
1308
|
-
this.session.getSessionId?.() ?? undefined,
|
|
1309
|
-
);
|
|
1310
|
-
}
|
|
1311
|
-
: undefined;
|
|
1312
|
-
await applyNestedPatches(repoRoot, allNestedPatches, commitMsg);
|
|
1429
|
+
await applyNestedPatches(repoRoot, nestedPatches, buildCommitMessageFn());
|
|
1313
1430
|
} catch {
|
|
1314
1431
|
// Nested patch failures are non-fatal to the parent merge
|
|
1315
1432
|
mergeSummary +=
|
|
@@ -1318,58 +1435,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1318
1435
|
}
|
|
1319
1436
|
}
|
|
1320
1437
|
|
|
1321
|
-
// Build final output - match plugin format
|
|
1322
|
-
const cancelledCount = results.filter(r => r.aborted).length;
|
|
1323
|
-
const successCount = results.filter(r => r.exitCode === 0 && !r.error && !r.aborted).length;
|
|
1324
|
-
const totalDuration = Date.now() - startTime;
|
|
1325
|
-
|
|
1326
|
-
const summaries = results.map(r => {
|
|
1327
|
-
const status = r.aborted
|
|
1328
|
-
? "cancelled"
|
|
1329
|
-
: r.exitCode === 0 && r.error
|
|
1330
|
-
? "merge failed"
|
|
1331
|
-
: r.exitCode === 0
|
|
1332
|
-
? "completed"
|
|
1333
|
-
: `failed (exit ${r.exitCode})`;
|
|
1334
|
-
const output = r.output.trim() || r.stderr.trim() || "(no output)";
|
|
1335
|
-
const outputCharCount = r.outputMeta?.charCount ?? output.length;
|
|
1336
|
-
const fullOutputThreshold = 5000;
|
|
1337
|
-
let preview = output;
|
|
1338
|
-
let truncated = false;
|
|
1339
|
-
if (outputCharCount > fullOutputThreshold) {
|
|
1340
|
-
const slice = output.slice(0, fullOutputThreshold);
|
|
1341
|
-
const lastNewline = slice.lastIndexOf("\n");
|
|
1342
|
-
preview = lastNewline >= 0 ? slice.slice(0, lastNewline) : slice;
|
|
1343
|
-
truncated = true;
|
|
1344
|
-
}
|
|
1345
|
-
return {
|
|
1346
|
-
agent: r.agent,
|
|
1347
|
-
status,
|
|
1348
|
-
id: r.id,
|
|
1349
|
-
preview,
|
|
1350
|
-
truncated,
|
|
1351
|
-
meta: r.outputMeta
|
|
1352
|
-
? {
|
|
1353
|
-
lineCount: r.outputMeta.lineCount,
|
|
1354
|
-
charSize: formatBytes(r.outputMeta.charCount),
|
|
1355
|
-
}
|
|
1356
|
-
: undefined,
|
|
1357
|
-
};
|
|
1358
|
-
});
|
|
1359
|
-
|
|
1360
|
-
const outputIds = results.filter(r => !r.aborted || r.output.trim()).map(r => `agent://${r.id}`);
|
|
1361
|
-
const summary = prompt.render(taskSummaryTemplate, {
|
|
1362
|
-
successCount,
|
|
1363
|
-
totalCount: results.length,
|
|
1364
|
-
cancelledCount,
|
|
1365
|
-
hasCancelledNote: aborted && cancelledCount > 0,
|
|
1366
|
-
duration: formatDuration(totalDuration),
|
|
1367
|
-
summaries,
|
|
1368
|
-
outputIds,
|
|
1369
|
-
agentName,
|
|
1370
|
-
mergeSummary,
|
|
1371
|
-
});
|
|
1372
|
-
|
|
1373
1438
|
// Cleanup temp directory if used
|
|
1374
1439
|
const shouldCleanupTempArtifacts =
|
|
1375
1440
|
tempArtifactsDir && (!isIsolated || changesApplied === true || changesApplied === null);
|
|
@@ -1377,25 +1442,65 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1377
1442
|
await fs.rm(tempArtifactsDir, { recursive: true, force: true });
|
|
1378
1443
|
}
|
|
1379
1444
|
|
|
1380
|
-
return
|
|
1381
|
-
content: [{ type: "text", text: summary }],
|
|
1382
|
-
details: {
|
|
1383
|
-
projectAgentsDir,
|
|
1384
|
-
results: results,
|
|
1385
|
-
totalDurationMs: totalDuration,
|
|
1386
|
-
usage: hasAggregatedUsage ? aggregatedUsage : undefined,
|
|
1387
|
-
outputPaths,
|
|
1388
|
-
},
|
|
1389
|
-
};
|
|
1445
|
+
return this.#buildResultPayload(result, projectAgentsDir, Date.now() - startTime, mergeSummary);
|
|
1390
1446
|
} catch (err) {
|
|
1391
1447
|
return {
|
|
1392
1448
|
content: [{ type: "text", text: `Task execution failed: ${err}` }],
|
|
1393
|
-
details: {
|
|
1394
|
-
projectAgentsDir,
|
|
1395
|
-
results: [],
|
|
1396
|
-
totalDurationMs: Date.now() - startTime,
|
|
1397
|
-
},
|
|
1449
|
+
details: { projectAgentsDir, results: [], totalDurationMs: Date.now() - startTime },
|
|
1398
1450
|
};
|
|
1399
1451
|
}
|
|
1400
1452
|
}
|
|
1453
|
+
|
|
1454
|
+
/** Build the tool result (summary text + details) for a settled run. */
|
|
1455
|
+
#buildResultPayload(
|
|
1456
|
+
result: SingleResult,
|
|
1457
|
+
projectAgentsDir: string | null,
|
|
1458
|
+
totalDurationMs: number,
|
|
1459
|
+
mergeSummary: string,
|
|
1460
|
+
): AgentToolResult<TaskToolDetails> {
|
|
1461
|
+
const status = result.aborted
|
|
1462
|
+
? "cancelled"
|
|
1463
|
+
: result.exitCode === 0 && result.error
|
|
1464
|
+
? "merge failed"
|
|
1465
|
+
: result.exitCode === 0
|
|
1466
|
+
? "completed"
|
|
1467
|
+
: `failed (exit ${result.exitCode})`;
|
|
1468
|
+
const output = formatResultOutputFallback(result);
|
|
1469
|
+
const outputCharCount = result.outputMeta?.charCount ?? output.length;
|
|
1470
|
+
const fullOutputThreshold = 5000;
|
|
1471
|
+
let preview = output;
|
|
1472
|
+
let truncated = false;
|
|
1473
|
+
if (outputCharCount > fullOutputThreshold) {
|
|
1474
|
+
const slice = output.slice(0, fullOutputThreshold);
|
|
1475
|
+
const lastNewline = slice.lastIndexOf("\n");
|
|
1476
|
+
preview = lastNewline >= 0 ? slice.slice(0, lastNewline) : slice;
|
|
1477
|
+
truncated = true;
|
|
1478
|
+
}
|
|
1479
|
+
const summary = prompt.render(taskSummaryTemplate, {
|
|
1480
|
+
agentName: result.agent,
|
|
1481
|
+
id: result.id,
|
|
1482
|
+
status,
|
|
1483
|
+
duration: formatDuration(totalDurationMs),
|
|
1484
|
+
preview,
|
|
1485
|
+
truncated,
|
|
1486
|
+
meta: result.outputMeta
|
|
1487
|
+
? {
|
|
1488
|
+
lineCount: result.outputMeta.lineCount,
|
|
1489
|
+
charSize: formatBytes(result.outputMeta.charCount),
|
|
1490
|
+
}
|
|
1491
|
+
: undefined,
|
|
1492
|
+
mergeSummary,
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
return {
|
|
1496
|
+
content: [{ type: "text", text: summary }],
|
|
1497
|
+
details: {
|
|
1498
|
+
projectAgentsDir,
|
|
1499
|
+
results: [result],
|
|
1500
|
+
totalDurationMs,
|
|
1501
|
+
usage: result.usage,
|
|
1502
|
+
outputPaths: result.outputPath ? [result.outputPath] : undefined,
|
|
1503
|
+
},
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1401
1506
|
}
|