@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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
3
|
+
import type { Details, SubagentState } from "../../shared/types.ts";
|
|
4
|
+
import { deliverStopRequest } from "../background/control-channel.ts";
|
|
5
|
+
import { reconcileAsyncRun } from "../background/stale-run-reconciler.ts";
|
|
6
|
+
|
|
7
|
+
function getAsyncStopTarget(
|
|
8
|
+
state: SubagentState,
|
|
9
|
+
runId: string | undefined,
|
|
10
|
+
location?: { asyncDir: string | null; resolvedId?: string },
|
|
11
|
+
): { asyncId: string; asyncDir: string } | undefined {
|
|
12
|
+
if (location?.asyncDir) {
|
|
13
|
+
return {
|
|
14
|
+
asyncId: location.resolvedId ?? runId ?? path.basename(location.asyncDir),
|
|
15
|
+
asyncDir: location.asyncDir,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (!runId) return undefined;
|
|
19
|
+
const direct = state.asyncJobs.get(runId);
|
|
20
|
+
return direct ? { asyncId: direct.asyncId, asyncDir: direct.asyncDir } : undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function stopAsyncRun(
|
|
24
|
+
state: SubagentState,
|
|
25
|
+
runId: string | undefined,
|
|
26
|
+
kill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean,
|
|
27
|
+
location?: { asyncDir: string | null; resolvedId?: string },
|
|
28
|
+
): AgentToolResult<Details> | null {
|
|
29
|
+
const target = getAsyncStopTarget(state, runId, location);
|
|
30
|
+
if (!target) return null;
|
|
31
|
+
const status = reconcileAsyncRun(target.asyncDir, { kill }).status;
|
|
32
|
+
if (state.currentSessionId && status?.sessionId !== state.currentSessionId) {
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text: `Async run '${target.asyncId}' was not found in the active session.` }],
|
|
35
|
+
isError: true,
|
|
36
|
+
details: { mode: "management", results: [] },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (!status || (status.state !== "running" && status.state !== "queued")) {
|
|
40
|
+
return {
|
|
41
|
+
content: [{ type: "text", text: `No running or queued async run was found for '${runId ?? "current"}'.` }],
|
|
42
|
+
isError: true,
|
|
43
|
+
details: { mode: "management", results: [] },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
deliverStopRequest({ asyncDir: target.asyncDir, pid: typeof status.pid === "number" ? status.pid : undefined, kill, source: "stop-action" });
|
|
48
|
+
const tracked = state.asyncJobs.get(target.asyncId);
|
|
49
|
+
if (tracked) {
|
|
50
|
+
tracked.activityState = undefined;
|
|
51
|
+
tracked.updatedAt = Date.now();
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
content: [{ type: "text", text: `Stop requested for async run ${target.asyncId}.` }],
|
|
55
|
+
details: { mode: "management", results: [] },
|
|
56
|
+
};
|
|
57
|
+
} catch (error) {
|
|
58
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
59
|
+
return {
|
|
60
|
+
content: [{ type: "text", text: `Failed to stop async run ${target.asyncId}: ${message}` }],
|
|
61
|
+
isError: true,
|
|
62
|
+
details: { mode: "management", results: [] },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -451,13 +451,13 @@ export class ChainClarifyComponent implements Component {
|
|
|
451
451
|
return;
|
|
452
452
|
}
|
|
453
453
|
|
|
454
|
-
if (matchesKey(data, "up")) {
|
|
454
|
+
if (matchesKey(data, "up") || matchesKey(data, "k")) {
|
|
455
455
|
this.selectedStep = Math.max(0, this.selectedStep - 1);
|
|
456
456
|
this.tui.requestRender();
|
|
457
457
|
return;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
if (matchesKey(data, "down")) {
|
|
460
|
+
if (matchesKey(data, "down") || matchesKey(data, "j")) {
|
|
461
461
|
const maxStep = Math.max(0, this.agentConfigs.length - 1);
|
|
462
462
|
this.selectedStep = Math.min(maxStep, this.selectedStep + 1);
|
|
463
463
|
this.tui.requestRender();
|
|
@@ -1123,7 +1123,7 @@ export class ChainClarifyComponent implements Component {
|
|
|
1123
1123
|
private getFooterText(): string {
|
|
1124
1124
|
return this.mode === 'single'
|
|
1125
1125
|
? " [Enter] Run • [Esc] Cancel "
|
|
1126
|
-
: " [Enter] Run • [Esc] Cancel • [
|
|
1126
|
+
: " [Enter] Run • [Esc] Cancel • [↑↓/jk] Navigate ";
|
|
1127
1127
|
}
|
|
1128
1128
|
|
|
1129
1129
|
private appendNotice(lines: string[]): void {
|
|
@@ -8,7 +8,7 @@ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
|
8
8
|
import type { ExtensionContext } from "@selesai/code";
|
|
9
9
|
import type { AgentConfig } from "../../agents/agents.ts";
|
|
10
10
|
import { ChainClarifyComponent, type ChainClarifyResult, type BehaviorOverride } from "./chain-clarify.ts";
|
|
11
|
-
import { toModelInfo, type ModelInfo } from "../../shared/model-info.ts";
|
|
11
|
+
import { resolveEffectiveThinking, toModelInfo, type ModelInfo } from "../../shared/model-info.ts";
|
|
12
12
|
import {
|
|
13
13
|
resolveChainTemplates,
|
|
14
14
|
createChainDir,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
createParallelDirs,
|
|
21
21
|
suppressProgressForReadOnlyTask,
|
|
22
22
|
aggregateParallelOutputs,
|
|
23
|
+
isCheckpointStep,
|
|
23
24
|
isDynamicParallelStep,
|
|
24
25
|
isParallelStep,
|
|
25
26
|
type StepOverrides,
|
|
@@ -33,7 +34,13 @@ import {
|
|
|
33
34
|
import { discoverAvailableSkills, normalizeSkillInput } from "../../agents/skills.ts";
|
|
34
35
|
import { INTERCOM_BRIDGE_MARKER } from "../../intercom/intercom-bridge.ts";
|
|
35
36
|
import { runSync } from "./execution.ts";
|
|
36
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
beginForegroundChild,
|
|
39
|
+
finishForegroundChild,
|
|
40
|
+
retainForegroundSchedulingOwner,
|
|
41
|
+
settleForegroundSchedulingOwner,
|
|
42
|
+
updateForegroundChild,
|
|
43
|
+
} from "./foreground-control.ts";
|
|
37
44
|
import { buildChainSummary } from "../../shared/formatters.ts";
|
|
38
45
|
import { compactForegroundDetails, getSingleResultOutput, mapConcurrent, resolveChildCwd, sumResultsCost, sumResultsUsage } from "../../shared/utils.ts";
|
|
39
46
|
import { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from "../shared/parallel-utils.ts";
|
|
@@ -64,6 +71,8 @@ import {
|
|
|
64
71
|
type ResolvedToolBudget,
|
|
65
72
|
type SingleResult,
|
|
66
73
|
type ToolBudgetConfig,
|
|
74
|
+
type ChainCheckpointState,
|
|
75
|
+
type UsageBudgetConfig,
|
|
67
76
|
MAX_CONCURRENCY,
|
|
68
77
|
resolveChildMaxSubagentDepth,
|
|
69
78
|
} from "../../shared/types.ts";
|
|
@@ -78,9 +87,38 @@ import { acceptanceFailureMessage, aggregateAcceptanceReport, evaluateAcceptance
|
|
|
78
87
|
import { isAgentContractV1 } from "../shared/agent-contract.ts";
|
|
79
88
|
import type { ChainOutputMap } from "../../shared/types.ts";
|
|
80
89
|
import { validateToolBudgetConfig } from "../shared/tool-budget.ts";
|
|
90
|
+
import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
|
|
81
91
|
import type { ContextMode } from "../shared/context-mode.ts";
|
|
82
92
|
import type { ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
|
|
83
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Resolve a chain step's output path and effective output mode.
|
|
96
|
+
*
|
|
97
|
+
* Explicit `output` paths pass through unchanged (absolute as-is, relative under
|
|
98
|
+
* the chain dir). Omitted output generates a collision-safe per-child durable
|
|
99
|
+
* path `<chainDir>/outputs/<flat-index>-<agent>.md` unless the caller explicitly
|
|
100
|
+
* used `output: false`. Omitted `outputMode` resolves to `file-only` when an
|
|
101
|
+
* output path is active; explicit `outputMode: "inline"` is preserved exactly.
|
|
102
|
+
*/
|
|
103
|
+
function resolveChainStepOutput(input: {
|
|
104
|
+
behaviorOutput: string | false;
|
|
105
|
+
rawOutput: string | false | undefined;
|
|
106
|
+
rawOutputMode: "inline" | "file-only" | undefined;
|
|
107
|
+
chainDir: string;
|
|
108
|
+
flatIndex: number;
|
|
109
|
+
agent: string;
|
|
110
|
+
}): { outputPath?: string; outputMode: "inline" | "file-only" } {
|
|
111
|
+
const explicit = typeof input.behaviorOutput === "string" ? input.behaviorOutput : undefined;
|
|
112
|
+
let outputPath: string | undefined;
|
|
113
|
+
if (explicit) {
|
|
114
|
+
outputPath = path.isAbsolute(explicit) ? explicit : path.join(input.chainDir, explicit);
|
|
115
|
+
} else if (input.behaviorOutput === false && input.rawOutput !== false && input.rawOutput !== "false") {
|
|
116
|
+
outputPath = path.join(input.chainDir, "outputs", `${input.flatIndex}-${input.agent}.md`);
|
|
117
|
+
}
|
|
118
|
+
return { outputPath, outputMode: input.rawOutputMode ?? (outputPath ? "file-only" : "inline") };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
84
122
|
interface ChainExecutionDetailsInput {
|
|
85
123
|
results: SingleResult[];
|
|
86
124
|
includeProgress?: boolean;
|
|
@@ -97,6 +135,8 @@ interface ChainExecutionDetailsInput {
|
|
|
97
135
|
dynamicChildren?: Record<number, Array<{ agent: string; label?: string; flatIndex: number; itemKey: string; outputName?: string; structured?: boolean; error?: string }>>;
|
|
98
136
|
dynamicGroupStatuses?: Record<number, { status: "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached"; error?: string; acceptance?: SingleResult["acceptance"] }>;
|
|
99
137
|
parallelHandoff?: Details["parallelHandoff"];
|
|
138
|
+
checkpoint?: ChainCheckpointState;
|
|
139
|
+
usageBudget?: UsageBudgetConfig;
|
|
100
140
|
}
|
|
101
141
|
|
|
102
142
|
interface ParallelChainRunInput {
|
|
@@ -145,7 +185,10 @@ interface ParallelChainRunInput {
|
|
|
145
185
|
timeoutMs?: number;
|
|
146
186
|
deadlineAt?: number;
|
|
147
187
|
turnBudget?: ResolvedTurnBudget;
|
|
188
|
+
usageBudget?: UsageBudgetConfig;
|
|
148
189
|
onDetachedExit?: (index: number, result: SingleResult) => void;
|
|
190
|
+
/** Called after an attached child releases its foreground ownership. */
|
|
191
|
+
onForegroundChildSettled?: () => void;
|
|
149
192
|
toolBudget?: ResolvedToolBudget;
|
|
150
193
|
configToolBudget?: ToolBudgetConfig;
|
|
151
194
|
globalSemaphore?: Semaphore;
|
|
@@ -165,6 +208,8 @@ function buildChainExecutionDetails(input: ChainExecutionDetailsInput): Details
|
|
|
165
208
|
outputs: input.outputs,
|
|
166
209
|
totalChildUsage: sumResultsUsage(input.results),
|
|
167
210
|
totalCost: sumResultsCost(input.results),
|
|
211
|
+
usageBudget: usageBudgetState(input.usageBudget, sumResultsCost(input.results)),
|
|
212
|
+
...(input.checkpoint ? { checkpoint: input.checkpoint } : {}),
|
|
168
213
|
...(input.parallelHandoff ? { parallelHandoff: input.parallelHandoff } : {}),
|
|
169
214
|
workflowGraph: buildWorkflowGraphSnapshot({
|
|
170
215
|
runId: input.runId,
|
|
@@ -277,12 +322,29 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
|
|
|
277
322
|
input.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModels[taskIndex]);
|
|
278
323
|
}
|
|
279
324
|
|
|
325
|
+
const completedResults: SingleResult[] = [];
|
|
326
|
+
if (input.foregroundControl) retainForegroundSchedulingOwner(input.foregroundControl);
|
|
280
327
|
const parallelResults = await mapConcurrent(
|
|
281
328
|
input.step.parallel,
|
|
282
329
|
concurrency,
|
|
283
330
|
async (task, taskIndex) => {
|
|
331
|
+
const childIndex = input.globalTaskIndex + taskIndex;
|
|
332
|
+
const budgetState = usageBudgetState(input.usageBudget, sumResultsCost(input.results.concat(completedResults)));
|
|
333
|
+
if (budgetState?.exhausted) {
|
|
334
|
+
return {
|
|
335
|
+
index: childIndex,
|
|
336
|
+
agent: task.agent,
|
|
337
|
+
task: input.parallelTemplates[taskIndex] ?? "(skipped)",
|
|
338
|
+
exitCode: 1,
|
|
339
|
+
messages: [],
|
|
340
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 },
|
|
341
|
+
error: usageBudgetExceededMessage(budgetState),
|
|
342
|
+
skipped: true,
|
|
343
|
+
} as SingleResult;
|
|
344
|
+
}
|
|
284
345
|
if (aborted && failFast) {
|
|
285
346
|
return {
|
|
347
|
+
index: childIndex,
|
|
286
348
|
agent: task.agent,
|
|
287
349
|
task: "(skipped)",
|
|
288
350
|
exitCode: -1,
|
|
@@ -319,17 +381,26 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
|
|
|
319
381
|
? input.worktreeSetup.worktrees[taskIndex]!.agentCwd
|
|
320
382
|
: resolveChildCwd(input.cwd ?? input.ctx.cwd, task.cwd);
|
|
321
383
|
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
:
|
|
384
|
+
const resolvedTaskOutput = resolveChainStepOutput({
|
|
385
|
+
behaviorOutput: behavior.output,
|
|
386
|
+
rawOutput: task.output,
|
|
387
|
+
rawOutputMode: task.outputMode,
|
|
388
|
+
chainDir: input.chainDir,
|
|
389
|
+
flatIndex: childIndex,
|
|
390
|
+
agent: task.agent,
|
|
391
|
+
});
|
|
392
|
+
const outputPath = resolvedTaskOutput.outputPath;
|
|
393
|
+
const effectiveOutputMode = resolvedTaskOutput.outputMode;
|
|
325
394
|
taskStr = injectSingleOutputInstruction(taskStr, outputPath, taskAgentConfig);
|
|
326
395
|
const interruptController = new AbortController();
|
|
327
|
-
const childIndex = input.globalTaskIndex + taskIndex;
|
|
328
396
|
if (input.foregroundControl) {
|
|
397
|
+
const thinking = resolveEffectiveThinking(effectiveModel, input.thinkingOverrideForTask?.(task.agent, childIndex, effectiveModel));
|
|
329
398
|
beginForegroundChild(input.foregroundControl, {
|
|
330
399
|
index: childIndex,
|
|
331
400
|
agent: task.agent,
|
|
332
401
|
description: cleanTask.trim(),
|
|
402
|
+
...(effectiveModel ? { model: effectiveModel } : {}),
|
|
403
|
+
...(thinking ? { thinking } : {}),
|
|
333
404
|
interrupt: () => {
|
|
334
405
|
if (interruptController.signal.aborted) return false;
|
|
335
406
|
interruptController.abort();
|
|
@@ -342,7 +413,9 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
|
|
|
342
413
|
? createStructuredOutputRuntime(task.outputSchema, path.join(input.chainDir, "structured-output"))
|
|
343
414
|
: undefined;
|
|
344
415
|
const agentContract = task.agentContract ?? input.step.agentContract ?? input.agentContract;
|
|
345
|
-
|
|
416
|
+
let result!: SingleResult;
|
|
417
|
+
try {
|
|
418
|
+
result = await runSync(input.ctx.cwd, input.agents, task.agent, taskStr, {
|
|
346
419
|
parentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,
|
|
347
420
|
capabilityCeiling: input.capabilityCeiling,
|
|
348
421
|
context: input.contextForAgent?.(task.agent),
|
|
@@ -361,7 +434,7 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
|
|
|
361
434
|
artifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,
|
|
362
435
|
artifactConfig: input.artifactConfig,
|
|
363
436
|
outputPath,
|
|
364
|
-
outputMode:
|
|
437
|
+
outputMode: effectiveOutputMode,
|
|
365
438
|
maxSubagentDepth,
|
|
366
439
|
controlConfig: input.controlConfig,
|
|
367
440
|
onControlEvent: input.onControlEvent,
|
|
@@ -380,9 +453,13 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
|
|
|
380
453
|
timeoutMs: input.timeoutMs,
|
|
381
454
|
deadlineAt: input.deadlineAt,
|
|
382
455
|
turnBudget: input.turnBudget,
|
|
383
|
-
onDetachedExit:
|
|
384
|
-
|
|
385
|
-
|
|
456
|
+
onDetachedExit: (result) => {
|
|
457
|
+
try {
|
|
458
|
+
if (input.foregroundControl) finishForegroundChild(input.foregroundControl, childIndex);
|
|
459
|
+
} finally {
|
|
460
|
+
input.onDetachedExit?.(childIndex, result);
|
|
461
|
+
}
|
|
462
|
+
},
|
|
386
463
|
toolBudget: toolBudget.toolBudget,
|
|
387
464
|
onUpdate: input.onUpdate
|
|
388
465
|
? (progressUpdate) => {
|
|
@@ -416,16 +493,28 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
|
|
|
416
493
|
});
|
|
417
494
|
}
|
|
418
495
|
: undefined,
|
|
419
|
-
|
|
420
|
-
|
|
496
|
+
});
|
|
497
|
+
} finally {
|
|
498
|
+
// Rejected attached attempts still release their parallel child control;
|
|
499
|
+
// detached receipts transfer ownership to onDetachedExit.
|
|
500
|
+
if (!result?.detached) {
|
|
501
|
+
if (input.foregroundControl) finishForegroundChild(input.foregroundControl, childIndex);
|
|
502
|
+
input.onForegroundChildSettled?.();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
421
505
|
|
|
422
506
|
if (result.exitCode !== 0 && failFast) {
|
|
423
507
|
aborted = true;
|
|
424
508
|
}
|
|
425
509
|
recordRun(task.agent, cleanTask, result.exitCode, result.progressSummary?.durationMs ?? 0);
|
|
510
|
+
completedResults.push(result);
|
|
426
511
|
return result;
|
|
427
512
|
},
|
|
428
513
|
input.globalSemaphore,
|
|
514
|
+
() => {
|
|
515
|
+
if (input.foregroundControl) settleForegroundSchedulingOwner(input.foregroundControl);
|
|
516
|
+
input.onForegroundChildSettled?.();
|
|
517
|
+
},
|
|
429
518
|
);
|
|
430
519
|
|
|
431
520
|
return parallelResults;
|
|
@@ -470,7 +559,10 @@ interface ChainExecutionParams {
|
|
|
470
559
|
deadlineAt?: number;
|
|
471
560
|
turnBudget?: ResolvedTurnBudget;
|
|
472
561
|
onDetachedExit?: (index: number, result: SingleResult) => void;
|
|
562
|
+
/** Ownership callback used when parallel siblings outlive executeChain rejection. */
|
|
563
|
+
onForegroundChildSettled?: () => void;
|
|
473
564
|
toolBudget?: ResolvedToolBudget;
|
|
565
|
+
usageBudget?: UsageBudgetConfig;
|
|
474
566
|
configToolBudget?: ToolBudgetConfig;
|
|
475
567
|
/** Global cap on simultaneously-running tasks within this chain. Defaults to DEFAULT_GLOBAL_CONCURRENCY_LIMIT. */
|
|
476
568
|
globalConcurrencyLimit?: number;
|
|
@@ -531,7 +623,9 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
531
623
|
let parallelHandoff: Details["parallelHandoff"];
|
|
532
624
|
|
|
533
625
|
const chainAgents: string[] = chainSteps.map((step) =>
|
|
534
|
-
|
|
626
|
+
isCheckpointStep(step)
|
|
627
|
+
? `checkpoint:${step.checkpoint}`
|
|
628
|
+
: isParallelStep(step)
|
|
535
629
|
? `[${step.parallel.map((t) => t.agent).join("+")}]`
|
|
536
630
|
: isDynamicParallelStep(step)
|
|
537
631
|
? `expand:${step.parallel.agent}`
|
|
@@ -539,7 +633,7 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
539
633
|
);
|
|
540
634
|
const totalSteps = chainSteps.length;
|
|
541
635
|
|
|
542
|
-
const makeDetailsInput = (overrides: Pick<Partial<ChainExecutionDetailsInput>, "currentStepIndex" | "currentFlatIndex"> = {}): ChainExecutionDetailsInput => ({
|
|
636
|
+
const makeDetailsInput = (overrides: Pick<Partial<ChainExecutionDetailsInput>, "currentStepIndex" | "currentFlatIndex" | "checkpoint"> = {}): ChainExecutionDetailsInput => ({
|
|
543
637
|
results,
|
|
544
638
|
...(includeProgress !== undefined ? { includeProgress } : {}),
|
|
545
639
|
allProgress,
|
|
@@ -553,16 +647,25 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
553
647
|
dynamicChildren,
|
|
554
648
|
dynamicGroupStatuses,
|
|
555
649
|
...(parallelHandoff ? { parallelHandoff } : {}),
|
|
650
|
+
usageBudget: params.usageBudget,
|
|
556
651
|
...overrides,
|
|
557
652
|
});
|
|
558
653
|
|
|
654
|
+
const usageBudgetError = (stepIndex: number, flatIndex: number): ChainExecutionResult | undefined => {
|
|
655
|
+
const state = usageBudgetState(params.usageBudget, sumResultsCost(results));
|
|
656
|
+
if (!state?.exhausted) return undefined;
|
|
657
|
+
return buildChainExecutionErrorResult(usageBudgetExceededMessage(state), makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: flatIndex }));
|
|
658
|
+
};
|
|
659
|
+
|
|
559
660
|
const firstStep = chainSteps[0]!;
|
|
560
661
|
const originalTask = params.task
|
|
561
|
-
?? (
|
|
562
|
-
?
|
|
563
|
-
:
|
|
564
|
-
? firstStep.parallel
|
|
565
|
-
: (firstStep
|
|
662
|
+
?? (isCheckpointStep(firstStep)
|
|
663
|
+
? undefined
|
|
664
|
+
: isParallelStep(firstStep)
|
|
665
|
+
? firstStep.parallel[0]!.task!
|
|
666
|
+
: isDynamicParallelStep(firstStep)
|
|
667
|
+
? firstStep.parallel.task!
|
|
668
|
+
: (firstStep as SequentialStep).task!);
|
|
566
669
|
try {
|
|
567
670
|
validateChainOutputBindings(chainSteps, { maxItems: params.dynamicFanoutMaxItems });
|
|
568
671
|
} catch (error) {
|
|
@@ -577,7 +680,7 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
577
680
|
}
|
|
578
681
|
|
|
579
682
|
const chainDir = createChainDir(runId, chainDirBase);
|
|
580
|
-
const hasParallelSteps = chainSteps.some((step) => isParallelStep(step) || isDynamicParallelStep(step));
|
|
683
|
+
const hasParallelSteps = chainSteps.some((step) => isParallelStep(step) || isDynamicParallelStep(step) || isCheckpointStep(step));
|
|
581
684
|
let templates: ResolvedTemplates = resolveChainTemplates(chainSteps);
|
|
582
685
|
const shouldClarify = clarify === true && ctx.hasUI && !hasParallelSteps;
|
|
583
686
|
let tuiBehaviorOverrides: (BehaviorOverride | undefined)[] | undefined;
|
|
@@ -677,9 +780,21 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
677
780
|
let progressCreated = false;
|
|
678
781
|
|
|
679
782
|
for (let stepIndex = 0; stepIndex < chainSteps.length; stepIndex++) {
|
|
783
|
+
const budgetError = usageBudgetError(stepIndex, globalTaskIndex);
|
|
784
|
+
if (budgetError) return budgetError;
|
|
680
785
|
const step = chainSteps[stepIndex]!;
|
|
681
786
|
const stepTemplates = templates[stepIndex]!;
|
|
682
787
|
|
|
788
|
+
if (isCheckpointStep(step)) {
|
|
789
|
+
const checkpoint = { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending" as const, stepIndex };
|
|
790
|
+
return {
|
|
791
|
+
content: [{ type: "text", text: `Chain paused at checkpoint '${step.checkpoint}'. Approve with subagent({ action: "approve-checkpoint", id: "${runId}" }) or reject with subagent({ action: "reject-checkpoint", id: "${runId}" }).${step.message ? `
|
|
792
|
+
|
|
793
|
+
${step.message}` : ""}` }],
|
|
794
|
+
details: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex, checkpoint })),
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
|
|
683
798
|
if (isParallelStep(step)) {
|
|
684
799
|
const parallelTemplates = stepTemplates as string[];
|
|
685
800
|
const parallelCwd = resolveChildCwd(cwd ?? ctx.cwd, step.cwd);
|
|
@@ -713,10 +828,16 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
713
828
|
.map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? step.parallel[taskIndex]?.task, originalTask));
|
|
714
829
|
for (let taskIndex = 0; taskIndex < step.parallel.length; taskIndex++) {
|
|
715
830
|
const behavior = parallelBehaviors[taskIndex]!;
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
:
|
|
719
|
-
|
|
831
|
+
const task = step.parallel[taskIndex]!;
|
|
832
|
+
const resolvedOutput = resolveChainStepOutput({
|
|
833
|
+
behaviorOutput: behavior.output,
|
|
834
|
+
rawOutput: task.output,
|
|
835
|
+
rawOutputMode: task.outputMode,
|
|
836
|
+
chainDir,
|
|
837
|
+
flatIndex: globalTaskIndex + taskIndex,
|
|
838
|
+
agent: task.agent,
|
|
839
|
+
});
|
|
840
|
+
const validationError = validateFileOnlyOutputMode(resolvedOutput.outputMode, resolvedOutput.outputPath, `Parallel chain step ${stepIndex + 1} task ${taskIndex + 1} (${task.agent})`);
|
|
720
841
|
if (validationError) return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));
|
|
721
842
|
}
|
|
722
843
|
progressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);
|
|
@@ -768,7 +889,9 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
768
889
|
timeoutMs: params.timeoutMs,
|
|
769
890
|
deadlineAt,
|
|
770
891
|
turnBudget: params.turnBudget,
|
|
892
|
+
usageBudget: params.usageBudget,
|
|
771
893
|
onDetachedExit,
|
|
894
|
+
onForegroundChildSettled: params.onForegroundChildSettled,
|
|
772
895
|
toolBudget: params.toolBudget,
|
|
773
896
|
configToolBudget: params.configToolBudget,
|
|
774
897
|
globalSemaphore,
|
|
@@ -967,10 +1090,16 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
967
1090
|
|
|
968
1091
|
for (let taskIndex = 0; taskIndex < dynamicParallelStep.parallel.length; taskIndex++) {
|
|
969
1092
|
const behavior = parallelBehaviors[taskIndex]!;
|
|
970
|
-
const
|
|
971
|
-
|
|
972
|
-
:
|
|
973
|
-
|
|
1093
|
+
const task = dynamicParallelStep.parallel[taskIndex]!;
|
|
1094
|
+
const resolvedOutput = resolveChainStepOutput({
|
|
1095
|
+
behaviorOutput: behavior.output,
|
|
1096
|
+
rawOutput: task.output,
|
|
1097
|
+
rawOutputMode: task.outputMode,
|
|
1098
|
+
chainDir,
|
|
1099
|
+
flatIndex: globalTaskIndex + taskIndex,
|
|
1100
|
+
agent: task.agent,
|
|
1101
|
+
});
|
|
1102
|
+
const validationError = validateFileOnlyOutputMode(resolvedOutput.outputMode, resolvedOutput.outputPath, `Dynamic chain step ${stepIndex + 1} item ${taskIndex + 1} (${task.agent})`);
|
|
974
1103
|
if (validationError) {
|
|
975
1104
|
dynamicGroupStatuses[stepIndex] = { status: "failed", error: validationError };
|
|
976
1105
|
return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));
|
|
@@ -1024,7 +1153,9 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1024
1153
|
timeoutMs: params.timeoutMs,
|
|
1025
1154
|
deadlineAt,
|
|
1026
1155
|
turnBudget: params.turnBudget,
|
|
1156
|
+
usageBudget: params.usageBudget,
|
|
1027
1157
|
onDetachedExit,
|
|
1158
|
+
onForegroundChildSettled: params.onForegroundChildSettled,
|
|
1028
1159
|
toolBudget: params.toolBudget,
|
|
1029
1160
|
configToolBudget: params.configToolBudget,
|
|
1030
1161
|
globalSemaphore,
|
|
@@ -1205,11 +1336,18 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1205
1336
|
{ scope: modelScope },
|
|
1206
1337
|
);
|
|
1207
1338
|
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1210
|
-
:
|
|
1339
|
+
const resolvedStepOutput = resolveChainStepOutput({
|
|
1340
|
+
behaviorOutput: behavior.output,
|
|
1341
|
+
rawOutput: stepOverride.output,
|
|
1342
|
+
rawOutputMode: seqStep.outputMode,
|
|
1343
|
+
chainDir,
|
|
1344
|
+
flatIndex: globalTaskIndex,
|
|
1345
|
+
agent: seqStep.agent,
|
|
1346
|
+
});
|
|
1347
|
+
const outputPath = resolvedStepOutput.outputPath;
|
|
1348
|
+
const effectiveOutputMode = resolvedStepOutput.outputMode;
|
|
1211
1349
|
stepTask = injectSingleOutputInstruction(stepTask, outputPath, agentConfig);
|
|
1212
|
-
const validationError = validateFileOnlyOutputMode(
|
|
1350
|
+
const validationError = validateFileOnlyOutputMode(effectiveOutputMode, outputPath, `Chain step ${stepIndex + 1} (${seqStep.agent})`);
|
|
1213
1351
|
if (validationError) {
|
|
1214
1352
|
return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
|
|
1215
1353
|
}
|
|
@@ -1217,10 +1355,13 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1217
1355
|
const childIndex = globalTaskIndex;
|
|
1218
1356
|
const interruptController = new AbortController();
|
|
1219
1357
|
if (foregroundControl) {
|
|
1358
|
+
const thinking = resolveEffectiveThinking(effectiveModel, params.thinkingOverrideForTask?.(seqStep.agent, childIndex, effectiveModel));
|
|
1220
1359
|
beginForegroundChild(foregroundControl, {
|
|
1221
1360
|
index: childIndex,
|
|
1222
1361
|
agent: seqStep.agent,
|
|
1223
1362
|
description: cleanTask.trim(),
|
|
1363
|
+
...(effectiveModel ? { model: effectiveModel } : {}),
|
|
1364
|
+
...(thinking ? { thinking } : {}),
|
|
1224
1365
|
interrupt: () => {
|
|
1225
1366
|
if (interruptController.signal.aborted) return false;
|
|
1226
1367
|
interruptController.abort();
|
|
@@ -1229,28 +1370,30 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1229
1370
|
});
|
|
1230
1371
|
}
|
|
1231
1372
|
|
|
1232
|
-
const structuredRuntime = seqStep.outputSchema
|
|
1233
|
-
? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, "structured-output"))
|
|
1234
|
-
: undefined;
|
|
1235
1373
|
const agentContract = seqStep.agentContract ?? params.agentContract;
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1374
|
+
let r!: SingleResult;
|
|
1375
|
+
try {
|
|
1376
|
+
const structuredRuntime = seqStep.outputSchema
|
|
1377
|
+
? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, "structured-output"))
|
|
1378
|
+
: undefined;
|
|
1379
|
+
const toolBudget = resolveChainToolBudget({ stepBudget: seqStep.toolBudget, runBudget: params.toolBudget, agentBudget: agentConfig?.toolBudget, configBudget: params.configToolBudget });
|
|
1380
|
+
if (toolBudget.error) return buildChainExecutionErrorResult(toolBudget.error, {
|
|
1381
|
+
results,
|
|
1382
|
+
includeProgress,
|
|
1383
|
+
allProgress,
|
|
1384
|
+
allArtifactPaths,
|
|
1385
|
+
artifactsDir: params.artifactsDir,
|
|
1386
|
+
chainAgents,
|
|
1387
|
+
chainSteps,
|
|
1388
|
+
totalSteps,
|
|
1389
|
+
currentStepIndex: stepIndex,
|
|
1390
|
+
runId: params.runId,
|
|
1391
|
+
outputs,
|
|
1392
|
+
currentFlatIndex: globalTaskIndex,
|
|
1393
|
+
dynamicChildren,
|
|
1394
|
+
dynamicGroupStatuses,
|
|
1395
|
+
});
|
|
1396
|
+
r = await runSync(ctx.cwd, agents, seqStep.agent, stepTask, {
|
|
1254
1397
|
parentSessionId: ctx.sessionManager.getSessionId() ?? undefined,
|
|
1255
1398
|
capabilityCeiling: params.capabilityCeiling,
|
|
1256
1399
|
context: params.contextForAgent?.(seqStep.agent),
|
|
@@ -1269,7 +1412,7 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1269
1412
|
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
1270
1413
|
artifactConfig,
|
|
1271
1414
|
outputPath,
|
|
1272
|
-
outputMode:
|
|
1415
|
+
outputMode: effectiveOutputMode,
|
|
1273
1416
|
maxSubagentDepth,
|
|
1274
1417
|
controlConfig,
|
|
1275
1418
|
onControlEvent,
|
|
@@ -1288,9 +1431,13 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1288
1431
|
timeoutMs: params.timeoutMs,
|
|
1289
1432
|
deadlineAt,
|
|
1290
1433
|
turnBudget: params.turnBudget,
|
|
1291
|
-
onDetachedExit:
|
|
1292
|
-
|
|
1293
|
-
|
|
1434
|
+
onDetachedExit: (result) => {
|
|
1435
|
+
try {
|
|
1436
|
+
if (foregroundControl) finishForegroundChild(foregroundControl, childIndex);
|
|
1437
|
+
} finally {
|
|
1438
|
+
onDetachedExit?.(childIndex, result);
|
|
1439
|
+
}
|
|
1440
|
+
},
|
|
1294
1441
|
toolBudget: toolBudget.toolBudget,
|
|
1295
1442
|
onUpdate: onUpdate
|
|
1296
1443
|
? (p) => {
|
|
@@ -1324,8 +1471,15 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
|
|
|
1324
1471
|
});
|
|
1325
1472
|
}
|
|
1326
1473
|
: undefined,
|
|
1327
|
-
|
|
1328
|
-
|
|
1474
|
+
});
|
|
1475
|
+
} finally {
|
|
1476
|
+
// Rejected attempts and early validation returns release the child here.
|
|
1477
|
+
// A detached receipt transfers cleanup ownership to onDetachedExit.
|
|
1478
|
+
if (!r?.detached) {
|
|
1479
|
+
if (foregroundControl) finishForegroundChild(foregroundControl, childIndex);
|
|
1480
|
+
params.onForegroundChildSettled?.();
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1329
1483
|
recordRun(seqStep.agent, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);
|
|
1330
1484
|
|
|
1331
1485
|
globalTaskIndex++;
|