@selesai/code 0.5.28 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +23 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +117 -0
- package/dist/cli/credential-print.js.map +1 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +20 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -3
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +11 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +10 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/llama/provider.d.ts.map +1 -1
- package/dist/core/llama/provider.js +8 -3
- package/dist/core/llama/provider.js.map +1 -1
- package/dist/core/model-config.d.ts +30 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +6 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +20 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +13 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +24 -11
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts +15 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +66 -9
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +19 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/system-prompt.test.d.ts +2 -0
- package/dist/core/system-prompt.test.d.ts.map +1 -0
- package/dist/core/system-prompt.test.js +89 -0
- package/dist/core/system-prompt.test.js.map +1 -0
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/defaults/models.json +13 -45
- package/dist/defaults/settings.json +1 -2
- package/dist/extensions/copy-turn.test.ts +131 -0
- package/dist/extensions/copy-turn.ts +6 -1
- package/dist/extensions/package.json +0 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
- package/dist/extensions/pi-intercom/README.md +102 -39
- package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
- package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
- package/dist/extensions/pi-intercom/broker/client.ts +315 -12
- package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
- package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
- package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
- package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
- package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
- package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
- package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
- package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
- package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
- package/dist/extensions/pi-intercom/config.test.ts +93 -0
- package/dist/extensions/pi-intercom/config.ts +55 -6
- package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
- package/dist/extensions/pi-intercom/cwd.ts +31 -0
- package/dist/extensions/pi-intercom/extension-api.ts +44 -0
- package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
- package/dist/extensions/pi-intercom/format-context.ts +32 -0
- package/dist/extensions/pi-intercom/index.ts +742 -145
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
- package/dist/extensions/pi-intercom/package.json +15 -5
- package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
- package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
- package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
- package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
- package/dist/extensions/pi-intercom/types.ts +94 -4
- package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
- package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
- package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
- package/dist/extensions/pi-subagents/CHANGELOG.md +88 -0
- package/dist/extensions/pi-subagents/LICENSE +21 -0
- package/dist/extensions/pi-subagents/README.md +158 -69
- package/dist/extensions/pi-subagents/agents/architect.md +5 -4
- package/dist/extensions/pi-subagents/agents/builder.md +6 -4
- package/dist/extensions/pi-subagents/agents/commentator.md +3 -2
- package/dist/extensions/pi-subagents/agents/explorer.md +3 -2
- package/dist/extensions/pi-subagents/agents/recapper.md +3 -2
- package/dist/extensions/pi-subagents/agents/researcher.md +4 -3
- package/dist/extensions/pi-subagents/package-lock.json +2 -2
- package/dist/extensions/pi-subagents/package.json +3 -3
- package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +22 -988
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +257 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +431 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +281 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +125 -37
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
- package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
- package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +125 -0
- package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +17 -13
- package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
- package/dist/extensions/pi-subagents/src/extension/index.ts +22 -8
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +33 -8
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +32 -14
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +86 -21
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +56 -5
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +92 -11
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +388 -29
- package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +214 -60
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +546 -252
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +553 -154
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +19 -13
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
- package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +63 -9
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +22 -1
- package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
- package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +196 -12
- package/dist/extensions/pi-subagents/src/shared/utils.ts +102 -5
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +10 -1
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
- package/dist/extensions/pi-subagents/src/tui/render.ts +55 -34
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
- package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +113 -8
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +419 -47
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +62 -22
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +8 -6
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +231 -19
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +48 -7
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +199 -17
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +898 -16
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +18 -2
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +198 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +161 -1
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +136 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
- package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +28 -2
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +17 -12
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +39 -2
- package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +46 -2
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +91 -1
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +26 -1
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +61 -10
- package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +43 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +10 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -46
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +4 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +72 -64
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/skills/ponytail/SKILL.md +1 -3
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +14 -5
- package/docs/environment-variables.md +86 -0
- package/docs/extensions.md +15 -5
- package/docs/index.md +1 -0
- package/docs/models.md +9 -2
- package/docs/plans/subagent-delegation/phase-0-correctness.md +265 -0
- package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +486 -0
- package/docs/plans/subagent-delegation/phase-2-context-controls.md +282 -0
- package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +362 -0
- package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +381 -0
- package/docs/providers.md +21 -2
- package/docs/rpc.md +23 -6
- package/docs/session-format.md +2 -0
- package/docs/settings.md +1 -1
- package/docs/usage.md +0 -13
- package/examples/extensions/custom-compaction.ts +5 -2
- package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +11 -3
- package/examples/extensions/message-renderer.ts +3 -3
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +5 -2
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/12-full-control.ts +3 -1
- package/package.json +16 -7
- package/dist/extensions/caveman/caveman-instructions.cjs +0 -11
- package/dist/extensions/caveman/index.js +0 -118
- package/dist/extensions/caveman/package.json +0 -8
- package/dist/extensions/caveman/test/extension.test.js +0 -203
- package/dist/extensions/caveman/test/helpers.test.js +0 -58
- package/dist/skills/caveman/SKILL.md +0 -50
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
type AsyncStatus,
|
|
19
19
|
type ChainOutputMap,
|
|
20
20
|
type CostSummary,
|
|
21
|
+
type LaunchResolvedChildExtensionsV1,
|
|
22
|
+
type RuntimeAcknowledgedChildExtensionsV1,
|
|
21
23
|
type ModelAttempt,
|
|
22
24
|
type NestedRouteInfo,
|
|
23
25
|
type NestedRunSummary,
|
|
@@ -25,6 +27,8 @@ import {
|
|
|
25
27
|
type ResolvedTurnBudget,
|
|
26
28
|
type ResolvedToolBudget,
|
|
27
29
|
type SubagentRunMode,
|
|
30
|
+
type SubagentOutputState,
|
|
31
|
+
type UsageBudgetConfig,
|
|
28
32
|
type ToolBudgetState,
|
|
29
33
|
type TurnBudgetState,
|
|
30
34
|
type Usage,
|
|
@@ -35,6 +39,7 @@ import {
|
|
|
35
39
|
DEFAULT_MAX_OUTPUT,
|
|
36
40
|
type MaxOutputConfig,
|
|
37
41
|
SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
42
|
+
POLL_INTERVAL_MS,
|
|
38
43
|
truncateOutput,
|
|
39
44
|
getSubagentDepthEnv,
|
|
40
45
|
} from "../../shared/types.ts";
|
|
@@ -49,6 +54,7 @@ import {
|
|
|
49
54
|
import {
|
|
50
55
|
type RunnerSubagentStep as SubagentStep,
|
|
51
56
|
type RunnerStep,
|
|
57
|
+
isCheckpointRunnerStep,
|
|
52
58
|
isDynamicRunnerGroup,
|
|
53
59
|
isParallelGroup,
|
|
54
60
|
flattenSteps,
|
|
@@ -58,13 +64,22 @@ import {
|
|
|
58
64
|
DEFAULT_GLOBAL_CONCURRENCY_LIMIT,
|
|
59
65
|
Semaphore,
|
|
60
66
|
} from "../shared/parallel-utils.ts";
|
|
61
|
-
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
67
|
+
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
68
|
+
import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
|
|
62
69
|
import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.ts";
|
|
63
70
|
import { createStructuredOutputRuntime, readStructuredOutput } from "../shared/structured-output.ts";
|
|
71
|
+
import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
|
|
64
72
|
import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
|
|
65
73
|
import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
|
|
66
74
|
import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.ts";
|
|
67
75
|
import { formatModelAttemptNote, isRetryableModelFailure } from "../shared/model-fallback.ts";
|
|
76
|
+
import {
|
|
77
|
+
SUBAGENT_STARTUP_RETRY_DELAYS_MS,
|
|
78
|
+
formatSubagentStartupRetryExhaustedError,
|
|
79
|
+
formatSubagentStartupRetryNote,
|
|
80
|
+
isRetryableSubagentStartupFailure,
|
|
81
|
+
waitForSubagentStartupRetry,
|
|
82
|
+
} from "../shared/subagent-startup-retry.ts";
|
|
68
83
|
import { markProcessTerminalCandidateLeaseRelease, writeProcessTerminalCandidate, type ProcessTerminalCandidate } from "./process-terminal.ts";
|
|
69
84
|
import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from "./steering.ts";
|
|
70
85
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
@@ -99,9 +114,10 @@ import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts
|
|
|
99
114
|
import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from "../shared/acceptance.ts";
|
|
100
115
|
import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.ts";
|
|
101
116
|
import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
|
|
102
|
-
import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from "./chain-append.ts";
|
|
117
|
+
import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.ts";
|
|
103
118
|
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
104
119
|
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
120
|
+
import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
|
|
105
121
|
import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup } from "../shared/parallel-handoff.ts";
|
|
106
122
|
import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
|
|
107
123
|
import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
|
|
@@ -149,12 +165,15 @@ interface SubagentRunConfig {
|
|
|
149
165
|
deadlineAt?: number;
|
|
150
166
|
turnBudget?: ResolvedTurnBudget;
|
|
151
167
|
toolBudget?: ResolvedToolBudget;
|
|
168
|
+
usageBudget?: UsageBudgetConfig;
|
|
152
169
|
revivalLease?: SessionLeaseRequest;
|
|
153
170
|
revivalLeaseToken?: string;
|
|
154
171
|
/** Global cap on simultaneously-running subagent tasks within this run. */
|
|
155
172
|
globalConcurrencyLimit?: number;
|
|
156
173
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
157
174
|
launchContractDigest?: string;
|
|
175
|
+
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
176
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
158
177
|
runnerProcessInstanceId?: string;
|
|
159
178
|
}
|
|
160
179
|
|
|
@@ -163,7 +182,10 @@ interface StepResult {
|
|
|
163
182
|
context?: "fresh" | "fork";
|
|
164
183
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
165
184
|
capabilityAudit?: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit;
|
|
185
|
+
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
186
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
166
187
|
output: string;
|
|
188
|
+
outputState?: SubagentOutputState;
|
|
167
189
|
error?: string;
|
|
168
190
|
protocolError?: ProtocolOutputLimit;
|
|
169
191
|
success: boolean;
|
|
@@ -172,6 +194,7 @@ interface StepResult {
|
|
|
172
194
|
interrupted?: boolean;
|
|
173
195
|
timedOut?: boolean;
|
|
174
196
|
stopped?: boolean;
|
|
197
|
+
processSignal?: string | null;
|
|
175
198
|
turnBudget?: TurnBudgetState;
|
|
176
199
|
turnBudgetExceeded?: boolean;
|
|
177
200
|
wrapUpRequested?: boolean;
|
|
@@ -395,10 +418,13 @@ interface RunPiStreamingResult {
|
|
|
395
418
|
exitCode: number | null;
|
|
396
419
|
messages: Message[];
|
|
397
420
|
usage: Usage;
|
|
421
|
+
toolCount: number;
|
|
422
|
+
durationMs: number;
|
|
398
423
|
model?: string;
|
|
399
424
|
error?: string;
|
|
400
425
|
protocolError?: ProtocolOutputLimit;
|
|
401
426
|
finalOutput: string;
|
|
427
|
+
outputState: SubagentOutputState;
|
|
402
428
|
interrupted?: boolean;
|
|
403
429
|
timedOut?: boolean;
|
|
404
430
|
stopped?: boolean;
|
|
@@ -409,6 +435,7 @@ interface RunPiStreamingResult {
|
|
|
409
435
|
toolBudgetBlocked?: boolean;
|
|
410
436
|
observedMutationAttempt?: boolean;
|
|
411
437
|
watchdog?: ChildWatchdogStateSnapshot;
|
|
438
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
412
439
|
processInstanceId: string;
|
|
413
440
|
processCloseObservedAt?: number;
|
|
414
441
|
processSignal?: string | null;
|
|
@@ -434,6 +461,7 @@ function runPiStreaming(
|
|
|
434
461
|
onWriterProcess?: (writer: { state: "none" | "spawning" } | { state: "running"; pid: number }) => void,
|
|
435
462
|
): Promise<RunPiStreamingResult> {
|
|
436
463
|
return new Promise((resolve) => {
|
|
464
|
+
const startedAt = Date.now();
|
|
437
465
|
const processInstanceId = randomUUID();
|
|
438
466
|
onWriterProcess?.({ state: "spawning" });
|
|
439
467
|
const outputStream = fs.createWriteStream(outputFile, { flags: "w" });
|
|
@@ -471,6 +499,7 @@ function runPiStreaming(
|
|
|
471
499
|
let turnBudgetMessage: string | undefined;
|
|
472
500
|
let turnBudget: TurnBudgetState | undefined;
|
|
473
501
|
let observedMutationAttempt = false;
|
|
502
|
+
let toolCount = 0;
|
|
474
503
|
const childWatchdogConfig = decodeChildWatchdogConfig(env?.[CHILD_WATCHDOG_CONFIG_ENV]);
|
|
475
504
|
let childWatchdogState: ChildWatchdogStateSnapshot | undefined;
|
|
476
505
|
let applyChildLifecycle = (_action: ChildLifecycleAction): void => {};
|
|
@@ -557,6 +586,7 @@ function runPiStreaming(
|
|
|
557
586
|
onChildEvent?.(event);
|
|
558
587
|
|
|
559
588
|
if (event.type === "tool_execution_start" && event.toolName) {
|
|
589
|
+
toolCount += 1;
|
|
560
590
|
observedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args);
|
|
561
591
|
const toolArgs = extractToolArgsPreview(event.args ?? {});
|
|
562
592
|
writeOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);
|
|
@@ -790,16 +820,27 @@ function runPiStreaming(
|
|
|
790
820
|
const stderr = stderrTail.text();
|
|
791
821
|
const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
|
|
792
822
|
const finalError = error ?? assistantError;
|
|
793
|
-
const forcedDrainAfterFinalSuccess = forcedTerminationSignal && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
|
|
823
|
+
const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
|
|
824
|
+
const signalError = isUnexplainedProcessSignal({
|
|
825
|
+
processSignal: signal,
|
|
826
|
+
interrupted,
|
|
827
|
+
timedOut,
|
|
828
|
+
stopped,
|
|
829
|
+
turnBudgetExceeded,
|
|
830
|
+
forcedDrainAfterFinalSuccess,
|
|
831
|
+
}) ? formatProcessSignalError(signal!) : undefined;
|
|
794
832
|
resolve({
|
|
795
833
|
stderr,
|
|
796
834
|
exitCode: timedOut || stopped ? 1 : turnBudgetExceeded ? 1 : interrupted || forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (exitCode ?? 1) : exitCode,
|
|
797
835
|
messages,
|
|
798
836
|
usage,
|
|
837
|
+
toolCount,
|
|
838
|
+
durationMs: Date.now() - startedAt,
|
|
799
839
|
model,
|
|
800
|
-
error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError,
|
|
840
|
+
error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError ?? signalError,
|
|
801
841
|
protocolError,
|
|
802
842
|
finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput,
|
|
843
|
+
outputState: finalOutput.trim() ? "present" : "absent",
|
|
803
844
|
interrupted,
|
|
804
845
|
timedOut,
|
|
805
846
|
stopped,
|
|
@@ -833,7 +874,7 @@ function runPiStreaming(
|
|
|
833
874
|
const stderr = stderrTail.text();
|
|
834
875
|
const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
|
|
835
876
|
const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
|
|
836
|
-
resolve({ stderr, exitCode: 1, messages, usage, model, error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput, timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState, processInstanceId });
|
|
877
|
+
resolve({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, model, error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput, outputState: finalOutput.trim() ? "present" : "absent", timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState, processInstanceId });
|
|
837
878
|
});
|
|
838
879
|
});
|
|
839
880
|
}
|
|
@@ -992,6 +1033,8 @@ async function runSingleStep(
|
|
|
992
1033
|
context?: "fresh" | "fork";
|
|
993
1034
|
agentContract?: import("../../shared/types.ts").AgentContract;
|
|
994
1035
|
launchContractDigest?: string;
|
|
1036
|
+
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
1037
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
995
1038
|
output: string;
|
|
996
1039
|
exitCode: number | null;
|
|
997
1040
|
error?: string;
|
|
@@ -1132,6 +1175,7 @@ async function runSingleStep(
|
|
|
1132
1175
|
: [undefined];
|
|
1133
1176
|
const attemptedModels: string[] = [];
|
|
1134
1177
|
let capabilityAudit: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit | undefined;
|
|
1178
|
+
let launchResolvedExtensions = step.launchResolvedExtensions;
|
|
1135
1179
|
const modelAttempts: ModelAttempt[] = [];
|
|
1136
1180
|
const writerProcesses: Array<{ processInstanceId: string; kind: "pi-writer"; attempt: number; closeObservedAt: number; exitCode: number | null; signal: string | null }> = [];
|
|
1137
1181
|
let writerAttemptCount = 0;
|
|
@@ -1145,9 +1189,11 @@ async function runSingleStep(
|
|
|
1145
1189
|
let toolBudgetBlocked = false;
|
|
1146
1190
|
let actualLaunchContractDigest = step.launchContractDigest;
|
|
1147
1191
|
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1192
|
+
let modelIndex = 0;
|
|
1193
|
+
let startupAttemptIndex = 0;
|
|
1194
|
+
modelAttemptsLoop: while (modelIndex < candidates.length) {
|
|
1195
|
+
if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
|
|
1196
|
+
const candidate = candidates[modelIndex];
|
|
1151
1197
|
ctx.onAttemptStart?.({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });
|
|
1152
1198
|
const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
|
|
1153
1199
|
if (effectiveStructuredOutput) {
|
|
@@ -1166,7 +1212,7 @@ async function runSingleStep(
|
|
|
1166
1212
|
childIndex: ctx.flatIndex,
|
|
1167
1213
|
})
|
|
1168
1214
|
: undefined;
|
|
1169
|
-
const { args, env, tempDir, toolDiagnosticPath, capabilityAudit: attemptCapabilityAudit } = buildPiArgs({
|
|
1215
|
+
const { args, env, tempDir, toolDiagnosticPath, runtimeAcknowledgedExtensionsPath, capabilityAudit: attemptCapabilityAudit } = buildPiArgs({
|
|
1170
1216
|
parentSessionId: step.parentSessionId,
|
|
1171
1217
|
baseArgs: ["--offline", "--mode", "json", "-p"],
|
|
1172
1218
|
task,
|
|
@@ -1215,6 +1261,7 @@ async function runSingleStep(
|
|
|
1215
1261
|
capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
|
|
1216
1262
|
inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
|
|
1217
1263
|
});
|
|
1264
|
+
launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
|
|
1218
1265
|
actualLaunchContractDigest = launchBindingDigest({
|
|
1219
1266
|
definitionDigest: step.definitionDigest,
|
|
1220
1267
|
task: step.launchBindingTask ?? task,
|
|
@@ -1259,7 +1306,7 @@ async function runSingleStep(
|
|
|
1259
1306
|
writerProcesses.push({
|
|
1260
1307
|
processInstanceId: run.processInstanceId,
|
|
1261
1308
|
kind: "pi-writer",
|
|
1262
|
-
attempt:
|
|
1309
|
+
attempt: writerAttemptCount - 1,
|
|
1263
1310
|
closeObservedAt: run.processCloseObservedAt,
|
|
1264
1311
|
exitCode: run.exitCode,
|
|
1265
1312
|
signal: run.processSignal ?? null,
|
|
@@ -1287,6 +1334,7 @@ async function runSingleStep(
|
|
|
1287
1334
|
const toolAvailabilityError = run.exitCode === 0 && !run.error
|
|
1288
1335
|
? readChildToolDiagnosticError(toolDiagnosticPath)
|
|
1289
1336
|
: undefined;
|
|
1337
|
+
const runtimeAcknowledgedExtensions = readRuntimeAcknowledgedExtensions(runtimeAcknowledgedExtensionsPath);
|
|
1290
1338
|
cleanupTempDir(tempDir);
|
|
1291
1339
|
|
|
1292
1340
|
const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError ? detectSubagentError(run.messages) : null;
|
|
@@ -1341,6 +1389,13 @@ async function runSingleStep(
|
|
|
1341
1389
|
: run.error && run.exitCode === 0
|
|
1342
1390
|
? 1
|
|
1343
1391
|
: run.exitCode;
|
|
1392
|
+
const signalError = run.exitCode !== 0 && isUnexplainedProcessSignal({
|
|
1393
|
+
processSignal: run.processSignal,
|
|
1394
|
+
interrupted: run.interrupted,
|
|
1395
|
+
timedOut: run.timedOut,
|
|
1396
|
+
stopped: run.stopped,
|
|
1397
|
+
turnBudgetExceeded: run.turnBudgetExceeded,
|
|
1398
|
+
}) ? formatProcessSignalError(run.processSignal!) : undefined;
|
|
1344
1399
|
const error = toolAvailabilityError
|
|
1345
1400
|
?? completionGuardError
|
|
1346
1401
|
?? structuredError
|
|
@@ -1349,7 +1404,7 @@ async function runSingleStep(
|
|
|
1349
1404
|
? hiddenError.details
|
|
1350
1405
|
? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
|
|
1351
1406
|
: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
|
|
1352
|
-
: run.error || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined));
|
|
1407
|
+
: run.error || signalError || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined));
|
|
1353
1408
|
const attempt: ModelAttempt = {
|
|
1354
1409
|
model: candidate ?? run.model ?? step.model ?? "default",
|
|
1355
1410
|
success: effectiveExitCode === 0 && !error,
|
|
@@ -1358,7 +1413,7 @@ async function runSingleStep(
|
|
|
1358
1413
|
usage: run.usage,
|
|
1359
1414
|
};
|
|
1360
1415
|
modelAttempts.push(attempt);
|
|
1361
|
-
if (candidate) attemptedModels.push(candidate);
|
|
1416
|
+
if (candidate && startupAttemptIndex === 0) attemptedModels.push(candidate);
|
|
1362
1417
|
completionGuardTriggeredFinal = completionGuardTriggered;
|
|
1363
1418
|
finalOutputSnapshot = outputSnapshot;
|
|
1364
1419
|
if (step.toolBudget) {
|
|
@@ -1367,17 +1422,65 @@ async function runSingleStep(
|
|
|
1367
1422
|
toolBudgetBlocked = Boolean(blockedMessage);
|
|
1368
1423
|
toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);
|
|
1369
1424
|
}
|
|
1370
|
-
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect ? { effects: { fileMutation: fileMutationEffect } } : {}) } as RunPiStreamingResult & { structuredOutput?: unknown; agentContract?: import("../../shared/types.ts").AgentContract; effects?: import("../../shared/types.ts").EffectsProjection };
|
|
1371
|
-
if (run.turnBudgetExceeded) break;
|
|
1372
|
-
if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
|
|
1373
|
-
if (attempt.success || completionGuardTriggered) break;
|
|
1374
|
-
|
|
1375
|
-
|
|
1425
|
+
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect ? { effects: { fileMutation: fileMutationEffect } } : {}) } as RunPiStreamingResult & { structuredOutput?: unknown; agentContract?: import("../../shared/types.ts").AgentContract; effects?: import("../../shared/types.ts").EffectsProjection };
|
|
1426
|
+
if (run.turnBudgetExceeded) break modelAttemptsLoop;
|
|
1427
|
+
if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break modelAttemptsLoop;
|
|
1428
|
+
if (attempt.success || completionGuardTriggered) break modelAttemptsLoop;
|
|
1429
|
+
|
|
1430
|
+
const startupFailure = isRetryableSubagentStartupFailure({
|
|
1431
|
+
exitCode: effectiveExitCode,
|
|
1432
|
+
error,
|
|
1433
|
+
finalOutput: run.finalOutput,
|
|
1434
|
+
messageCount: run.messages.length,
|
|
1435
|
+
toolCount: run.toolCount,
|
|
1436
|
+
usage: run.usage,
|
|
1437
|
+
durationMs: run.durationMs,
|
|
1438
|
+
protocolError: run.protocolError,
|
|
1439
|
+
processSignal: run.processSignal,
|
|
1440
|
+
observedMutationAttempt: run.observedMutationAttempt,
|
|
1441
|
+
interrupted: run.interrupted,
|
|
1442
|
+
timedOut: run.timedOut,
|
|
1443
|
+
stopped: run.stopped,
|
|
1444
|
+
turnBudgetExceeded: run.turnBudgetExceeded,
|
|
1445
|
+
});
|
|
1446
|
+
const retryDelayMs = SUBAGENT_STARTUP_RETRY_DELAYS_MS[startupAttemptIndex];
|
|
1447
|
+
if (startupFailure && retryDelayMs !== undefined) {
|
|
1448
|
+
const retryNote = formatSubagentStartupRetryNote({
|
|
1449
|
+
model: attempt.model,
|
|
1450
|
+
attempt: startupAttemptIndex + 1,
|
|
1451
|
+
maxAttempts: SUBAGENT_STARTUP_RETRY_DELAYS_MS.length + 1,
|
|
1452
|
+
delayMs: retryDelayMs,
|
|
1453
|
+
});
|
|
1454
|
+
const shouldRetry = await waitForSubagentStartupRetry(retryDelayMs, [ctx.timeoutSignal, ctx.stopSignal]);
|
|
1455
|
+
if (!shouldRetry || ctx.skipAcceptance?.()) break modelAttemptsLoop;
|
|
1456
|
+
attempt.error = retryNote;
|
|
1457
|
+
attemptNotes.push(retryNote);
|
|
1458
|
+
startupAttemptIndex += 1;
|
|
1459
|
+
continue;
|
|
1460
|
+
}
|
|
1461
|
+
if (startupFailure) {
|
|
1462
|
+
const startupError = formatSubagentStartupRetryExhaustedError({
|
|
1463
|
+
model: attempt.model,
|
|
1464
|
+
attempts: startupAttemptIndex + 1,
|
|
1465
|
+
});
|
|
1466
|
+
attempt.error = startupError;
|
|
1467
|
+
finalResult.error = startupError;
|
|
1468
|
+
finalResult.finalOutput = startupError;
|
|
1469
|
+
break modelAttemptsLoop;
|
|
1470
|
+
}
|
|
1471
|
+
if (!isRetryableModelFailure(error) || modelIndex === candidates.length - 1) break modelAttemptsLoop;
|
|
1472
|
+
attemptNotes.push(formatModelAttemptNote(attempt, candidates[modelIndex + 1]));
|
|
1473
|
+
modelIndex += 1;
|
|
1474
|
+
startupAttemptIndex = 0;
|
|
1376
1475
|
}
|
|
1377
1476
|
|
|
1378
1477
|
const rawOutput = finalResult?.finalOutput ?? "";
|
|
1379
1478
|
const outputForPersistence = stripAcceptanceReport(rawOutput);
|
|
1380
|
-
|
|
1479
|
+
// Persist whenever an output path is configured and meaningful output exists,
|
|
1480
|
+
// not only for successful runs: failed children keep a readable result file
|
|
1481
|
+
// and a saved-output reference instead of raw inline output. Synthetic
|
|
1482
|
+
// failures without output stay "absent" and are not promoted to a reference.
|
|
1483
|
+
const resolvedOutput = step.outputPath && (outputForPersistence.trim() || (finalResult?.exitCode ?? 1) === 0)
|
|
1381
1484
|
? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot)
|
|
1382
1485
|
: { fullOutput: outputForPersistence };
|
|
1383
1486
|
const output = stripAcceptanceReport(resolvedOutput.fullOutput);
|
|
@@ -1401,6 +1504,13 @@ async function runSingleStep(
|
|
|
1401
1504
|
const childWrittenOutput = step.outputPath
|
|
1402
1505
|
? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)
|
|
1403
1506
|
: undefined;
|
|
1507
|
+
const outputState: SubagentOutputState = finalResult?.outputState === "present"
|
|
1508
|
+
|| (finalResult as (RunPiStreamingResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput !== undefined
|
|
1509
|
+
|| Boolean(childWrittenOutput?.trim())
|
|
1510
|
+
? "present"
|
|
1511
|
+
: resolvedOutput.savedPath
|
|
1512
|
+
? "unknown"
|
|
1513
|
+
: finalResult?.outputState ?? "unknown";
|
|
1404
1514
|
const finalizedOutput = finalizeSingleOutput({
|
|
1405
1515
|
fullOutput: outputForSummary,
|
|
1406
1516
|
outputPath: step.outputPath,
|
|
@@ -1409,6 +1519,9 @@ async function runSingleStep(
|
|
|
1409
1519
|
savedPath: resolvedOutput.savedPath,
|
|
1410
1520
|
outputReference,
|
|
1411
1521
|
saveError: resolvedOutput.saveError,
|
|
1522
|
+
error: finalResult?.error
|
|
1523
|
+
?? (finalResult?.stopped ? ctx.stopMessage ?? "Subagent stopped by user." : undefined)
|
|
1524
|
+
?? (finalResult?.timedOut ? ctx.timeoutMessage ?? "Subagent timed out." : undefined),
|
|
1412
1525
|
});
|
|
1413
1526
|
outputForSummary = finalizedOutput.displayOutput;
|
|
1414
1527
|
const acceptance = step.effectiveAcceptance && !finalResult?.stopped && !finalResult?.turnBudgetExceeded && !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted && !ctx.skipAcceptance?.()
|
|
@@ -1473,6 +1586,8 @@ async function runSingleStep(
|
|
|
1473
1586
|
acceptance: effectiveAcceptance,
|
|
1474
1587
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
1475
1588
|
launchContractDigest: actualLaunchContractDigest,
|
|
1589
|
+
launchResolvedExtensions,
|
|
1590
|
+
...((finalResult as (RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }) | undefined)?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: (finalResult as RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }).runtimeAcknowledgedExtensions } : {}),
|
|
1476
1591
|
...(transcriptWriter ? { transcriptPath: artifactPaths.transcriptPath } : {}),
|
|
1477
1592
|
transcriptError: transcriptWriter?.getError(),
|
|
1478
1593
|
skills: step.skills,
|
|
@@ -1488,7 +1603,12 @@ async function runSingleStep(
|
|
|
1488
1603
|
context: step.context,
|
|
1489
1604
|
...(step.agentContract ? { agentContract: step.agentContract } : {}),
|
|
1490
1605
|
launchContractDigest: actualLaunchContractDigest,
|
|
1606
|
+
// Authoritative durable output location for parent-facing delivery: the
|
|
1607
|
+
// explicit/generated saved output path when present, otherwise the async
|
|
1608
|
+
// per-child output log (`asyncDir/output-<flat-index>.log`).
|
|
1609
|
+
outputPath: step.outputPath ?? ctx.outputFile,
|
|
1491
1610
|
output: outputForSummary,
|
|
1611
|
+
outputState,
|
|
1492
1612
|
exitCode: effectiveFinalExitCode,
|
|
1493
1613
|
error: effectiveFinalError,
|
|
1494
1614
|
protocolError: finalResult?.protocolError,
|
|
@@ -1504,6 +1624,7 @@ async function runSingleStep(
|
|
|
1504
1624
|
interrupted: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? false : finalResult?.interrupted,
|
|
1505
1625
|
timedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,
|
|
1506
1626
|
stopped: stoppedAfterAcceptance ? true : finalResult?.stopped,
|
|
1627
|
+
processSignal: finalResult?.processSignal,
|
|
1507
1628
|
turnBudget,
|
|
1508
1629
|
turnBudgetExceeded: turnBudgetExceeded || undefined,
|
|
1509
1630
|
wrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined,
|
|
@@ -1517,6 +1638,8 @@ async function runSingleStep(
|
|
|
1517
1638
|
acceptance: effectiveAcceptance,
|
|
1518
1639
|
watchdog: finalResult?.watchdog,
|
|
1519
1640
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
1641
|
+
launchResolvedExtensions,
|
|
1642
|
+
...((finalResult as (RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }) | undefined)?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: (finalResult as RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }).runtimeAcknowledgedExtensions } : {}),
|
|
1520
1643
|
writerProcesses,
|
|
1521
1644
|
writerAttemptCount,
|
|
1522
1645
|
};
|
|
@@ -1525,6 +1648,7 @@ async function runSingleStep(
|
|
|
1525
1648
|
|
|
1526
1649
|
type RunnerStatusStep = NonNullable<AsyncStatus["steps"]>[number] & {
|
|
1527
1650
|
exitCode?: number | null;
|
|
1651
|
+
description?: string;
|
|
1528
1652
|
};
|
|
1529
1653
|
|
|
1530
1654
|
function appendCapabilityCeilingAppliedEvent(eventsPath: string, runId: string, stepIndex: number, agent: string, result: StepResult): void {
|
|
@@ -1722,6 +1846,10 @@ async function runSubagent(
|
|
|
1722
1846
|
let timedOut = false;
|
|
1723
1847
|
let stopped = false;
|
|
1724
1848
|
let turnBudgetExceeded = false;
|
|
1849
|
+
let usageBudgetExceeded = false;
|
|
1850
|
+
let checkpointRejected = false;
|
|
1851
|
+
let pendingCheckpointDecision: "approved" | "rejected" | undefined;
|
|
1852
|
+
let wakeCheckpointDecision: (() => void) | undefined;
|
|
1725
1853
|
const timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;
|
|
1726
1854
|
const stopMessage = "Subagent stopped by user.";
|
|
1727
1855
|
const timeoutAbortController = new AbortController();
|
|
@@ -1736,6 +1864,19 @@ async function runSubagent(
|
|
|
1736
1864
|
let flatStepCount = 0;
|
|
1737
1865
|
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
|
|
1738
1866
|
const step = steps[stepIndex]!;
|
|
1867
|
+
if (isCheckpointRunnerStep(step)) {
|
|
1868
|
+
initialStatusSteps.push({
|
|
1869
|
+
agent: `checkpoint:${step.checkpoint}`,
|
|
1870
|
+
phase: step.phase,
|
|
1871
|
+
label: step.label ?? step.checkpoint,
|
|
1872
|
+
status: "pending",
|
|
1873
|
+
checkpoint: { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending", stepIndex },
|
|
1874
|
+
recentTools: [],
|
|
1875
|
+
recentOutput: [],
|
|
1876
|
+
});
|
|
1877
|
+
flatStepCount++;
|
|
1878
|
+
continue;
|
|
1879
|
+
}
|
|
1739
1880
|
if (isParallelGroup(step)) {
|
|
1740
1881
|
parallelGroups.push({ start: flatStepCount, count: step.parallel.length, stepIndex });
|
|
1741
1882
|
for (const task of step.parallel) {
|
|
@@ -1743,6 +1884,7 @@ async function runSubagent(
|
|
|
1743
1884
|
const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount });
|
|
1744
1885
|
initialStatusSteps.push({
|
|
1745
1886
|
agent: task.agent,
|
|
1887
|
+
...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
|
|
1746
1888
|
...(task.context ? { context: task.context } : {}),
|
|
1747
1889
|
phase: task.phase,
|
|
1748
1890
|
label: task.label,
|
|
@@ -1750,6 +1892,7 @@ async function runSubagent(
|
|
|
1750
1892
|
structured: task.structured,
|
|
1751
1893
|
...(task.agentContract ? { agentContract: task.agentContract } : {}),
|
|
1752
1894
|
...(task.launchContractDigest ? { launchContractDigest: task.launchContractDigest } : {}),
|
|
1895
|
+
...(task.launchResolvedExtensions ? { launchResolvedExtensions: task.launchResolvedExtensions } : {}),
|
|
1753
1896
|
...(task.capabilityCeiling ? { capabilityCeiling: task.capabilityCeiling } : {}),
|
|
1754
1897
|
status: "pending",
|
|
1755
1898
|
...(task.toolBudget ? { toolBudget: initialToolBudgetState(task.toolBudget) } : {}),
|
|
@@ -1786,6 +1929,7 @@ async function runSubagent(
|
|
|
1786
1929
|
const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount });
|
|
1787
1930
|
initialStatusSteps.push({
|
|
1788
1931
|
agent: step.agent,
|
|
1932
|
+
...(statusStepDescription(step.task) ? { description: statusStepDescription(step.task) } : {}),
|
|
1789
1933
|
...(step.context ? { context: step.context } : {}),
|
|
1790
1934
|
phase: step.phase,
|
|
1791
1935
|
label: step.label,
|
|
@@ -1793,6 +1937,7 @@ async function runSubagent(
|
|
|
1793
1937
|
structured: step.structured,
|
|
1794
1938
|
...(step.agentContract ? { agentContract: step.agentContract } : {}),
|
|
1795
1939
|
...(step.launchContractDigest ? { launchContractDigest: step.launchContractDigest } : {}),
|
|
1940
|
+
...(step.launchResolvedExtensions ? { launchResolvedExtensions: step.launchResolvedExtensions } : {}),
|
|
1796
1941
|
...(step.capabilityCeiling ? { capabilityCeiling: step.capabilityCeiling } : {}),
|
|
1797
1942
|
status: "pending",
|
|
1798
1943
|
...(step.toolBudget ? { toolBudget: initialToolBudgetState(step.toolBudget) } : {}),
|
|
@@ -1831,6 +1976,7 @@ async function runSubagent(
|
|
|
1831
1976
|
...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
|
|
1832
1977
|
...(config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {}),
|
|
1833
1978
|
...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),
|
|
1979
|
+
...(config.usageBudget ? { usageBudget: usageBudgetState(config.usageBudget, undefined) } : {}),
|
|
1834
1980
|
pid: process.pid,
|
|
1835
1981
|
cwd,
|
|
1836
1982
|
currentStep: 0,
|
|
@@ -1838,6 +1984,7 @@ async function runSubagent(
|
|
|
1838
1984
|
parallelGroups,
|
|
1839
1985
|
workflowGraph: config.workflowGraph,
|
|
1840
1986
|
...(config.launchContractDigest ? { launchContractDigest: config.launchContractDigest } : {}),
|
|
1987
|
+
...(config.launchResolvedExtensions ? { launchResolvedExtensions: config.launchResolvedExtensions } : {}),
|
|
1841
1988
|
...(config.capabilityCeiling ? { capabilityCeiling: config.capabilityCeiling } : {}),
|
|
1842
1989
|
...(config.runnerProcessInstanceId ? { processTerminal: { version: 1 as const, state: "pending" as const, runId: id, runnerProcessInstanceId: config.runnerProcessInstanceId } } : {}),
|
|
1843
1990
|
steps: initialStatusSteps,
|
|
@@ -1848,6 +1995,23 @@ async function runSubagent(
|
|
|
1848
1995
|
|
|
1849
1996
|
fs.mkdirSync(asyncDir, { recursive: true });
|
|
1850
1997
|
writeAtomicJson(statusPath, statusPayload);
|
|
1998
|
+
let pendingParallelUsageCost: CostSummary = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
1999
|
+
const currentUsageTotals = (): CostSummary => {
|
|
2000
|
+
const cost = results.reduce<CostSummary>((sum, result) => ({
|
|
2001
|
+
inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? result.usage?.input ?? 0),
|
|
2002
|
+
outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? result.usage?.output ?? 0),
|
|
2003
|
+
costUsd: sum.costUsd + (result.totalCost?.costUsd ?? result.usage?.cost ?? 0),
|
|
2004
|
+
}), { inputTokens: pendingParallelUsageCost.inputTokens, outputTokens: pendingParallelUsageCost.outputTokens, costUsd: pendingParallelUsageCost.costUsd });
|
|
2005
|
+
return {
|
|
2006
|
+
inputTokens: Math.max(cost.inputTokens, statusPayload.totalTokens?.input ?? 0),
|
|
2007
|
+
outputTokens: Math.max(cost.outputTokens, statusPayload.totalTokens?.output ?? 0),
|
|
2008
|
+
costUsd: cost.costUsd,
|
|
2009
|
+
};
|
|
2010
|
+
};
|
|
2011
|
+
const refreshUsageBudget = () => {
|
|
2012
|
+
statusPayload.usageBudget = usageBudgetState(config.usageBudget, currentUsageTotals());
|
|
2013
|
+
return statusPayload.usageBudget;
|
|
2014
|
+
};
|
|
1851
2015
|
const emitNestedSelfEvent = (type: "subagent.nested.updated" | "subagent.nested.completed"): void => {
|
|
1852
2016
|
if (!config.nestedRoute || !config.nestedSelf) return;
|
|
1853
2017
|
try {
|
|
@@ -1873,9 +2037,9 @@ async function runSubagent(
|
|
|
1873
2037
|
const refreshWorkflowGraph = (): void => {
|
|
1874
2038
|
if (!config.workflowGraph) return;
|
|
1875
2039
|
const graph = structuredClone(statusPayload.workflowGraph ?? config.workflowGraph);
|
|
1876
|
-
const normalize = (status: RunnerStatusStep["status"]): "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached" => {
|
|
2040
|
+
const normalize = (status: RunnerStatusStep["status"]): "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached" | "rejected" => {
|
|
1877
2041
|
if (status === "complete" || status === "completed") return "completed";
|
|
1878
|
-
if (status === "running" || status === "failed" || status === "paused" || status === "stopped" || status === "pending") return status;
|
|
2042
|
+
if (status === "running" || status === "failed" || status === "paused" || status === "stopped" || status === "pending" || status === "rejected") return status;
|
|
1879
2043
|
return "pending";
|
|
1880
2044
|
};
|
|
1881
2045
|
const updateNode = (node: NonNullable<typeof graph.nodes>[number]): void => {
|
|
@@ -1885,6 +2049,7 @@ async function runSubagent(
|
|
|
1885
2049
|
node.status = normalize(step.status);
|
|
1886
2050
|
node.error = step.error;
|
|
1887
2051
|
node.acceptanceStatus = step.acceptance?.status;
|
|
2052
|
+
node.checkpoint = step.checkpoint;
|
|
1888
2053
|
}
|
|
1889
2054
|
if (statusPayload.currentStep === node.flatIndex) graph.currentNodeId = node.id;
|
|
1890
2055
|
}
|
|
@@ -1893,10 +2058,11 @@ async function runSubagent(
|
|
|
1893
2058
|
if (node.children.every((child) => child.status === "completed")) node.status = "completed";
|
|
1894
2059
|
else if (node.children.some((child) => child.status === "running")) node.status = "running";
|
|
1895
2060
|
else if (node.children.some((child) => child.status === "stopped")) node.status = "stopped";
|
|
2061
|
+
else if (node.children.some((child) => child.status === "rejected")) node.status = "rejected";
|
|
1896
2062
|
else if (node.children.some((child) => child.status === "failed")) node.status = "failed";
|
|
1897
2063
|
else if (node.children.some((child) => child.status === "paused")) node.status = "paused";
|
|
1898
2064
|
}
|
|
1899
|
-
if (node.error && node.status !== "stopped") node.status = "failed";
|
|
2065
|
+
if (node.error && node.status !== "stopped" && node.status !== "rejected") node.status = "failed";
|
|
1900
2066
|
};
|
|
1901
2067
|
for (const node of graph.nodes) updateNode(node);
|
|
1902
2068
|
statusPayload.workflowGraph = graph;
|
|
@@ -2544,6 +2710,7 @@ async function runSubagent(
|
|
|
2544
2710
|
const totalInput = statusPayload.totalTokens?.input ?? 0;
|
|
2545
2711
|
const totalOutput = statusPayload.totalTokens?.output ?? 0;
|
|
2546
2712
|
statusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };
|
|
2713
|
+
refreshUsageBudget();
|
|
2547
2714
|
}
|
|
2548
2715
|
statusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);
|
|
2549
2716
|
updateStepTurnBudget(
|
|
@@ -2729,6 +2896,10 @@ async function runSubagent(
|
|
|
2729
2896
|
onInterrupt: interruptRunner,
|
|
2730
2897
|
onTimeout: timeoutRunner,
|
|
2731
2898
|
onStop: stopRunner,
|
|
2899
|
+
onCheckpointDecision: (decision) => {
|
|
2900
|
+
pendingCheckpointDecision = decision;
|
|
2901
|
+
wakeCheckpointDecision?.();
|
|
2902
|
+
},
|
|
2732
2903
|
onSteer: (request) => {
|
|
2733
2904
|
const targetStep = request.targetIndex !== undefined ? statusPayload.steps[request.targetIndex] : undefined;
|
|
2734
2905
|
if (targetStep?.status === "pending") {
|
|
@@ -2779,14 +2950,95 @@ async function runSubagent(
|
|
|
2779
2950
|
|
|
2780
2951
|
let flatIndex = 0;
|
|
2781
2952
|
let stepCursor = 0;
|
|
2953
|
+
const waitForCheckpointDecision = async (): Promise<"approved" | "rejected" | undefined> => {
|
|
2954
|
+
while (!pendingCheckpointDecision && !interrupted && !timedOut && !stopped) {
|
|
2955
|
+
await new Promise<void>((resolve) => {
|
|
2956
|
+
wakeCheckpointDecision = resolve;
|
|
2957
|
+
const timer = setTimeout(resolve, POLL_INTERVAL_MS);
|
|
2958
|
+
timer.unref?.();
|
|
2959
|
+
});
|
|
2960
|
+
wakeCheckpointDecision = undefined;
|
|
2961
|
+
}
|
|
2962
|
+
const decision = pendingCheckpointDecision;
|
|
2963
|
+
pendingCheckpointDecision = undefined;
|
|
2964
|
+
return decision;
|
|
2965
|
+
};
|
|
2782
2966
|
|
|
2783
2967
|
while (true) {
|
|
2784
2968
|
if (interrupted || timedOut || stopped || turnBudgetExceeded) break;
|
|
2785
2969
|
consumePendingAppendRequests();
|
|
2786
2970
|
if (stepCursor >= steps.length) break;
|
|
2971
|
+
refreshUsageBudget();
|
|
2972
|
+
if (statusPayload.usageBudget?.exhausted) {
|
|
2973
|
+
usageBudgetExceeded = true;
|
|
2974
|
+
statusPayload.state = "failed";
|
|
2975
|
+
statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
2976
|
+
statusPayload.currentStep = flatIndex;
|
|
2977
|
+
statusPayload.lastUpdate = Date.now();
|
|
2978
|
+
writeStatusPayload();
|
|
2979
|
+
break;
|
|
2980
|
+
}
|
|
2787
2981
|
const stepIndex = stepCursor++;
|
|
2788
2982
|
const step = steps[stepIndex]!;
|
|
2789
2983
|
|
|
2984
|
+
if (isCheckpointRunnerStep(step)) {
|
|
2985
|
+
const now = Date.now();
|
|
2986
|
+
const statusStep = statusPayload.steps[flatIndex];
|
|
2987
|
+
const checkpoint = { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending" as const, stepIndex };
|
|
2988
|
+
statusPayload.state = "paused";
|
|
2989
|
+
statusPayload.currentStep = flatIndex;
|
|
2990
|
+
statusPayload.checkpoint = checkpoint;
|
|
2991
|
+
statusPayload.activityState = undefined;
|
|
2992
|
+
statusPayload.lastUpdate = now;
|
|
2993
|
+
if (statusStep) {
|
|
2994
|
+
statusStep.status = "paused";
|
|
2995
|
+
statusStep.startedAt = now;
|
|
2996
|
+
statusStep.checkpoint = checkpoint;
|
|
2997
|
+
}
|
|
2998
|
+
writeStatusPayload();
|
|
2999
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.paused", ts: now, runId: id, stepIndex, checkpoint }));
|
|
3000
|
+
const decision = await waitForCheckpointDecision();
|
|
3001
|
+
if (decision === "approved") {
|
|
3002
|
+
const approvedAt = Date.now();
|
|
3003
|
+
const approved = { ...checkpoint, status: "approved" as const, approvedAt };
|
|
3004
|
+
statusPayload.state = "running";
|
|
3005
|
+
statusPayload.checkpoint = approved;
|
|
3006
|
+
if (statusStep) {
|
|
3007
|
+
statusStep.status = "complete";
|
|
3008
|
+
statusStep.endedAt = approvedAt;
|
|
3009
|
+
statusStep.durationMs = approvedAt - now;
|
|
3010
|
+
statusStep.exitCode = 0;
|
|
3011
|
+
statusStep.checkpoint = approved;
|
|
3012
|
+
}
|
|
3013
|
+
statusPayload.lastUpdate = approvedAt;
|
|
3014
|
+
writeStatusPayload();
|
|
3015
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.approved", ts: approvedAt, runId: id, stepIndex, checkpoint: approved }));
|
|
3016
|
+
flatIndex++;
|
|
3017
|
+
continue;
|
|
3018
|
+
}
|
|
3019
|
+
if (decision === "rejected") {
|
|
3020
|
+
const rejectedAt = Date.now();
|
|
3021
|
+
const rejected = { ...checkpoint, status: "rejected" as const, rejectedAt };
|
|
3022
|
+
checkpointRejected = true;
|
|
3023
|
+
statusPayload.state = "rejected";
|
|
3024
|
+
statusPayload.error = `Checkpoint '${step.checkpoint}' rejected.`;
|
|
3025
|
+
statusPayload.checkpoint = rejected;
|
|
3026
|
+
if (statusStep) {
|
|
3027
|
+
statusStep.status = "rejected";
|
|
3028
|
+
statusStep.error = statusPayload.error;
|
|
3029
|
+
statusStep.endedAt = rejectedAt;
|
|
3030
|
+
statusStep.durationMs = rejectedAt - now;
|
|
3031
|
+
statusStep.exitCode = 1;
|
|
3032
|
+
statusStep.checkpoint = rejected;
|
|
3033
|
+
}
|
|
3034
|
+
statusPayload.lastUpdate = rejectedAt;
|
|
3035
|
+
writeStatusPayload();
|
|
3036
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.rejected", ts: rejectedAt, runId: id, stepIndex, checkpoint: rejected }));
|
|
3037
|
+
break;
|
|
3038
|
+
}
|
|
3039
|
+
break;
|
|
3040
|
+
}
|
|
3041
|
+
|
|
2790
3042
|
if (isDynamicRunnerGroup(step)) {
|
|
2791
3043
|
const groupStartFlatIndex = flatIndex;
|
|
2792
3044
|
let materialized: ReturnType<typeof materializeDynamicParallelStep>;
|
|
@@ -2931,12 +3183,14 @@ async function runSubagent(
|
|
|
2931
3183
|
const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount });
|
|
2932
3184
|
return {
|
|
2933
3185
|
agent: task.agent,
|
|
3186
|
+
...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
|
|
2934
3187
|
...(task.context ? { context: task.context } : {}),
|
|
2935
3188
|
phase: task.phase ?? step.phase,
|
|
2936
3189
|
label: task.label,
|
|
2937
3190
|
outputName: undefined,
|
|
2938
3191
|
structured: Boolean(task.structuredOutputSchema),
|
|
2939
3192
|
...(task.agentContract ? { agentContract: task.agentContract } : {}),
|
|
3193
|
+
...(task.launchResolvedExtensions ? { launchResolvedExtensions: task.launchResolvedExtensions } : {}),
|
|
2940
3194
|
...(task.capabilityCeiling ? { capabilityCeiling: task.capabilityCeiling } : {}),
|
|
2941
3195
|
status: "pending",
|
|
2942
3196
|
...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),
|
|
@@ -2997,6 +3251,22 @@ async function runSubagent(
|
|
|
2997
3251
|
let aborted = false;
|
|
2998
3252
|
const parallelResults = await mapConcurrent(dynamicSteps, concurrency, async (task, taskIdx) => {
|
|
2999
3253
|
const fi = groupStartFlatIndex + taskIdx;
|
|
3254
|
+
refreshUsageBudget();
|
|
3255
|
+
if (statusPayload.usageBudget?.exhausted) {
|
|
3256
|
+
const skippedAt = Date.now();
|
|
3257
|
+
const message = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
3258
|
+
statusPayload.steps[fi].status = "failed";
|
|
3259
|
+
statusPayload.steps[fi].error = message;
|
|
3260
|
+
statusPayload.steps[fi].startedAt = skippedAt;
|
|
3261
|
+
statusPayload.steps[fi].endedAt = skippedAt;
|
|
3262
|
+
statusPayload.steps[fi].durationMs = 0;
|
|
3263
|
+
statusPayload.steps[fi].exitCode = 1;
|
|
3264
|
+
statusPayload.lastUpdate = skippedAt;
|
|
3265
|
+
usageBudgetExceeded = true;
|
|
3266
|
+
writeStatusPayload();
|
|
3267
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0 }));
|
|
3268
|
+
return { agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true };
|
|
3269
|
+
}
|
|
3000
3270
|
if (timedOut) return timedOutStepResult(task.agent, task.context);
|
|
3001
3271
|
if (stopped) return stoppedStepResult(task.agent, task.context);
|
|
3002
3272
|
if (interrupted) return pausedStepResult(task.agent, task.context);
|
|
@@ -3080,11 +3350,21 @@ async function runSubagent(
|
|
|
3080
3350
|
statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
|
|
3081
3351
|
statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
|
|
3082
3352
|
statusPayload.steps[fi].totalCost = singleResult.totalCost;
|
|
3353
|
+
if (singleResult.totalCost) {
|
|
3354
|
+
pendingParallelUsageCost = {
|
|
3355
|
+
inputTokens: pendingParallelUsageCost.inputTokens + singleResult.totalCost.inputTokens,
|
|
3356
|
+
outputTokens: pendingParallelUsageCost.outputTokens + singleResult.totalCost.outputTokens,
|
|
3357
|
+
costUsd: pendingParallelUsageCost.costUsd + singleResult.totalCost.costUsd,
|
|
3358
|
+
};
|
|
3359
|
+
refreshUsageBudget();
|
|
3360
|
+
}
|
|
3083
3361
|
statusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error;
|
|
3084
3362
|
statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
|
|
3085
3363
|
statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
|
|
3086
3364
|
statusPayload.steps[fi].agentContract = singleResult.agentContract;
|
|
3087
3365
|
statusPayload.steps[fi].launchContractDigest = singleResult.launchContractDigest;
|
|
3366
|
+
statusPayload.steps[fi].launchResolvedExtensions = singleResult.launchResolvedExtensions;
|
|
3367
|
+
statusPayload.steps[fi].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
|
|
3088
3368
|
statusPayload.steps[fi].effects = singleResult.effects;
|
|
3089
3369
|
statusPayload.steps[fi].execution = singleResult.execution;
|
|
3090
3370
|
statusPayload.steps[fi].review = singleResult.review;
|
|
@@ -3116,7 +3396,11 @@ async function runSubagent(
|
|
|
3116
3396
|
context: pr.context,
|
|
3117
3397
|
agentContract: pr.agentContract,
|
|
3118
3398
|
launchContractDigest: pr.launchContractDigest,
|
|
3399
|
+
launchResolvedExtensions: pr.launchResolvedExtensions,
|
|
3400
|
+
runtimeAcknowledgedExtensions: pr.runtimeAcknowledgedExtensions,
|
|
3119
3401
|
output: pr.output,
|
|
3402
|
+
outputPath: pr.outputPath,
|
|
3403
|
+
outputState: pr.outputState,
|
|
3120
3404
|
error: pr.error,
|
|
3121
3405
|
protocolError: pr.protocolError,
|
|
3122
3406
|
success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
|
|
@@ -3151,6 +3435,8 @@ async function runSubagent(
|
|
|
3151
3435
|
capabilityAudit: pr.capabilityAudit,
|
|
3152
3436
|
});
|
|
3153
3437
|
}
|
|
3438
|
+
pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
3439
|
+
refreshUsageBudget();
|
|
3154
3440
|
const collection = collectDynamicResults(step as Parameters<typeof collectDynamicResults>[0], materialized.items, parallelResults);
|
|
3155
3441
|
const failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
|
|
3156
3442
|
const acceptanceFailures = parallelResults
|
|
@@ -3316,6 +3602,25 @@ async function runSubagent(
|
|
|
3316
3602
|
concurrency,
|
|
3317
3603
|
async (task, taskIdx) => {
|
|
3318
3604
|
const fi = groupStartFlatIndex + taskIdx;
|
|
3605
|
+
refreshUsageBudget();
|
|
3606
|
+
if (statusPayload.usageBudget?.exhausted) {
|
|
3607
|
+
const skippedAt = Date.now();
|
|
3608
|
+
const message = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
3609
|
+
statusPayload.steps[fi].status = "failed";
|
|
3610
|
+
statusPayload.steps[fi].error = message;
|
|
3611
|
+
statusPayload.steps[fi].startedAt = skippedAt;
|
|
3612
|
+
statusPayload.steps[fi].endedAt = skippedAt;
|
|
3613
|
+
statusPayload.steps[fi].durationMs = 0;
|
|
3614
|
+
statusPayload.steps[fi].exitCode = 1;
|
|
3615
|
+
statusPayload.steps[fi].activityState = undefined;
|
|
3616
|
+
statusPayload.lastUpdate = skippedAt;
|
|
3617
|
+
usageBudgetExceeded = true;
|
|
3618
|
+
writeStatusPayload();
|
|
3619
|
+
appendJsonl(eventsPath, JSON.stringify({
|
|
3620
|
+
type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0,
|
|
3621
|
+
}));
|
|
3622
|
+
return { agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true };
|
|
3623
|
+
}
|
|
3319
3624
|
if (timedOut) return timedOutStepResult(task.agent, task.context);
|
|
3320
3625
|
if (stopped) return stoppedStepResult(task.agent, task.context);
|
|
3321
3626
|
if (interrupted) return pausedStepResult(task.agent, task.context);
|
|
@@ -3421,10 +3726,20 @@ async function runSubagent(
|
|
|
3421
3726
|
statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
|
|
3422
3727
|
statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
|
|
3423
3728
|
statusPayload.steps[fi].totalCost = singleResult.totalCost;
|
|
3729
|
+
if (singleResult.totalCost) {
|
|
3730
|
+
pendingParallelUsageCost = {
|
|
3731
|
+
inputTokens: pendingParallelUsageCost.inputTokens + singleResult.totalCost.inputTokens,
|
|
3732
|
+
outputTokens: pendingParallelUsageCost.outputTokens + singleResult.totalCost.outputTokens,
|
|
3733
|
+
costUsd: pendingParallelUsageCost.costUsd + singleResult.totalCost.costUsd,
|
|
3734
|
+
};
|
|
3735
|
+
refreshUsageBudget();
|
|
3736
|
+
}
|
|
3424
3737
|
statusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error;
|
|
3425
3738
|
statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
|
|
3426
3739
|
statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
|
|
3427
3740
|
statusPayload.steps[fi].agentContract = singleResult.agentContract;
|
|
3741
|
+
statusPayload.steps[fi].launchResolvedExtensions = singleResult.launchResolvedExtensions;
|
|
3742
|
+
statusPayload.steps[fi].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
|
|
3428
3743
|
statusPayload.steps[fi].effects = singleResult.effects;
|
|
3429
3744
|
statusPayload.steps[fi].execution = singleResult.execution;
|
|
3430
3745
|
statusPayload.steps[fi].review = singleResult.review;
|
|
@@ -3492,7 +3807,10 @@ async function runSubagent(
|
|
|
3492
3807
|
context: pr.context,
|
|
3493
3808
|
agentContract: pr.agentContract,
|
|
3494
3809
|
launchContractDigest: pr.launchContractDigest,
|
|
3810
|
+
launchResolvedExtensions: pr.launchResolvedExtensions,
|
|
3495
3811
|
output: pr.output,
|
|
3812
|
+
outputPath: pr.outputPath,
|
|
3813
|
+
outputState: pr.outputState,
|
|
3496
3814
|
error: pr.error,
|
|
3497
3815
|
protocolError: pr.protocolError,
|
|
3498
3816
|
success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
|
|
@@ -3525,6 +3843,8 @@ async function runSubagent(
|
|
|
3525
3843
|
watchdog: pr.watchdog,
|
|
3526
3844
|
});
|
|
3527
3845
|
}
|
|
3846
|
+
pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
3847
|
+
refreshUsageBudget();
|
|
3528
3848
|
for (let t = 0; t < group.parallel.length; t++) {
|
|
3529
3849
|
const outputName = group.parallel[t]?.outputName;
|
|
3530
3850
|
if (outputName) outputs[outputName] = outputEntryFromAsyncResult({
|
|
@@ -3564,7 +3884,13 @@ async function runSubagent(
|
|
|
3564
3884
|
cleanup,
|
|
3565
3885
|
results: parallelResults.map((result) => ({
|
|
3566
3886
|
agent: result.agent,
|
|
3567
|
-
status: result.stopped
|
|
3887
|
+
status: result.stopped || (result.exitCode !== 0 && isUnexplainedProcessSignal({
|
|
3888
|
+
processSignal: result.processSignal,
|
|
3889
|
+
interrupted: result.interrupted,
|
|
3890
|
+
timedOut: result.timedOut,
|
|
3891
|
+
stopped: result.stopped,
|
|
3892
|
+
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
3893
|
+
})) ? "stopped" : result.interrupted ? "paused" : result.exitCode === 0 ? "completed" : "failed",
|
|
3568
3894
|
summary: result.output || result.error || "(no output)",
|
|
3569
3895
|
...(result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {}),
|
|
3570
3896
|
...(result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {}),
|
|
@@ -3668,7 +3994,11 @@ async function runSubagent(
|
|
|
3668
3994
|
context: singleResult.context,
|
|
3669
3995
|
agentContract: singleResult.agentContract,
|
|
3670
3996
|
launchContractDigest: singleResult.launchContractDigest,
|
|
3997
|
+
launchResolvedExtensions: singleResult.launchResolvedExtensions,
|
|
3998
|
+
runtimeAcknowledgedExtensions: singleResult.runtimeAcknowledgedExtensions,
|
|
3671
3999
|
output: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
|
|
4000
|
+
outputPath: singleResult.outputPath,
|
|
4001
|
+
outputState: singleResult.outputState,
|
|
3672
4002
|
error: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error,
|
|
3673
4003
|
protocolError: singleResult.protocolError,
|
|
3674
4004
|
success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,
|
|
@@ -3758,6 +4088,8 @@ async function runSubagent(
|
|
|
3758
4088
|
statusPayload.steps[flatIndex].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[flatIndex].transcriptPath;
|
|
3759
4089
|
statusPayload.steps[flatIndex].transcriptError = singleResult.transcriptError;
|
|
3760
4090
|
statusPayload.steps[flatIndex].agentContract = singleResult.agentContract;
|
|
4091
|
+
statusPayload.steps[flatIndex].launchResolvedExtensions = singleResult.launchResolvedExtensions;
|
|
4092
|
+
statusPayload.steps[flatIndex].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
|
|
3761
4093
|
statusPayload.steps[flatIndex].effects = singleResult.effects;
|
|
3762
4094
|
statusPayload.steps[flatIndex].execution = singleResult.execution;
|
|
3763
4095
|
statusPayload.steps[flatIndex].review = singleResult.review;
|
|
@@ -3828,6 +4160,7 @@ async function runSubagent(
|
|
|
3828
4160
|
}
|
|
3829
4161
|
|
|
3830
4162
|
const resultMode = config.resultMode ?? statusPayload.mode;
|
|
4163
|
+
const singleRuntimeAcknowledgedExtensions = results.length === 1 ? results[0]?.runtimeAcknowledgedExtensions : undefined;
|
|
3831
4164
|
const totalCost = results.reduce<CostSummary>((sum, result) => ({
|
|
3832
4165
|
inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? 0),
|
|
3833
4166
|
outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? 0),
|
|
@@ -3878,7 +4211,14 @@ async function runSubagent(
|
|
|
3878
4211
|
clearTimeout(timeoutTimer);
|
|
3879
4212
|
timeoutTimer = undefined;
|
|
3880
4213
|
}
|
|
3881
|
-
|
|
4214
|
+
const signalTerminated = !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal({
|
|
4215
|
+
processSignal: result.processSignal,
|
|
4216
|
+
interrupted: result.interrupted,
|
|
4217
|
+
timedOut: result.timedOut,
|
|
4218
|
+
stopped: result.stopped,
|
|
4219
|
+
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
4220
|
+
}));
|
|
4221
|
+
statusPayload.state = checkpointRejected ? "rejected" : stopped || signalTerminated ? "stopped" : timedOut || turnBudgetExceeded || usageBudgetExceeded || statusPayload.error ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed";
|
|
3882
4222
|
closeSteerInbox(asyncDir, statusPayload.state);
|
|
3883
4223
|
disposeControlInbox();
|
|
3884
4224
|
for (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);
|
|
@@ -3900,6 +4240,8 @@ async function runSubagent(
|
|
|
3900
4240
|
if (stopped) {
|
|
3901
4241
|
statusPayload.stopped = true;
|
|
3902
4242
|
statusPayload.error = stopMessage;
|
|
4243
|
+
} else if (signalTerminated && !statusPayload.error) {
|
|
4244
|
+
statusPayload.error = results.find((result) => result.processSignal)?.error;
|
|
3903
4245
|
}
|
|
3904
4246
|
if (timedOut) {
|
|
3905
4247
|
statusPayload.timedOut = true;
|
|
@@ -3909,10 +4251,15 @@ async function runSubagent(
|
|
|
3909
4251
|
const budget = statusPayload.turnBudget;
|
|
3910
4252
|
statusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : "Subagent exceeded turn budget.";
|
|
3911
4253
|
}
|
|
4254
|
+
if (usageBudgetExceeded && statusPayload.usageBudget && !statusPayload.error) {
|
|
4255
|
+
statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
4256
|
+
}
|
|
3912
4257
|
statusPayload.endedAt = runEndedAt;
|
|
3913
4258
|
statusPayload.lastUpdate = runEndedAt;
|
|
3914
4259
|
statusPayload.sessionFile = effectiveSessionFile;
|
|
4260
|
+
if (singleRuntimeAcknowledgedExtensions) statusPayload.runtimeAcknowledgedExtensions = singleRuntimeAcknowledgedExtensions;
|
|
3915
4261
|
statusPayload.totalCost = finalTotalCost;
|
|
4262
|
+
statusPayload.usageBudget = usageBudgetState(config.usageBudget, currentUsageTotals());
|
|
3916
4263
|
statusPayload.shareUrl = shareUrl;
|
|
3917
4264
|
statusPayload.gistUrl = gistUrl;
|
|
3918
4265
|
statusPayload.shareError = shareError;
|
|
@@ -3934,6 +4281,7 @@ async function runSubagent(
|
|
|
3934
4281
|
durationMs: runEndedAt - overallStartTime,
|
|
3935
4282
|
totalTokens: statusPayload.totalTokens,
|
|
3936
4283
|
totalCost: finalTotalCost,
|
|
4284
|
+
usageBudget: statusPayload.usageBudget,
|
|
3937
4285
|
}),
|
|
3938
4286
|
);
|
|
3939
4287
|
writeRunLog(logPath, {
|
|
@@ -3961,9 +4309,9 @@ async function runSubagent(
|
|
|
3961
4309
|
id,
|
|
3962
4310
|
agent: agentName,
|
|
3963
4311
|
mode: resultMode,
|
|
3964
|
-
success: !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.every((r) => r.success),
|
|
3965
|
-
state: stopped ? "stopped" : timedOut || turnBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
|
|
3966
|
-
summary: stopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? (statusPayload.error ?? "Subagent exceeded turn budget.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
|
|
4312
|
+
success: !checkpointRejected && !stopped && !timedOut && !turnBudgetExceeded && !usageBudgetExceeded && !interrupted && !signalTerminated && results.every((r) => r.success),
|
|
4313
|
+
state: checkpointRejected ? "rejected" : stopped || signalTerminated ? "stopped" : timedOut || turnBudgetExceeded || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
|
|
4314
|
+
summary: checkpointRejected ? (statusPayload.error ?? "Checkpoint rejected.") : stopped ? stopMessage : signalTerminated ? (statusPayload.error ?? "Subagent process terminated by signal.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? (statusPayload.error ?? "Subagent exceeded turn budget.") : usageBudgetExceeded ? (statusPayload.error ?? "Usage budget exhausted.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
|
|
3967
4315
|
...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),
|
|
3968
4316
|
...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
|
|
3969
4317
|
...(statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {}),
|
|
@@ -3971,11 +4319,15 @@ async function runSubagent(
|
|
|
3971
4319
|
...(statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {}),
|
|
3972
4320
|
...(statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {}),
|
|
3973
4321
|
...(statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {}),
|
|
3974
|
-
...(
|
|
4322
|
+
...(statusPayload.usageBudget ? { usageBudget: statusPayload.usageBudget } : {}),
|
|
4323
|
+
...(statusPayload.checkpoint ? { checkpoint: statusPayload.checkpoint } : {}),
|
|
4324
|
+
...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } : turnBudgetExceeded ? { error: statusPayload.error ?? "Subagent exceeded turn budget." } : usageBudgetExceeded ? { error: statusPayload.error ?? "Usage budget exhausted." } : {}),
|
|
3975
4325
|
results: results.map((r) => ({
|
|
3976
4326
|
agent: r.agent,
|
|
3977
4327
|
context: r.context,
|
|
4328
|
+
outputPath: r.outputPath,
|
|
3978
4329
|
output: r.output,
|
|
4330
|
+
outputState: r.outputState,
|
|
3979
4331
|
error: r.error,
|
|
3980
4332
|
protocolError: r.protocolError,
|
|
3981
4333
|
success: r.success,
|
|
@@ -3983,6 +4335,7 @@ async function runSubagent(
|
|
|
3983
4335
|
interrupted: r.interrupted || undefined,
|
|
3984
4336
|
timedOut: r.timedOut || undefined,
|
|
3985
4337
|
stopped: r.stopped || undefined,
|
|
4338
|
+
processSignal: r.processSignal || undefined,
|
|
3986
4339
|
turnBudget: r.turnBudget,
|
|
3987
4340
|
turnBudgetExceeded: r.turnBudgetExceeded || undefined,
|
|
3988
4341
|
wrapUpRequested: r.wrapUpRequested || undefined,
|
|
@@ -4000,6 +4353,8 @@ async function runSubagent(
|
|
|
4000
4353
|
transcriptError: r.transcriptError,
|
|
4001
4354
|
agentContract: r.agentContract,
|
|
4002
4355
|
launchContractDigest: r.launchContractDigest,
|
|
4356
|
+
launchResolvedExtensions: r.launchResolvedExtensions,
|
|
4357
|
+
runtimeAcknowledgedExtensions: r.runtimeAcknowledgedExtensions,
|
|
4003
4358
|
execution: r.execution,
|
|
4004
4359
|
review: r.review,
|
|
4005
4360
|
effects: r.effects,
|
|
@@ -4016,16 +4371,20 @@ async function runSubagent(
|
|
|
4016
4371
|
parallelHandoff: statusPayload.parallelHandoff,
|
|
4017
4372
|
capabilityCeiling: statusPayload.capabilityCeiling,
|
|
4018
4373
|
capabilityAudit: statusPayload.capabilityAudit,
|
|
4019
|
-
exitCode: stopped || timedOut || turnBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
|
|
4374
|
+
exitCode: checkpointRejected || stopped || timedOut || turnBudgetExceeded || usageBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
|
|
4020
4375
|
timestamp: runEndedAt,
|
|
4021
4376
|
durationMs: runEndedAt - overallStartTime,
|
|
4022
4377
|
totalTokens: statusPayload.totalTokens,
|
|
4023
4378
|
totalCost: finalTotalCost,
|
|
4379
|
+
usageBudget: statusPayload.usageBudget,
|
|
4380
|
+
checkpoint: statusPayload.checkpoint,
|
|
4024
4381
|
truncated,
|
|
4025
4382
|
artifactsDir,
|
|
4026
4383
|
cwd,
|
|
4027
4384
|
asyncDir,
|
|
4028
4385
|
launchContractDigest: config.launchContractDigest,
|
|
4386
|
+
launchResolvedExtensions: config.launchResolvedExtensions,
|
|
4387
|
+
runtimeAcknowledgedExtensions: singleRuntimeAcknowledgedExtensions,
|
|
4029
4388
|
sessionId: config.sessionId,
|
|
4030
4389
|
sessionFile: effectiveSessionFile,
|
|
4031
4390
|
intercomTarget: config.controlIntercomTarget,
|