@selesai/code 0.13.0 → 0.13.2
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 +22 -0
- package/dist/core/agent-session.d.ts +1 -1
- package/dist/core/agent-session.js +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.js +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/extensions/package.json +1 -2
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
- package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
- package/dist/extensions/pi-hermes-memory/README.md +643 -0
- package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
- package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
- package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
- package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
- package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
- package/dist/extensions/pi-hermes-memory/package.json +66 -0
- package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
- package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
- package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
- package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
- package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
- package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
- package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
- package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
- package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
- package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
- package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
- package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
- package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
- package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
- package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
- package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
- package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
- package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
- package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
- package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
- package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
- package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
- package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
- package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
- package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
- package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
- package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
- package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
- package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
- package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
- package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
- package/dist/extensions/pi-rewind-hook/README.md +4 -1
- package/dist/extensions/pi-rewind-hook/index.ts +151 -21
- package/dist/extensions/pi-rewind-hook/package.json +5 -3
- package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
- package/dist/extensions/pi-subagents/AGENTS.md +5 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
- package/dist/extensions/pi-subagents/README.md +12 -6
- package/dist/extensions/pi-subagents/VISION.md +81 -0
- package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
- package/dist/extensions/pi-subagents/docs/agents.md +488 -0
- package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
- package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
- package/dist/extensions/pi-subagents/docs/models.md +27 -4
- package/dist/extensions/pi-subagents/docs/observability.md +10 -9
- package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
- package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
- package/dist/extensions/pi-subagents/package-lock.json +389 -2
- package/dist/extensions/pi-subagents/package.json +3 -1
- package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
- package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
- package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
- package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
- package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
- package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
- package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
- package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
- package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
- package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
- package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
- package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -7
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
- package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
- package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
- package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
- package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
- package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
- package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
- package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
- package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
- package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
- package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
- package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
- package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
- package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
- package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
- package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
- package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
- package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
- package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
- package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
- package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
- package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
- package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
- package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
- package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
- package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
- package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
- package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
- package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
- package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
- package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +136 -6
- package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
- package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
- package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
- package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
- package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
- package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
- package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -7
- package/dist/skills/workflow/SKILL.md +65 -50
- package/package.json +112 -110
- package/dist/extensions/enable-readonly-tools.test.ts +0 -63
- package/dist/extensions/enable-readonly-tools.ts +0 -24
- package/dist/extensions/model-prompt-injector/config.json +0 -16
- package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
- package/dist/extensions/model-prompt-injector/index.ts +0 -148
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
|
@@ -14,6 +14,7 @@ import { createChildTranscriptWriter, type ChildTranscriptWriter } from "../../s
|
|
|
14
14
|
import { closeSteerInbox, consumeInterruptRequest, consumeSteerRequests, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, enqueueStepSteer, steerAcksDir, steerCapabilityPath, stepSteerInboxDir, watchAsyncControlInbox, type SteerAck, type SteerCapability, type SteerRequest, type StopRequest } from "./control-channel.ts";
|
|
15
15
|
import { appendJsonl as appendRawJsonl, formatOutputArtifactContent, getArtifactPaths, writeArtifact, writeMetadata } from "../../shared/artifacts.ts";
|
|
16
16
|
import { PI_CODING_AGENT_PACKAGE, getPiSpawnCommand, resolveInstalledPiPackageRoot } from "../shared/pi-spawn.ts";
|
|
17
|
+
import { preflightLaunchCwd } from "../shared/launch-cwd.ts";
|
|
17
18
|
import { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, injectSingleOutputInstruction, resolveSingleOutput, type SingleOutputSnapshot } from "../shared/single-output.ts";
|
|
18
19
|
import {
|
|
19
20
|
type ActivityState,
|
|
@@ -35,24 +36,21 @@ import {
|
|
|
35
36
|
type NestedRouteInfo,
|
|
36
37
|
type NestedRunSummary,
|
|
37
38
|
type ResolvedControlConfig,
|
|
38
|
-
type ResolvedTurnBudget,
|
|
39
39
|
type ResolvedToolBudget,
|
|
40
40
|
type RunFanoutBudgetDescriptor,
|
|
41
41
|
type SubagentRunMode,
|
|
42
42
|
type SubagentOutputState,
|
|
43
43
|
type UsageBudgetConfig,
|
|
44
44
|
type ToolBudgetState,
|
|
45
|
-
type TurnBudgetState,
|
|
46
45
|
type Usage,
|
|
47
46
|
type WorkflowGraphSnapshot,
|
|
48
|
-
type SteeringStatus,
|
|
49
47
|
type SteeringTargetState,
|
|
50
48
|
type SteeringTargetStatus,
|
|
51
49
|
type SubagentChildStatusEvent,
|
|
50
|
+
type WorkflowLaneMetadata,
|
|
52
51
|
DEFAULT_MAX_OUTPUT,
|
|
53
52
|
type MaxOutputConfig,
|
|
54
53
|
SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
55
|
-
POLL_INTERVAL_MS,
|
|
56
54
|
truncateOutput,
|
|
57
55
|
getSubagentDepthEnv,
|
|
58
56
|
} from "../../shared/types.ts";
|
|
@@ -78,16 +76,17 @@ import {
|
|
|
78
76
|
Semaphore,
|
|
79
77
|
} from "../shared/parallel-utils.ts";
|
|
80
78
|
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan, type SubagentTaskDelivery } from "../shared/pi-args.ts";
|
|
79
|
+
import { deriveChildSessionName } from "../../shared/child-session-name.ts";
|
|
81
80
|
import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
|
|
82
81
|
import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.ts";
|
|
83
82
|
import { createStructuredOutputRuntime, MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput, readStructuredOutputAcceptanceReport } from "../shared/structured-output.ts";
|
|
84
|
-
import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
|
|
83
|
+
import { formatMidToolExitError, formatProcessSignalError, isOrdinaryToolForMidToolExit, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
|
|
85
84
|
import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
|
|
86
85
|
import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTrackedMutations } from "../shared/mutation-evidence.ts";
|
|
87
86
|
import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
|
|
88
87
|
import { claimRunFanoutBatch, getRunFanoutBudgetSnapshot } from "../shared/run-fanout-budget.ts";
|
|
89
88
|
import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.ts";
|
|
90
|
-
import { formatModelAttemptNote, formatSubagentModelVerificationError, isContextOverflow,
|
|
89
|
+
import { formatModelAttemptNote, formatSubagentModelVerificationError, isContextOverflow, isRetryableModelFailureAttempt, recordRetryableModelFailure } from "../shared/model-fallback.ts";
|
|
91
90
|
import {
|
|
92
91
|
SUBAGENT_STARTUP_RETRY_DELAYS_MS,
|
|
93
92
|
formatSubagentExtensionConflictError,
|
|
@@ -100,8 +99,10 @@ import { markProcessTerminalCandidateLeaseRelease, writeProcessTerminalCandidate
|
|
|
100
99
|
import { createOwnedProcessTreeController, type OwnedProcessTreeController } from "./owned-process-tree.ts";
|
|
101
100
|
import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from "./steering.ts";
|
|
102
101
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
103
|
-
import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.ts";
|
|
104
|
-
import { evaluateCompletionMutationGuard, validateImplementationToolContract } from "../shared/completion-guard.ts";
|
|
102
|
+
import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getFinalOutput, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.ts";
|
|
103
|
+
import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.ts";
|
|
104
|
+
import { planCompletionEvidence, projectSettlementDiagnostic } from "../shared/completion-evidence.ts";
|
|
105
|
+
import { planAbortRecovery } from "../shared/abort-recovery.ts";
|
|
105
106
|
import {
|
|
106
107
|
createMutatingFailureState,
|
|
107
108
|
didMutatingToolFail,
|
|
@@ -124,7 +125,7 @@ import {
|
|
|
124
125
|
formatWorktreeTaskCwdConflict,
|
|
125
126
|
type WorktreeSetup,
|
|
126
127
|
} from "../shared/worktree.ts";
|
|
127
|
-
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
128
|
+
import { findModelInfo, resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
128
129
|
import { assertThinkingWithinCeiling, decodeThinkingCeiling, SUBAGENT_THINKING_CEILING_ENV } from "../../shared/thinking-ceiling.ts";
|
|
129
130
|
import { launchBindingDigest } from "../../shared/launch-contract.ts";
|
|
130
131
|
import { writeInitialProgressFile } from "../../shared/settings.ts";
|
|
@@ -135,15 +136,18 @@ import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
|
|
|
135
136
|
import { normalizeExtensionBindings } from "../shared/extension-bindings.ts";
|
|
136
137
|
import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.ts";
|
|
137
138
|
import { asyncStatusChildIdentity } from "../shared/child-identity.ts";
|
|
138
|
-
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
139
139
|
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
140
140
|
import { effectiveToolTimeoutMs, formatToolTimeoutMessage, toolTimeoutCallKey } from "../shared/tool-timeout.ts";
|
|
141
141
|
import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
|
|
142
142
|
import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writePendingParallelHandoff } from "../shared/parallel-handoff.ts";
|
|
143
143
|
import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
|
|
144
|
-
import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, PI_AGGREGATE_EVENT_PROJECTOR, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
|
|
144
|
+
import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, PI_AGGREGATE_EVENT_PROJECTOR, projectChildLifecycle, type ChildLifecycleAction, type ChildLifecycleState, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
|
|
145
145
|
import { acquireSessionLease, type SessionLeaseRequest } from "../shared/session-lease.ts";
|
|
146
146
|
import { buildExternalCliPrompt, runExternalCli } from "../shared/external-cli-runner.ts";
|
|
147
|
+
import { resolveClaudeCodeLaunch } from "../shared/claude-code-adapter.ts";
|
|
148
|
+
import { resolveCodexExecLaunch } from "../shared/codex-exec-adapter.ts";
|
|
149
|
+
import { resolveCursorAgentLaunch } from "../shared/cursor-agent-adapter.ts";
|
|
150
|
+
import { resolveExternalCliRunnerStatus } from "../shared/external-cli-contract.ts";
|
|
147
151
|
import { runExternalJob } from "../shared/external-job-runner.ts";
|
|
148
152
|
import { createOrcaProgressTab, type OrcaProgressTab } from "../shared/orca-progress-tabs.ts";
|
|
149
153
|
import { decodeSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV, type ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
|
|
@@ -193,7 +197,6 @@ interface SubagentRunConfig {
|
|
|
193
197
|
deadlineAt?: number;
|
|
194
198
|
/** Resolved configured hard per-tool-call timeout (ms); fast tools still have a default when undefined. */
|
|
195
199
|
toolTimeoutMs?: number;
|
|
196
|
-
turnBudget?: ResolvedTurnBudget;
|
|
197
200
|
toolBudget?: ResolvedToolBudget;
|
|
198
201
|
usageBudget?: UsageBudgetConfig;
|
|
199
202
|
revivalLease?: SessionLeaseRequest;
|
|
@@ -206,12 +209,16 @@ interface SubagentRunConfig {
|
|
|
206
209
|
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
207
210
|
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
208
211
|
runnerProcessInstanceId?: string;
|
|
212
|
+
launchBarrierToken?: string;
|
|
209
213
|
parentWorkflowRunId?: string;
|
|
210
214
|
workflowKey?: string;
|
|
215
|
+
lane?: WorkflowLaneMetadata;
|
|
211
216
|
}
|
|
212
217
|
|
|
213
218
|
interface StepResult {
|
|
214
219
|
agent: string;
|
|
220
|
+
/** Human-readable display name for the child session, when derived at launch. */
|
|
221
|
+
sessionName?: string;
|
|
215
222
|
context?: "fresh" | "fork";
|
|
216
223
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
217
224
|
capabilityAudit?: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit;
|
|
@@ -232,9 +239,6 @@ interface StepResult {
|
|
|
232
239
|
stopped?: boolean;
|
|
233
240
|
processSignal?: string | null;
|
|
234
241
|
timeoutRecovery?: import("../../shared/types.ts").TimeoutRecoverySummary;
|
|
235
|
-
turnBudget?: TurnBudgetState;
|
|
236
|
-
turnBudgetExceeded?: boolean;
|
|
237
|
-
wrapUpRequested?: boolean;
|
|
238
242
|
toolBudget?: ToolBudgetState;
|
|
239
243
|
toolBudgetBlocked?: boolean;
|
|
240
244
|
sessionFile?: string;
|
|
@@ -422,6 +426,23 @@ function costSummaryFromAttempts(attempts: ModelAttempt[] | undefined): CostSumm
|
|
|
422
426
|
: undefined;
|
|
423
427
|
}
|
|
424
428
|
|
|
429
|
+
function usageFromAttempts(attempts: ModelAttempt[] | undefined): Usage | undefined {
|
|
430
|
+
if (!attempts || attempts.length === 0) return undefined;
|
|
431
|
+
const usage = emptyUsage();
|
|
432
|
+
for (const attempt of attempts) {
|
|
433
|
+
if (!attempt.usage) continue;
|
|
434
|
+
usage.input += attempt.usage.input;
|
|
435
|
+
usage.output += attempt.usage.output;
|
|
436
|
+
usage.cacheRead += attempt.usage.cacheRead;
|
|
437
|
+
usage.cacheWrite += attempt.usage.cacheWrite;
|
|
438
|
+
usage.cost += attempt.usage.cost;
|
|
439
|
+
usage.turns += attempt.usage.turns;
|
|
440
|
+
}
|
|
441
|
+
return usage.input !== 0 || usage.output !== 0 || usage.cacheRead !== 0 || usage.cacheWrite !== 0 || usage.cost !== 0 || usage.turns !== 0
|
|
442
|
+
? usage
|
|
443
|
+
: undefined;
|
|
444
|
+
}
|
|
445
|
+
|
|
425
446
|
function appendRecentStepOutput(step: RunnerStatusStep, lines: string[]): void {
|
|
426
447
|
const nonEmpty = lines.filter((line) => line.trim());
|
|
427
448
|
if (nonEmpty.length === 0) return;
|
|
@@ -496,6 +517,7 @@ interface ChildUsage {
|
|
|
496
517
|
output?: number;
|
|
497
518
|
outputTokens?: number;
|
|
498
519
|
cacheRead?: number;
|
|
520
|
+
cacheReadTokens?: number;
|
|
499
521
|
cacheWrite?: number;
|
|
500
522
|
cost?: { total?: number };
|
|
501
523
|
}
|
|
@@ -529,14 +551,12 @@ interface RunPiStreamingResult {
|
|
|
529
551
|
interrupted?: boolean;
|
|
530
552
|
timedOut?: boolean;
|
|
531
553
|
stopped?: boolean;
|
|
532
|
-
turnBudget?: TurnBudgetState;
|
|
533
|
-
turnBudgetExceeded?: boolean;
|
|
534
|
-
wrapUpRequested?: boolean;
|
|
535
554
|
toolBudget?: ToolBudgetState;
|
|
536
555
|
toolBudgetBlocked?: boolean;
|
|
537
556
|
observedMutationAttempt?: boolean;
|
|
538
557
|
structuredOutputToolInvoked?: boolean;
|
|
539
558
|
structuredOutputMessageStartIndex?: number;
|
|
559
|
+
structuredOutput?: unknown;
|
|
540
560
|
watchdog?: ChildWatchdogStateSnapshot;
|
|
541
561
|
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
542
562
|
processInstanceId: string;
|
|
@@ -546,6 +566,43 @@ interface RunPiStreamingResult {
|
|
|
546
566
|
currentTool?: string;
|
|
547
567
|
currentToolArgs?: string;
|
|
548
568
|
currentPath?: string;
|
|
569
|
+
afterCompactionSettlement?: boolean;
|
|
570
|
+
abortRecoveryDiagnostic?: string;
|
|
571
|
+
effects?: import("../../shared/types.ts").EffectsProjection;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const MAX_CHILD_FAILURE_DIAGNOSTIC_CHARS = 8_192;
|
|
575
|
+
|
|
576
|
+
function formatRequiredOutputError(requiredOutput: {
|
|
577
|
+
kind: "file-only" | "structured";
|
|
578
|
+
path: string;
|
|
579
|
+
missing: boolean;
|
|
580
|
+
} | undefined): string | undefined {
|
|
581
|
+
if (!requiredOutput?.missing) return undefined;
|
|
582
|
+
return `Required ${requiredOutput.kind} output was not produced: ${requiredOutput.path.slice(0, 2_048)}`;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function formatChildFailureDiagnostic(input: {
|
|
586
|
+
error: string | undefined;
|
|
587
|
+
afterCompactionSettlement?: boolean;
|
|
588
|
+
abortRecoveryDiagnostic?: string;
|
|
589
|
+
requiredOutput?: {
|
|
590
|
+
kind: "file-only" | "structured";
|
|
591
|
+
path: string;
|
|
592
|
+
missing: boolean;
|
|
593
|
+
};
|
|
594
|
+
}): string | undefined {
|
|
595
|
+
const missingOutput = formatRequiredOutputError(input.requiredOutput);
|
|
596
|
+
const notes = [
|
|
597
|
+
input.abortRecoveryDiagnostic,
|
|
598
|
+
input.afterCompactionSettlement ? "Child failure followed session compaction and agent settlement." : undefined,
|
|
599
|
+
missingOutput && input.error !== missingOutput ? missingOutput : undefined,
|
|
600
|
+
].filter((note): note is string => Boolean(note));
|
|
601
|
+
if (notes.length === 0) return input.error;
|
|
602
|
+
const context = notes.join("\n");
|
|
603
|
+
const errorLimit = MAX_CHILD_FAILURE_DIAGNOSTIC_CHARS - (context ? context.length + 1 : 0);
|
|
604
|
+
const baseError = input.error || "Subagent failed.";
|
|
605
|
+
return `${baseError.slice(0, Math.max(0, errorLimit))}${context ? `\n${context}` : ""}`;
|
|
549
606
|
}
|
|
550
607
|
|
|
551
608
|
function runPiStreaming(
|
|
@@ -564,13 +621,13 @@ function runPiStreaming(
|
|
|
564
621
|
timeoutMessage?: string,
|
|
565
622
|
registerStop?: (stop: (() => void) | undefined) => void,
|
|
566
623
|
stopMessage?: string,
|
|
567
|
-
registerTurnBudgetAbort?: (abort: ((message: string, state?: TurnBudgetState) => void) | undefined) => void,
|
|
568
624
|
onWriterProcess?: (writer: { state: "none" | "spawning" } | { state: "running"; pid: number }) => void,
|
|
569
625
|
toolTimeoutMs?: number,
|
|
570
626
|
runDeadlineAt?: number,
|
|
571
627
|
orcaProgressTab?: OrcaProgressTab,
|
|
572
628
|
expectedModelForVerification?: string,
|
|
573
629
|
modelVerificationRegistry?: Array<{ provider: string; id: string; fullId: string }>,
|
|
630
|
+
mutationTools?: readonly string[],
|
|
574
631
|
): Promise<RunPiStreamingResult> {
|
|
575
632
|
return new Promise((resolve) => {
|
|
576
633
|
const startedAt = Date.now();
|
|
@@ -610,9 +667,6 @@ function runPiStreaming(
|
|
|
610
667
|
let interrupted = false;
|
|
611
668
|
let timedOut = false;
|
|
612
669
|
let stopped = false;
|
|
613
|
-
let turnBudgetExceeded = false;
|
|
614
|
-
let turnBudgetMessage: string | undefined;
|
|
615
|
-
let turnBudget: TurnBudgetState | undefined;
|
|
616
670
|
let observedMutationAttempt = false;
|
|
617
671
|
let structuredOutputToolInvoked = false;
|
|
618
672
|
let structuredOutputMessageStartIndex: number | undefined;
|
|
@@ -620,8 +674,50 @@ function runPiStreaming(
|
|
|
620
674
|
let currentToolArgs: string | undefined;
|
|
621
675
|
let currentPath: string | undefined;
|
|
622
676
|
let toolCount = 0;
|
|
677
|
+
type ActiveToolCall = { key: string; tool: string; args?: string; path?: string };
|
|
678
|
+
let activeToolSequence = 0;
|
|
679
|
+
const activeToolCalls = new Map<string, ActiveToolCall>();
|
|
680
|
+
const activeToolKeysByName = new Map<string, string[]>();
|
|
681
|
+
const refreshCurrentTool = (): void => {
|
|
682
|
+
const active = [...activeToolCalls.values()].at(-1);
|
|
683
|
+
currentTool = active?.tool;
|
|
684
|
+
currentToolArgs = active?.args;
|
|
685
|
+
currentPath = active?.path;
|
|
686
|
+
};
|
|
687
|
+
const recordActiveToolCall = (event: { toolCallId?: unknown; toolName: string; args?: Record<string, unknown> }): void => {
|
|
688
|
+
const key = toolTimeoutCallKey(event, ++activeToolSequence);
|
|
689
|
+
const active = omitUndefinedProperties({
|
|
690
|
+
key,
|
|
691
|
+
tool: event.toolName,
|
|
692
|
+
args: extractToolArgsPreview(event.args ?? {}),
|
|
693
|
+
path: resolveCurrentPath(event.toolName, event.args),
|
|
694
|
+
});
|
|
695
|
+
activeToolCalls.set(key, active);
|
|
696
|
+
const keys = activeToolKeysByName.get(active.tool) ?? [];
|
|
697
|
+
keys.push(key);
|
|
698
|
+
activeToolKeysByName.set(active.tool, keys);
|
|
699
|
+
refreshCurrentTool();
|
|
700
|
+
};
|
|
701
|
+
const removeActiveToolCall = (event: { toolCallId?: unknown; toolName?: unknown }): void => {
|
|
702
|
+
const key = typeof event.toolCallId === "string" && event.toolCallId.length > 0
|
|
703
|
+
? `id:${event.toolCallId}`
|
|
704
|
+
: typeof event.toolName === "string"
|
|
705
|
+
? activeToolKeysByName.get(event.toolName)?.[0]
|
|
706
|
+
: activeToolCalls.size === 1
|
|
707
|
+
? [...activeToolCalls.keys()][0]
|
|
708
|
+
: undefined;
|
|
709
|
+
if (!key) return;
|
|
710
|
+
const active = activeToolCalls.get(key);
|
|
711
|
+
if (!active) return;
|
|
712
|
+
activeToolCalls.delete(key);
|
|
713
|
+
const keys = activeToolKeysByName.get(active.tool)?.filter((candidate) => candidate !== key) ?? [];
|
|
714
|
+
if (keys.length > 0) activeToolKeysByName.set(active.tool, keys);
|
|
715
|
+
else activeToolKeysByName.delete(active.tool);
|
|
716
|
+
refreshCurrentTool();
|
|
717
|
+
};
|
|
623
718
|
const childWatchdogConfig = decodeChildWatchdogConfig(env?.[CHILD_WATCHDOG_CONFIG_ENV]);
|
|
624
719
|
let childWatchdogState: ChildWatchdogStateSnapshot | undefined;
|
|
720
|
+
const childLifecycleState: ChildLifecycleState = { compactionRetryActive: false };
|
|
625
721
|
let applyChildLifecycle = (_action: ChildLifecycleAction): void => {};
|
|
626
722
|
const updateChildWatchdogState = (snapshot: ChildWatchdogStateSnapshot): void => {
|
|
627
723
|
childWatchdogState = snapshot;
|
|
@@ -672,8 +768,21 @@ function runPiStreaming(
|
|
|
672
768
|
|
|
673
769
|
appendChildEvent(event as unknown as Record<string, unknown>);
|
|
674
770
|
transcriptWriter?.writeChildEvent(event);
|
|
675
|
-
if (event.type === "
|
|
676
|
-
|
|
771
|
+
if (event.type === "compaction_start") compactionStartedReceived = true;
|
|
772
|
+
if (event.type === "compaction_end" && event.willRetry === true) {
|
|
773
|
+
compactionStartedReceived = false;
|
|
774
|
+
afterCompactionSettlement = false;
|
|
775
|
+
}
|
|
776
|
+
if (event.type === "agent_start" || event.type === "auto_retry_start") {
|
|
777
|
+
compactionStartedReceived = false;
|
|
778
|
+
afterCompactionSettlement = false;
|
|
779
|
+
}
|
|
780
|
+
const lifecycleAction = projectChildLifecycle(event, false, childLifecycleState);
|
|
781
|
+
if (event.type === "agent_settled" && lifecycleAction === "start-drain") {
|
|
782
|
+
agentSettledReceived = true;
|
|
783
|
+
afterCompactionSettlement = compactionStartedReceived;
|
|
784
|
+
}
|
|
785
|
+
applyChildLifecycle(lifecycleAction);
|
|
677
786
|
|
|
678
787
|
if (isChildWatchdogStatusEvent(event)) {
|
|
679
788
|
if (!childWatchdogConfig) return;
|
|
@@ -710,29 +819,32 @@ function runPiStreaming(
|
|
|
710
819
|
|
|
711
820
|
if (event.type === "tool_execution_end") {
|
|
712
821
|
clearActiveToolTimeout(event);
|
|
713
|
-
|
|
714
|
-
currentToolArgs = undefined;
|
|
715
|
-
currentPath = undefined;
|
|
822
|
+
removeActiveToolCall(event);
|
|
716
823
|
return;
|
|
717
824
|
}
|
|
718
825
|
|
|
719
826
|
if (event.type === "tool_execution_start" && event.toolName) {
|
|
720
827
|
toolCount += 1;
|
|
721
828
|
armToolTimeout({ toolCallId: (event as { toolCallId?: unknown }).toolCallId, toolName: event.toolName });
|
|
722
|
-
|
|
723
|
-
currentToolArgs = extractToolArgsPreview(event.args ?? {});
|
|
724
|
-
currentPath = resolveCurrentPath(event.toolName, event.args);
|
|
829
|
+
recordActiveToolCall({ toolCallId: (event as { toolCallId?: unknown }).toolCallId, toolName: event.toolName, args: event.args });
|
|
725
830
|
if (event.toolName === "structured_output") {
|
|
726
831
|
structuredOutputToolInvoked = true;
|
|
727
832
|
structuredOutputMessageStartIndex = messages.length;
|
|
728
833
|
}
|
|
729
|
-
observedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args);
|
|
834
|
+
observedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args, mutationTools);
|
|
730
835
|
const toolArgs = extractToolArgsPreview(event.args ?? {});
|
|
731
836
|
writeOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);
|
|
732
837
|
return;
|
|
733
838
|
}
|
|
734
839
|
|
|
735
840
|
if ((event.type === "message_end" || event.type === "tool_result_end") && event.message) {
|
|
841
|
+
if (event.type === "tool_result_end") {
|
|
842
|
+
clearActiveToolTimeout(event);
|
|
843
|
+
removeActiveToolCall({
|
|
844
|
+
toolCallId: (event.message as { toolCallId?: unknown }).toolCallId ?? (event as { toolCallId?: unknown }).toolCallId,
|
|
845
|
+
toolName: (event.message as { toolName?: unknown }).toolName ?? event.toolName,
|
|
846
|
+
});
|
|
847
|
+
}
|
|
736
848
|
messages.push(event.message);
|
|
737
849
|
const text = extractTextFromContent(event.message.content);
|
|
738
850
|
if (text) writeOutputText(text);
|
|
@@ -759,7 +871,11 @@ function runPiStreaming(
|
|
|
759
871
|
if (isTerminalAssistantStop(event.message)) {
|
|
760
872
|
if (!event.message.errorMessage && extractTextFromContent(event.message.content).trim()) assistantError = undefined;
|
|
761
873
|
cleanTerminalAssistantStopReceived ||= !event.message.errorMessage;
|
|
762
|
-
|
|
874
|
+
clearAllToolTimeouts();
|
|
875
|
+
activeToolCalls.clear();
|
|
876
|
+
activeToolKeysByName.clear();
|
|
877
|
+
refreshCurrentTool();
|
|
878
|
+
applyChildLifecycle(projectChildLifecycle(event, true, childLifecycleState));
|
|
763
879
|
}
|
|
764
880
|
}
|
|
765
881
|
};
|
|
@@ -772,11 +888,11 @@ function runPiStreaming(
|
|
|
772
888
|
let forcedTerminationSignal = false;
|
|
773
889
|
let cleanTerminalAssistantStopReceived = false;
|
|
774
890
|
let agentSettledReceived = false;
|
|
891
|
+
let compactionStartedReceived = false;
|
|
892
|
+
let afterCompactionSettlement = false;
|
|
775
893
|
let finalDrainTimer: NodeJS.Timeout | undefined;
|
|
776
894
|
let finalHardKillTimer: NodeJS.Timeout | undefined;
|
|
777
895
|
let watchdogTailTimer: NodeJS.Timeout | undefined;
|
|
778
|
-
let turnBudgetTerminationTimer: NodeJS.Timeout | undefined;
|
|
779
|
-
let turnBudgetHardKillTimer: NodeJS.Timeout | undefined;
|
|
780
896
|
let protocolHardKillTimer: NodeJS.Timeout | undefined;
|
|
781
897
|
let protocolError: ProtocolOutputLimit | undefined;
|
|
782
898
|
let settled = false;
|
|
@@ -897,23 +1013,6 @@ function runPiStreaming(
|
|
|
897
1013
|
if (processTreeController) void processTreeController.terminate();
|
|
898
1014
|
else trySignalChild(child, "SIGTERM");
|
|
899
1015
|
});
|
|
900
|
-
registerTurnBudgetAbort?.((message, state) => {
|
|
901
|
-
if (settled || timedOut || stopped || turnBudgetExceeded) return;
|
|
902
|
-
turnBudgetExceeded = true;
|
|
903
|
-
turnBudgetMessage = message;
|
|
904
|
-
turnBudget = state;
|
|
905
|
-
interrupted = false;
|
|
906
|
-
error = message;
|
|
907
|
-
trySignalChild(child, "SIGINT");
|
|
908
|
-
turnBudgetTerminationTimer = setTimeout(() => {
|
|
909
|
-
if (!settled && !timedOut && !stopped) trySignalChild(child, "SIGTERM");
|
|
910
|
-
}, 1000);
|
|
911
|
-
turnBudgetTerminationTimer.unref?.();
|
|
912
|
-
turnBudgetHardKillTimer = setTimeout(() => {
|
|
913
|
-
if (!settled && !timedOut && !stopped) trySignalChild(child, "SIGKILL");
|
|
914
|
-
}, 4000);
|
|
915
|
-
turnBudgetHardKillTimer.unref?.();
|
|
916
|
-
});
|
|
917
1016
|
const clearDrainTimers = () => {
|
|
918
1017
|
clearAllToolTimeouts();
|
|
919
1018
|
if (finalDrainTimer) {
|
|
@@ -925,14 +1024,6 @@ function runPiStreaming(
|
|
|
925
1024
|
finalHardKillTimer = undefined;
|
|
926
1025
|
}
|
|
927
1026
|
clearWatchdogTailTimer();
|
|
928
|
-
if (turnBudgetTerminationTimer) {
|
|
929
|
-
clearTimeout(turnBudgetTerminationTimer);
|
|
930
|
-
turnBudgetTerminationTimer = undefined;
|
|
931
|
-
}
|
|
932
|
-
if (turnBudgetHardKillTimer) {
|
|
933
|
-
clearTimeout(turnBudgetHardKillTimer);
|
|
934
|
-
turnBudgetHardKillTimer = undefined;
|
|
935
|
-
}
|
|
936
1027
|
if (protocolHardKillTimer) {
|
|
937
1028
|
clearTimeout(protocolHardKillTimer);
|
|
938
1029
|
protocolHardKillTimer = undefined;
|
|
@@ -1000,7 +1091,6 @@ function runPiStreaming(
|
|
|
1000
1091
|
registerInterrupt?.(undefined);
|
|
1001
1092
|
registerTimeout?.(undefined);
|
|
1002
1093
|
registerStop?.(undefined);
|
|
1003
|
-
registerTurnBudgetAbort?.(undefined);
|
|
1004
1094
|
clearDrainTimers();
|
|
1005
1095
|
clearStdioGuard();
|
|
1006
1096
|
stdoutReader.end();
|
|
@@ -1010,32 +1100,32 @@ function runPiStreaming(
|
|
|
1010
1100
|
const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
|
|
1011
1101
|
const finalError = error ?? assistantError;
|
|
1012
1102
|
const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
|
|
1103
|
+
const forcedDrainAfterEmptyTerminal = forcedDrainAfterFinalSuccess && hasEmptyTerminalAssistantResponse(messages);
|
|
1104
|
+
const forcedDrainError = forcedDrainAfterEmptyTerminal && stderr.trim()
|
|
1105
|
+
? stderr.trim()
|
|
1106
|
+
: undefined;
|
|
1013
1107
|
const signalError = isUnexplainedProcessSignal({
|
|
1014
1108
|
processSignal: signal,
|
|
1015
1109
|
interrupted,
|
|
1016
1110
|
timedOut,
|
|
1017
1111
|
stopped,
|
|
1018
|
-
|
|
1019
|
-
forcedDrainAfterFinalSuccess,
|
|
1112
|
+
forcedDrainAfterFinalSuccess: forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal,
|
|
1020
1113
|
}) ? formatProcessSignalError(signal!) : undefined;
|
|
1021
1114
|
resolve(omitUndefinedProperties({
|
|
1022
1115
|
stderr,
|
|
1023
|
-
exitCode: timedOut || stopped ? 1 :
|
|
1116
|
+
exitCode: timedOut || stopped ? 1 : interrupted || (forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal) ? 0 : forcedTerminationSignal || signal ? (exitCode ?? 1) : exitCode,
|
|
1024
1117
|
messages,
|
|
1025
1118
|
usage,
|
|
1026
1119
|
toolCount,
|
|
1027
1120
|
durationMs: Date.now() - startedAt,
|
|
1028
1121
|
model,
|
|
1029
|
-
error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") :
|
|
1122
|
+
error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : interrupted || (forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal) ? undefined : finalError ?? forcedDrainError ?? signalError,
|
|
1030
1123
|
protocolError,
|
|
1031
1124
|
finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput,
|
|
1032
1125
|
outputState: finalOutput.trim() ? "present" : "absent",
|
|
1033
1126
|
interrupted,
|
|
1034
1127
|
timedOut,
|
|
1035
1128
|
stopped,
|
|
1036
|
-
turnBudget,
|
|
1037
|
-
turnBudgetExceeded,
|
|
1038
|
-
wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined,
|
|
1039
1129
|
observedMutationAttempt,
|
|
1040
1130
|
structuredOutputToolInvoked,
|
|
1041
1131
|
structuredOutputMessageStartIndex,
|
|
@@ -1047,6 +1137,7 @@ function runPiStreaming(
|
|
|
1047
1137
|
currentTool,
|
|
1048
1138
|
currentToolArgs,
|
|
1049
1139
|
currentPath,
|
|
1140
|
+
afterCompactionSettlement: afterCompactionSettlement || undefined,
|
|
1050
1141
|
}));
|
|
1051
1142
|
});
|
|
1052
1143
|
|
|
@@ -1060,7 +1151,6 @@ function runPiStreaming(
|
|
|
1060
1151
|
registerInterrupt?.(undefined);
|
|
1061
1152
|
registerTimeout?.(undefined);
|
|
1062
1153
|
registerStop?.(undefined);
|
|
1063
|
-
registerTurnBudgetAbort?.(undefined);
|
|
1064
1154
|
clearDrainTimers();
|
|
1065
1155
|
clearStdioGuard();
|
|
1066
1156
|
stdoutReader.end();
|
|
@@ -1069,7 +1159,7 @@ function runPiStreaming(
|
|
|
1069
1159
|
const stderr = stderrTail.text();
|
|
1070
1160
|
const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
|
|
1071
1161
|
const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
|
|
1072
|
-
resolve(omitUndefinedProperties({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, model, error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") :
|
|
1162
|
+
resolve(omitUndefinedProperties({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, model, error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : 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, observedMutationAttempt, structuredOutputToolInvoked, structuredOutputMessageStartIndex, watchdog: childWatchdogState, processInstanceId, processTree: { state: "unknown", reason: "verification-failed", diagnostic: spawnErrorMessage } }));
|
|
1073
1163
|
});
|
|
1074
1164
|
});
|
|
1075
1165
|
}
|
|
@@ -1204,7 +1294,6 @@ interface SingleStepContext {
|
|
|
1204
1294
|
registerInterrupt?: (interrupt: (() => void) | undefined) => void;
|
|
1205
1295
|
registerTimeout?: (interrupt: (() => void) | undefined) => void;
|
|
1206
1296
|
registerStop?: (stop: (() => void) | undefined) => void;
|
|
1207
|
-
registerTurnBudgetAbort?: (abort: ((message: string, state?: TurnBudgetState) => void) | undefined) => void;
|
|
1208
1297
|
timeoutSignal?: AbortSignal;
|
|
1209
1298
|
stopSignal?: AbortSignal;
|
|
1210
1299
|
timeoutMessage?: string;
|
|
@@ -1213,18 +1302,18 @@ interface SingleStepContext {
|
|
|
1213
1302
|
toolTimeoutMs?: number;
|
|
1214
1303
|
/** Effective step deadline (Date.now() + effective timeout) when a run budget exists. */
|
|
1215
1304
|
deadlineAt?: number;
|
|
1216
|
-
turnBudget?: ResolvedTurnBudget;
|
|
1217
1305
|
childIntercomTarget?: string;
|
|
1218
1306
|
orchestratorIntercomTarget?: string;
|
|
1219
1307
|
nestedRoute?: NestedRouteInfo;
|
|
1220
1308
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
1221
1309
|
runFanoutBudget?: RunFanoutBudgetDescriptor;
|
|
1222
|
-
onAttemptStart?: (attempt: { model?: string; thinking?: string }) => void;
|
|
1310
|
+
onAttemptStart?: (attempt: { model?: string; thinking?: string; contextLimit?: number }) => void;
|
|
1223
1311
|
onChildEvent?: (event: ChildEvent) => void;
|
|
1224
1312
|
onWriterProcess?: (writer: { state: "none" | "spawning" } | { state: "running"; pid: number }) => void;
|
|
1225
1313
|
onExternalProcess?: (process: ExternalProcessStatus) => void;
|
|
1226
1314
|
onExternalJob?: (status: ExternalJobStatus) => void;
|
|
1227
1315
|
skipAcceptance?: () => boolean;
|
|
1316
|
+
usageBudgetExhausted?: () => boolean;
|
|
1228
1317
|
/** False when sibling work in the same Git worktree could have caused the tracked diff. */
|
|
1229
1318
|
trackedMutationEvidenceForCompletionGuard?: boolean;
|
|
1230
1319
|
orcaProgressTab?: OrcaProgressTab;
|
|
@@ -1293,10 +1382,13 @@ async function runSingleStepInner(
|
|
|
1293
1382
|
modelAttempts: imported.modelAttempts,
|
|
1294
1383
|
contextOverflow: imported.contextOverflow,
|
|
1295
1384
|
totalCost: imported.totalCost,
|
|
1385
|
+
usage: imported.usage,
|
|
1296
1386
|
structuredOutput: timedOut || stopped ? undefined : imported.structuredOutput,
|
|
1297
1387
|
structuredOutputPath: timedOut || stopped ? undefined : imported.structuredOutputPath,
|
|
1298
1388
|
structuredOutputSchemaPath: timedOut || stopped ? undefined : imported.structuredOutputSchemaPath,
|
|
1299
1389
|
acceptance: timedOut || stopped ? undefined : imported.acceptance,
|
|
1390
|
+
execution: timedOut || stopped ? undefined : imported.execution,
|
|
1391
|
+
effects: timedOut || stopped ? undefined : imported.effects,
|
|
1300
1392
|
});
|
|
1301
1393
|
} finally {
|
|
1302
1394
|
ctx.registerTimeout?.(undefined);
|
|
@@ -1315,12 +1407,15 @@ async function runSingleStepInner(
|
|
|
1315
1407
|
if (!step.runner) {
|
|
1316
1408
|
resolvedTaskToolPlan = resolvePiLaunchToolPlan(omitUndefinedProperties({
|
|
1317
1409
|
tools: step.tools,
|
|
1410
|
+
allowNestedSubagents: step.allowNestedSubagents,
|
|
1318
1411
|
extensions: step.extensions,
|
|
1319
1412
|
subagentOnlyExtensions: step.subagentOnlyExtensions,
|
|
1320
1413
|
fast: step.fast,
|
|
1321
1414
|
model: step.model,
|
|
1322
1415
|
modelCandidates: step.modelCandidates,
|
|
1323
1416
|
mcpDirectTools: step.mcpDirectTools,
|
|
1417
|
+
mcpConfig: step.mcpConfig,
|
|
1418
|
+
runtimeServerNames: step.runtimeServerNames,
|
|
1324
1419
|
cwd: step.cwd ?? ctx.cwd,
|
|
1325
1420
|
requireReadTool: Boolean(step.skills?.length),
|
|
1326
1421
|
structuredOutput: Boolean(effectiveStructuredOutput),
|
|
@@ -1351,6 +1446,9 @@ async function runSingleStepInner(
|
|
|
1351
1446
|
});
|
|
1352
1447
|
}
|
|
1353
1448
|
}
|
|
1449
|
+
// Derive from the pre-acceptance task so internal acceptance/recovery
|
|
1450
|
+
// instructions never leak into the display name.
|
|
1451
|
+
const childSessionName = step.sessionName ?? deriveChildSessionName({ agent: step.agent, task, label: step.label });
|
|
1354
1452
|
if (step.effectiveAcceptance) {
|
|
1355
1453
|
const acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance, { reportOptional: isAgentContractV1(step.agentContract), structuredOutput: Boolean(step.structuredOutput?.acceptanceReportPath) });
|
|
1356
1454
|
if (acceptancePrompt) task = `${task}\n${acceptancePrompt}`;
|
|
@@ -1381,21 +1479,29 @@ async function runSingleStepInner(
|
|
|
1381
1479
|
transcriptWriter?.writeInitialUserMessage(`${PROMPT_REDACTED}; live Prompt Audit only.`);
|
|
1382
1480
|
|
|
1383
1481
|
if (step.runner?.type === "external-cli") {
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
command: step.runner.command,
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1482
|
+
const externalCwd = step.cwd ?? ctx.cwd;
|
|
1483
|
+
const adapterLaunch = step.runner.adapter === "codex-exec" || step.runner.adapter === "codex-exec-writer"
|
|
1484
|
+
? resolveCodexExecLaunch({ adapter: step.runner.adapter, command: step.runner.command, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex })
|
|
1485
|
+
: step.runner.adapter === "claude-code" || step.runner.adapter === "claude-code-writer"
|
|
1486
|
+
? resolveClaudeCodeLaunch({ adapter: step.runner.adapter, command: step.runner.command })
|
|
1487
|
+
: step.runner.adapter === "cursor-agent" || step.runner.adapter === "cursor-agent-writer"
|
|
1488
|
+
? resolveCursorAgentLaunch({ adapter: step.runner.adapter, command: step.runner.command, cwd: externalCwd, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex })
|
|
1489
|
+
: undefined;
|
|
1490
|
+
const runner = resolveExternalCliRunnerStatus({ ...step.runner, ...(adapterLaunch ? { args: adapterLaunch.args } : {}) });
|
|
1391
1491
|
const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
|
|
1392
1492
|
const external = await runExternalCli(omitUndefinedProperties({
|
|
1393
|
-
command: runner.command,
|
|
1394
|
-
args: runner.args,
|
|
1395
|
-
cwd:
|
|
1493
|
+
command: adapterLaunch?.command ?? runner.command,
|
|
1494
|
+
args: adapterLaunch?.args ?? runner.args,
|
|
1495
|
+
cwd: externalCwd,
|
|
1396
1496
|
prompt: buildExternalCliPrompt(step.systemPrompt ?? "", task),
|
|
1397
1497
|
asyncDir: path.dirname(ctx.outputFile),
|
|
1398
1498
|
stepIndex: ctx.flatIndex,
|
|
1499
|
+
environment: adapterLaunch?.environment,
|
|
1500
|
+
preflight: adapterLaunch?.preflight,
|
|
1501
|
+
parser: adapterLaunch?.parser,
|
|
1502
|
+
finalOutputPath: adapterLaunch?.finalOutputPath,
|
|
1503
|
+
promptFilePath: adapterLaunch?.promptFilePath,
|
|
1504
|
+
temporaryDirectories: adapterLaunch?.temporaryDirectories,
|
|
1399
1505
|
registerTimeout: ctx.registerTimeout,
|
|
1400
1506
|
registerStop: ctx.registerStop,
|
|
1401
1507
|
timeoutMessage: ctx.timeoutMessage,
|
|
@@ -1406,14 +1512,18 @@ async function runSingleStepInner(
|
|
|
1406
1512
|
}));
|
|
1407
1513
|
try { fs.writeFileSync(ctx.outputFile, external.output, "utf-8"); } catch { /* Observability output is best-effort. */ }
|
|
1408
1514
|
const resolvedOutput = step.outputPath && external.exitCode === 0
|
|
1409
|
-
? resolveSingleOutput(step.outputPath, external.output, outputSnapshot)
|
|
1515
|
+
? resolveSingleOutput(step.outputPath, external.output, outputSnapshot, step.outputClaimPath)
|
|
1410
1516
|
: { fullOutput: external.output };
|
|
1411
1517
|
const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, resolvedOutput.fullOutput) : undefined;
|
|
1518
|
+
const exitCode = resolvedOutput.fatalError ? 1 : external.exitCode;
|
|
1519
|
+
const error = resolvedOutput.fatalError && resolvedOutput.saveError
|
|
1520
|
+
? external.error ? `${external.error}\n${resolvedOutput.saveError}` : resolvedOutput.saveError
|
|
1521
|
+
: external.error;
|
|
1412
1522
|
const finalizedOutput = finalizeSingleOutput(omitUndefinedProperties({
|
|
1413
1523
|
fullOutput: resolvedOutput.fullOutput,
|
|
1414
1524
|
outputPath: step.outputPath,
|
|
1415
1525
|
outputMode: step.outputMode,
|
|
1416
|
-
exitCode:
|
|
1526
|
+
exitCode: exitCode ?? 1,
|
|
1417
1527
|
savedPath: resolvedOutput.savedPath,
|
|
1418
1528
|
outputReference,
|
|
1419
1529
|
saveError: resolvedOutput.saveError,
|
|
@@ -1428,16 +1538,17 @@ async function runSingleStepInner(
|
|
|
1428
1538
|
: {};
|
|
1429
1539
|
return omitUndefinedProperties({
|
|
1430
1540
|
agent: step.agent,
|
|
1541
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
1431
1542
|
context: step.context,
|
|
1432
1543
|
output: finalizedOutput.displayOutput,
|
|
1433
1544
|
outputState: external.output.trim() ? "present" : "absent",
|
|
1434
|
-
exitCode
|
|
1435
|
-
error
|
|
1545
|
+
exitCode,
|
|
1546
|
+
error,
|
|
1436
1547
|
timedOut: external.timedOut,
|
|
1437
1548
|
stopped: external.stopped,
|
|
1438
1549
|
processSignal: external.processSignal,
|
|
1439
1550
|
artifactPaths,
|
|
1440
|
-
outputSaveError: artifactErrors.outputSaveError,
|
|
1551
|
+
outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
|
|
1441
1552
|
metadataSaveError: artifactErrors.metadataSaveError,
|
|
1442
1553
|
runner,
|
|
1443
1554
|
externalProcess: external.externalProcess,
|
|
@@ -1471,14 +1582,18 @@ async function runSingleStepInner(
|
|
|
1471
1582
|
}));
|
|
1472
1583
|
try { fs.writeFileSync(ctx.outputFile, external.output, "utf-8"); } catch { /* Observability output is best-effort. */ }
|
|
1473
1584
|
const resolvedOutput = step.outputPath && external.exitCode === 0
|
|
1474
|
-
? resolveSingleOutput(step.outputPath, external.output, outputSnapshot)
|
|
1585
|
+
? resolveSingleOutput(step.outputPath, external.output, outputSnapshot, step.outputClaimPath)
|
|
1475
1586
|
: { fullOutput: external.output };
|
|
1476
1587
|
const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, resolvedOutput.fullOutput) : undefined;
|
|
1588
|
+
const exitCode = resolvedOutput.fatalError ? 1 : external.exitCode;
|
|
1589
|
+
const error = resolvedOutput.fatalError && resolvedOutput.saveError
|
|
1590
|
+
? external.error ? `${external.error}\n${resolvedOutput.saveError}` : resolvedOutput.saveError
|
|
1591
|
+
: external.error;
|
|
1477
1592
|
const finalizedOutput = finalizeSingleOutput(omitUndefinedProperties({
|
|
1478
1593
|
fullOutput: resolvedOutput.fullOutput,
|
|
1479
1594
|
outputPath: step.outputPath,
|
|
1480
1595
|
outputMode: step.outputMode,
|
|
1481
|
-
exitCode:
|
|
1596
|
+
exitCode: exitCode ?? 1,
|
|
1482
1597
|
savedPath: resolvedOutput.savedPath,
|
|
1483
1598
|
outputReference,
|
|
1484
1599
|
saveError: resolvedOutput.saveError,
|
|
@@ -1493,21 +1608,26 @@ async function runSingleStepInner(
|
|
|
1493
1608
|
: {};
|
|
1494
1609
|
return omitUndefinedProperties({
|
|
1495
1610
|
agent: step.agent,
|
|
1611
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
1496
1612
|
context: step.context,
|
|
1497
1613
|
output: finalizedOutput.displayOutput,
|
|
1498
1614
|
outputState: external.output.trim() ? "present" : "absent",
|
|
1499
|
-
exitCode
|
|
1500
|
-
error
|
|
1615
|
+
exitCode,
|
|
1616
|
+
error,
|
|
1501
1617
|
timedOut: external.timedOut,
|
|
1502
1618
|
stopped: external.stopped,
|
|
1503
1619
|
artifactPaths,
|
|
1504
|
-
outputSaveError: artifactErrors.outputSaveError,
|
|
1620
|
+
outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
|
|
1505
1621
|
metadataSaveError: artifactErrors.metadataSaveError,
|
|
1506
1622
|
runner,
|
|
1507
1623
|
externalJob: external.externalJob,
|
|
1508
1624
|
});
|
|
1509
1625
|
}
|
|
1510
1626
|
|
|
1627
|
+
const effectiveCwd = step.cwd ?? ctx.cwd;
|
|
1628
|
+
const cwdError = preflightLaunchCwd(step.requestedCwd ?? effectiveCwd, effectiveCwd);
|
|
1629
|
+
if (cwdError) return { agent: step.agent, output: cwdError, error: cwdError, exitCode: 1, context: step.context };
|
|
1630
|
+
|
|
1511
1631
|
const candidates = step.modelCandidates !== undefined
|
|
1512
1632
|
? step.modelCandidates.length > 0 ? step.modelCandidates : [undefined]
|
|
1513
1633
|
: step.model
|
|
@@ -1526,7 +1646,6 @@ async function runSingleStepInner(
|
|
|
1526
1646
|
let structuredAcceptanceReport: unknown;
|
|
1527
1647
|
let structuredAcceptanceReportError: string | undefined;
|
|
1528
1648
|
let completionGuardTriggeredFinal = false;
|
|
1529
|
-
let turnBudget = ctx.turnBudget ? initialTurnBudgetState(ctx.turnBudget) : undefined;
|
|
1530
1649
|
let toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;
|
|
1531
1650
|
let toolBudgetBlocked = false;
|
|
1532
1651
|
let actualLaunchContractDigest = step.launchContractDigest;
|
|
@@ -1540,8 +1659,12 @@ async function runSingleStepInner(
|
|
|
1540
1659
|
let taskDeliveryOverride: SubagentTaskDelivery | undefined;
|
|
1541
1660
|
let contextOverflow = false;
|
|
1542
1661
|
let launchWarningsEmitted = false;
|
|
1662
|
+
let abortRecoveryAttempted = false;
|
|
1663
|
+
let nextAttemptTask = task;
|
|
1543
1664
|
modelAttemptsLoop: while (modelIndex < candidates.length) {
|
|
1544
1665
|
if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
|
|
1666
|
+
const recoveringAbort = abortRecoveryAttempted;
|
|
1667
|
+
const attemptTask = nextAttemptTask;
|
|
1545
1668
|
const candidate = candidates[modelIndex];
|
|
1546
1669
|
const expectedModelForVerification = candidate && !(step.skipPrimaryModelVerification && modelIndex === 0) ? candidate : undefined;
|
|
1547
1670
|
try {
|
|
@@ -1550,7 +1673,11 @@ async function runSingleStepInner(
|
|
|
1550
1673
|
const message = error instanceof Error ? error.message : String(error);
|
|
1551
1674
|
return omitUndefinedProperties({ agent: step.agent, output: message, error: message, exitCode: 1, context: step.context, thinkingCeiling: step.thinkingCeiling });
|
|
1552
1675
|
}
|
|
1553
|
-
ctx.onAttemptStart?.(omitUndefinedProperties({
|
|
1676
|
+
ctx.onAttemptStart?.(omitUndefinedProperties({
|
|
1677
|
+
model: candidate,
|
|
1678
|
+
thinking: resolveEffectiveThinking(candidate, step.thinking),
|
|
1679
|
+
contextLimit: findModelInfo(candidate, step.modelVerificationRegistry)?.contextWindow,
|
|
1680
|
+
}));
|
|
1554
1681
|
const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
|
|
1555
1682
|
if (effectiveStructuredOutput) {
|
|
1556
1683
|
try {
|
|
@@ -1572,27 +1699,32 @@ async function runSingleStepInner(
|
|
|
1572
1699
|
const { args, env, tempDir, toolDiagnosticPath, runtimeAcknowledgedExtensionsPath, capabilityAudit: attemptCapabilityAudit, warnings } = buildPiArgs(omitUndefinedProperties({
|
|
1573
1700
|
parentSessionId: step.parentSessionId,
|
|
1574
1701
|
baseArgs: ["--mode", "json", "-p"],
|
|
1575
|
-
task,
|
|
1702
|
+
task: attemptTask,
|
|
1576
1703
|
taskDelivery: taskDeliveryOverride,
|
|
1577
1704
|
sessionEnabled,
|
|
1578
1705
|
sessionDir,
|
|
1579
1706
|
sessionFile: step.sessionFile,
|
|
1580
1707
|
model: candidate,
|
|
1581
1708
|
inheritProjectContext: step.inheritProjectContext,
|
|
1709
|
+
inheritGlobalContext: step.inheritGlobalContext,
|
|
1582
1710
|
inheritSkills: step.inheritSkills,
|
|
1583
1711
|
requireReadTool: Boolean(step.skills?.length),
|
|
1584
1712
|
tools: step.tools,
|
|
1713
|
+
allowNestedSubagents: step.allowNestedSubagents,
|
|
1585
1714
|
extensions: step.extensions,
|
|
1586
1715
|
subagentOnlyExtensions: step.subagentOnlyExtensions,
|
|
1587
1716
|
fast: step.fast,
|
|
1588
1717
|
modelCandidates: step.modelCandidates,
|
|
1589
|
-
systemPrompt:
|
|
1718
|
+
systemPrompt: step.systemPrompt ?? "",
|
|
1590
1719
|
systemPromptMode: step.systemPromptMode,
|
|
1591
1720
|
mcpDirectTools: step.mcpDirectTools,
|
|
1721
|
+
mcpConfig: step.mcpConfig,
|
|
1722
|
+
runtimeServerNames: step.runtimeServerNames,
|
|
1592
1723
|
capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
|
|
1593
1724
|
cwd: step.cwd ?? ctx.cwd,
|
|
1594
1725
|
promptFileStem: step.agent,
|
|
1595
1726
|
intercomSessionName: ctx.childIntercomTarget,
|
|
1727
|
+
sessionName: childSessionName,
|
|
1596
1728
|
orchestratorIntercomTarget: ctx.orchestratorIntercomTarget,
|
|
1597
1729
|
runId: ctx.id,
|
|
1598
1730
|
childAgentName: step.agent,
|
|
@@ -1616,6 +1748,7 @@ async function runSingleStepInner(
|
|
|
1616
1748
|
: undefined,
|
|
1617
1749
|
childWatchdog,
|
|
1618
1750
|
waitToolEnabled: step.waitToolEnabled,
|
|
1751
|
+
waitToolDefaultTimeoutMs: step.waitToolDefaultTimeoutMs,
|
|
1619
1752
|
thinkingCeiling: step.thinkingCeiling,
|
|
1620
1753
|
extensionBindings,
|
|
1621
1754
|
}));
|
|
@@ -1626,12 +1759,15 @@ async function runSingleStepInner(
|
|
|
1626
1759
|
if (step.definitionDigest) {
|
|
1627
1760
|
const toolPlan = resolvedTaskToolPlan ?? resolvePiLaunchToolPlan(omitUndefinedProperties({
|
|
1628
1761
|
tools: step.tools,
|
|
1762
|
+
allowNestedSubagents: step.allowNestedSubagents,
|
|
1629
1763
|
extensions: step.extensions,
|
|
1630
1764
|
subagentOnlyExtensions: step.subagentOnlyExtensions,
|
|
1631
1765
|
fast: step.fast,
|
|
1632
1766
|
model: step.model,
|
|
1633
1767
|
modelCandidates: step.modelCandidates,
|
|
1634
1768
|
mcpDirectTools: step.mcpDirectTools,
|
|
1769
|
+
mcpConfig: step.mcpConfig,
|
|
1770
|
+
runtimeServerNames: step.runtimeServerNames,
|
|
1635
1771
|
cwd: step.cwd ?? ctx.cwd,
|
|
1636
1772
|
requireReadTool: Boolean(step.skills?.length),
|
|
1637
1773
|
structuredOutput: Boolean(effectiveStructuredOutput),
|
|
@@ -1648,9 +1784,10 @@ async function runSingleStepInner(
|
|
|
1648
1784
|
...(step.fast !== undefined ? { fast: step.fast } : {}),
|
|
1649
1785
|
...(resolveEffectiveThinking(candidate, step.thinking) ? { thinking: resolveEffectiveThinking(candidate, step.thinking) } : {}),
|
|
1650
1786
|
...(step.thinkingCeiling ? { thinkingCeiling: step.thinkingCeiling } : {}),
|
|
1651
|
-
systemPrompt:
|
|
1787
|
+
systemPrompt: step.systemPrompt ?? "",
|
|
1652
1788
|
systemPromptMode: step.systemPromptMode,
|
|
1653
1789
|
inheritProjectContext: step.inheritProjectContext,
|
|
1790
|
+
inheritGlobalContext: step.inheritGlobalContext,
|
|
1654
1791
|
inheritSkills: step.inheritSkills,
|
|
1655
1792
|
skills: step.skills,
|
|
1656
1793
|
tools: toolPlan.effectiveToolAllowlist,
|
|
@@ -1680,13 +1817,13 @@ async function runSingleStepInner(
|
|
|
1680
1817
|
ctx.timeoutMessage,
|
|
1681
1818
|
ctx.registerStop,
|
|
1682
1819
|
ctx.stopMessage,
|
|
1683
|
-
ctx.registerTurnBudgetAbort,
|
|
1684
1820
|
ctx.onWriterProcess,
|
|
1685
1821
|
ctx.toolTimeoutMs,
|
|
1686
1822
|
ctx.deadlineAt,
|
|
1687
1823
|
ctx.orcaProgressTab,
|
|
1688
1824
|
expectedModelForVerification,
|
|
1689
1825
|
step.modelVerificationRegistry,
|
|
1826
|
+
step.mutationTools,
|
|
1690
1827
|
);
|
|
1691
1828
|
if (run.processCloseObservedAt !== undefined) {
|
|
1692
1829
|
writerProcesses.push({
|
|
@@ -1699,35 +1836,29 @@ async function runSingleStepInner(
|
|
|
1699
1836
|
processTree: run.processTree,
|
|
1700
1837
|
});
|
|
1701
1838
|
}
|
|
1702
|
-
if (run.turnBudget) turnBudget = run.turnBudget;
|
|
1703
|
-
else if (ctx.turnBudget) {
|
|
1704
|
-
const assistantMessages = run.messages.filter((message) => message.role === "assistant");
|
|
1705
|
-
const turnCount = assistantMessages.length;
|
|
1706
|
-
const lastAssistantMessage = assistantMessages.at(-1);
|
|
1707
|
-
if (turnCount > 0 && turnCount < ctx.turnBudget.maxTurns) {
|
|
1708
|
-
turnBudget = { ...ctx.turnBudget, outcome: "within-budget", turnCount };
|
|
1709
|
-
} else if (turnCount >= ctx.turnBudget.maxTurns) {
|
|
1710
|
-
const decision = turnBudgetDecision(
|
|
1711
|
-
ctx.turnBudget,
|
|
1712
|
-
turnCount,
|
|
1713
|
-
lastAssistantMessage ? isTerminalAssistantStop(lastAssistantMessage) : false,
|
|
1714
|
-
lastAssistantMessage ? assistantStartsToolCall(lastAssistantMessage) : false,
|
|
1715
|
-
);
|
|
1716
|
-
turnBudget = decision === "defer"
|
|
1717
|
-
? turnBudgetDeferredState(ctx.turnBudget, turnCount)
|
|
1718
|
-
: turnBudgetState(ctx.turnBudget, turnCount, decision === "abort");
|
|
1719
|
-
}
|
|
1720
|
-
}
|
|
1721
1839
|
const toolAvailabilityError = run.exitCode === 0 && !run.error
|
|
1722
1840
|
? readChildToolDiagnosticError(toolDiagnosticPath)
|
|
1723
1841
|
: undefined;
|
|
1724
1842
|
const runtimeAcknowledgedExtensions = readRuntimeAcknowledgedExtensions(runtimeAcknowledgedExtensionsPath);
|
|
1725
1843
|
cleanupTempDir(tempDir);
|
|
1844
|
+
const midToolExitError = run.currentTool
|
|
1845
|
+
&& isOrdinaryToolForMidToolExit(run.currentTool)
|
|
1846
|
+
&& !run.interrupted
|
|
1847
|
+
&& !run.timedOut
|
|
1848
|
+
&& !run.stopped
|
|
1849
|
+
&& !run.protocolError
|
|
1850
|
+
&& !toolAvailabilityError
|
|
1851
|
+
? formatMidToolExitError({
|
|
1852
|
+
toolName: run.currentTool,
|
|
1853
|
+
exitCode: run.exitCode,
|
|
1854
|
+
processSignal: run.processSignal,
|
|
1855
|
+
})
|
|
1856
|
+
: undefined;
|
|
1726
1857
|
|
|
1727
1858
|
let structuredOutput: unknown;
|
|
1728
1859
|
let structuredError: string | undefined;
|
|
1729
1860
|
let validatedStructuredOutput = false;
|
|
1730
|
-
if (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError) {
|
|
1861
|
+
if (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError) {
|
|
1731
1862
|
if (!run.structuredOutputToolInvoked) {
|
|
1732
1863
|
structuredError = MISSING_STRUCTURED_OUTPUT_CALL_ERROR;
|
|
1733
1864
|
} else {
|
|
@@ -1749,51 +1880,58 @@ async function runSingleStepInner(
|
|
|
1749
1880
|
const errorMessages = validatedStructuredOutput
|
|
1750
1881
|
? run.messages.slice(run.structuredOutputMessageStartIndex ?? run.messages.length)
|
|
1751
1882
|
: run.messages;
|
|
1752
|
-
const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError
|
|
1883
|
+
const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError
|
|
1753
1884
|
? detectSubagentError(errorMessages)
|
|
1754
1885
|
: null;
|
|
1886
|
+
const terminalEmptyAfterUsefulWork = !validatedStructuredOutput
|
|
1887
|
+
&& hasEmptyTerminalAssistantResponse(run.messages)
|
|
1888
|
+
&& (run.toolCount > 0 || Boolean(run.finalOutput.trim()));
|
|
1755
1889
|
const emptyOutputError = run.exitCode === 0
|
|
1756
1890
|
&& !run.error
|
|
1757
1891
|
&& !toolAvailabilityError
|
|
1758
1892
|
&& !structuredError
|
|
1759
|
-
&& !run.finalOutput.trim()
|
|
1760
1893
|
&& !validatedStructuredOutput
|
|
1894
|
+
&& (!run.finalOutput.trim() || terminalEmptyAfterUsefulWork)
|
|
1761
1895
|
&& (!hiddenError?.hasError || hasEmptyTerminalAssistantResponse(run.messages))
|
|
1762
|
-
?
|
|
1896
|
+
? formatEmptyTerminalAssistantResponseError(run.messages)
|
|
1763
1897
|
: undefined;
|
|
1764
1898
|
const completionGuardEnabled = isAgentContractV1(step.agentContract) ? step.completionGuard === true : step.completionGuard !== false;
|
|
1765
1899
|
const completionToolPlan = resolvedTaskToolPlan;
|
|
1900
|
+
const completionTools = completionToolPlan ? (completionToolPlan.explicitToolAllowlist ? completionToolPlan.effectiveToolAllowlist : undefined) : step.tools;
|
|
1766
1901
|
const mutationEvidence = collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
|
|
1767
1902
|
finalMutationEvidence = mutationEvidence;
|
|
1768
1903
|
const completionMutationEvidence = ctx.trackedMutationEvidenceForCompletionGuard === false ? undefined : mutationEvidence;
|
|
1769
|
-
const completionGuard = run.exitCode === 0 && !run.error && !structuredError && !hiddenError?.hasError && !emptyOutputError && completionGuardEnabled
|
|
1904
|
+
const completionGuard = run.exitCode === 0 && !run.error && !structuredError && !hiddenError?.hasError && !midToolExitError && !emptyOutputError && completionGuardEnabled
|
|
1770
1905
|
? evaluateCompletionMutationGuard(omitUndefinedProperties({
|
|
1771
1906
|
agent: step.agent,
|
|
1772
1907
|
task: taskForCompletionGuard,
|
|
1773
1908
|
messages: run.messages,
|
|
1774
|
-
tools:
|
|
1909
|
+
tools: completionTools,
|
|
1775
1910
|
mcpDirectTools: completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools,
|
|
1911
|
+
mutationTools: step.mutationTools,
|
|
1776
1912
|
toolAvailabilityError,
|
|
1777
1913
|
mutationEvidence: completionMutationEvidence,
|
|
1778
1914
|
}))
|
|
1779
1915
|
: undefined;
|
|
1780
1916
|
const mutationAttemptObserved = run.observedMutationAttempt === true || completionMutationEvidence?.attemptedMutation === true;
|
|
1781
|
-
const
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
:
|
|
1793
|
-
|
|
1794
|
-
|
|
1917
|
+
const completionEvidence = planCompletionEvidence({
|
|
1918
|
+
guard: completionGuard,
|
|
1919
|
+
completionGuardEnabled,
|
|
1920
|
+
mutationCapable: hasMutationToolCapability(completionTools, completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools),
|
|
1921
|
+
implementationMutationExpected: expectsImplementationMutation(step.agent, taskForCompletionGuard),
|
|
1922
|
+
mutationAttemptObserved,
|
|
1923
|
+
mutationEvidence: completionMutationEvidence,
|
|
1924
|
+
agentContractV1: isAgentContractV1(step.agentContract),
|
|
1925
|
+
});
|
|
1926
|
+
const finalOutputHasPersistableFileContent = run.exitCode === 0 && !run.error && !emptyOutputError && Boolean(stripAcceptanceReport(run.finalOutput).trim());
|
|
1927
|
+
const requiredOutput = step.outputMode === "file-only" && step.outputPath
|
|
1928
|
+
? { kind: "file-only" as const, path: step.outputPath, missing: !fs.existsSync(step.outputPath) && !finalOutputHasPersistableFileContent }
|
|
1929
|
+
: effectiveStructuredOutput
|
|
1930
|
+
? { kind: "structured" as const, path: effectiveStructuredOutput.outputPath, missing: !fs.existsSync(effectiveStructuredOutput.outputPath) }
|
|
1795
1931
|
: undefined;
|
|
1796
|
-
const
|
|
1932
|
+
const missingRequiredOutputError = formatRequiredOutputError(requiredOutput);
|
|
1933
|
+
const missingRequiredOutputAfterMutation = Boolean(missingRequiredOutputError) && (mutationAttemptObserved || Boolean(mutationEvidence.changedFiles.length));
|
|
1934
|
+
const effectiveExitCode = toolAvailabilityError || completionEvidence.legacyFailureError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError
|
|
1797
1935
|
? 1
|
|
1798
1936
|
: hiddenError?.hasError
|
|
1799
1937
|
? (hiddenError.exitCode ?? 1)
|
|
@@ -1805,18 +1943,23 @@ async function runSingleStepInner(
|
|
|
1805
1943
|
interrupted: run.interrupted,
|
|
1806
1944
|
timedOut: run.timedOut,
|
|
1807
1945
|
stopped: run.stopped,
|
|
1808
|
-
turnBudgetExceeded: run.turnBudgetExceeded,
|
|
1809
1946
|
})) ? formatProcessSignalError(run.processSignal!) : undefined;
|
|
1947
|
+
const underlyingError = toolAvailabilityError
|
|
1948
|
+
?? midToolExitError
|
|
1949
|
+
?? structuredError
|
|
1950
|
+
?? run.error
|
|
1951
|
+
?? signalError
|
|
1952
|
+
?? (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined)
|
|
1953
|
+
?? ((emptyOutputError || missingRequiredOutputError) && run.stderr.trim() ? run.stderr.trim() : undefined)
|
|
1954
|
+
?? emptyOutputError
|
|
1955
|
+
?? (missingRequiredOutputAfterMutation ? missingRequiredOutputError : undefined)
|
|
1956
|
+
?? (hiddenError?.hasError
|
|
1957
|
+
? hiddenError.details
|
|
1958
|
+
? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
|
|
1959
|
+
: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
|
|
1960
|
+
: undefined);
|
|
1810
1961
|
const error = formatSubagentExtensionConflictError(
|
|
1811
|
-
|
|
1812
|
-
?? completionGuardError
|
|
1813
|
-
?? structuredError
|
|
1814
|
-
?? emptyOutputError
|
|
1815
|
-
?? (hiddenError?.hasError
|
|
1816
|
-
? hiddenError.details
|
|
1817
|
-
? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
|
|
1818
|
-
: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
|
|
1819
|
-
: run.error || signalError || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined)),
|
|
1962
|
+
underlyingError ?? missingRequiredOutputError ?? completionEvidence.legacyFailureError,
|
|
1820
1963
|
{
|
|
1821
1964
|
agent: step.agent,
|
|
1822
1965
|
ambientExtensionsEnabled: launchResolvedExtensions?.disableAmbientExtensions === false,
|
|
@@ -1830,8 +1973,8 @@ async function runSingleStepInner(
|
|
|
1830
1973
|
usage: run.usage,
|
|
1831
1974
|
});
|
|
1832
1975
|
modelAttempts.push(attempt);
|
|
1833
|
-
if (candidate && startupAttemptIndex === 0) attemptedModels.push(candidate);
|
|
1834
|
-
completionGuardTriggeredFinal =
|
|
1976
|
+
if (!recoveringAbort && candidate && startupAttemptIndex === 0) attemptedModels.push(candidate);
|
|
1977
|
+
completionGuardTriggeredFinal = completionEvidence.guardTriggered && !underlyingError && !missingRequiredOutputError;
|
|
1835
1978
|
finalOutputSnapshot = outputSnapshot;
|
|
1836
1979
|
if (step.toolBudget) {
|
|
1837
1980
|
const toolMessages = run.messages.filter((message) => message.role === "toolResult");
|
|
@@ -1839,10 +1982,48 @@ async function runSingleStepInner(
|
|
|
1839
1982
|
toolBudgetBlocked = Boolean(blockedMessage);
|
|
1840
1983
|
toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);
|
|
1841
1984
|
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1985
|
+
const settlementDiagnostic = projectSettlementDiagnostic(completionEvidence, {
|
|
1986
|
+
terminalFailed: effectiveExitCode !== 0,
|
|
1987
|
+
finalTextPresent: Boolean(stripAcceptanceReport(run.finalOutput).trim()),
|
|
1988
|
+
mutationObserved: mutationEvidence.attemptedMutation,
|
|
1989
|
+
requiredOutput,
|
|
1990
|
+
afterCompactionSettlement: run.afterCompactionSettlement === true,
|
|
1991
|
+
});
|
|
1992
|
+
const fileMutationEffect = completionEvidence.fileMutation ?? (missingRequiredOutputAfterMutation ? { status: "observed" as const, expected: completionEvidence.mutationExpected, attempted: true, evidence: mutationEvidence } : undefined);
|
|
1993
|
+
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect || settlementDiagnostic ? { effects: { ...(fileMutationEffect ? { fileMutation: fileMutationEffect } : {}), ...(settlementDiagnostic ? { settlementDiagnostic } : {}) } } : {}) } as RunPiStreamingResult;
|
|
1994
|
+
const abortRecovery = !attempt.success ? planAbortRecovery({
|
|
1995
|
+
messages: run.messages,
|
|
1996
|
+
error,
|
|
1997
|
+
processSignal: run.processSignal,
|
|
1998
|
+
sessionAvailable: Boolean(step.sessionFile && fs.existsSync(step.sessionFile)),
|
|
1999
|
+
alreadyResumed: abortRecoveryAttempted,
|
|
2000
|
+
stopped: run.stopped || ctx.stopSignal?.aborted || ctx.skipAcceptance?.(),
|
|
2001
|
+
interrupted: run.interrupted,
|
|
2002
|
+
timedOut: run.timedOut || ctx.timeoutSignal?.aborted,
|
|
2003
|
+
toolBudgetExhausted: run.toolBudgetBlocked || toolBudgetBlocked,
|
|
2004
|
+
usageBudgetExhausted: ctx.usageBudgetExhausted?.(),
|
|
2005
|
+
structuredOutputFailed: Boolean(structuredError),
|
|
2006
|
+
acceptanceFailed: false,
|
|
2007
|
+
currentTool: run.currentTool,
|
|
2008
|
+
afterCompactionSettlement: run.afterCompactionSettlement,
|
|
2009
|
+
}) : undefined;
|
|
2010
|
+
if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) {
|
|
2011
|
+
attempt.error = attempt.error
|
|
2012
|
+
? `${abortRecovery.diagnostic}\n${attempt.error.slice(0, 8_000)}`
|
|
2013
|
+
: abortRecovery.diagnostic;
|
|
2014
|
+
if (finalResult) finalResult.abortRecoveryDiagnostic = abortRecovery.diagnostic;
|
|
2015
|
+
}
|
|
1844
2016
|
if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break modelAttemptsLoop;
|
|
1845
|
-
if (
|
|
2017
|
+
if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) break modelAttemptsLoop;
|
|
2018
|
+
if (attempt.success) break modelAttemptsLoop;
|
|
2019
|
+
if (recoveringAbort) break modelAttemptsLoop;
|
|
2020
|
+
if (abortRecovery?.action === "resume") {
|
|
2021
|
+
abortRecoveryAttempted = true;
|
|
2022
|
+
nextAttemptTask = abortRecovery.prompt;
|
|
2023
|
+
attemptNotes.push("[abort-recovery] provider/transport abort after useful progress; resuming the retained child session once.");
|
|
2024
|
+
continue;
|
|
2025
|
+
}
|
|
2026
|
+
if (completionEvidence.guardTriggered) break modelAttemptsLoop;
|
|
1846
2027
|
|
|
1847
2028
|
const startupFailure = isRetryableSubagentStartupFailure(omitUndefinedProperties({
|
|
1848
2029
|
exitCode: effectiveExitCode,
|
|
@@ -1858,7 +2039,6 @@ async function runSingleStepInner(
|
|
|
1858
2039
|
interrupted: run.interrupted,
|
|
1859
2040
|
timedOut: run.timedOut,
|
|
1860
2041
|
stopped: run.stopped,
|
|
1861
|
-
turnBudgetExceeded: run.turnBudgetExceeded,
|
|
1862
2042
|
}));
|
|
1863
2043
|
const retryDelayMs = SUBAGENT_STARTUP_RETRY_DELAYS_MS[startupAttemptIndex];
|
|
1864
2044
|
if (startupFailure && retryDelayMs !== undefined) {
|
|
@@ -1889,7 +2069,7 @@ async function runSingleStepInner(
|
|
|
1889
2069
|
finalResult.finalOutput = startupError;
|
|
1890
2070
|
break modelAttemptsLoop;
|
|
1891
2071
|
}
|
|
1892
|
-
const retryableModelFailure =
|
|
2072
|
+
const retryableModelFailure = isRetryableModelFailureAttempt({ error, messages: run.messages, toolCount: run.toolCount });
|
|
1893
2073
|
if (retryableModelFailure) recordRetryableModelFailure(candidate ?? run.model ?? step.model, error);
|
|
1894
2074
|
if (isContextOverflow(error)) {
|
|
1895
2075
|
contextOverflow = true;
|
|
@@ -1905,8 +2085,14 @@ async function runSingleStepInner(
|
|
|
1905
2085
|
const rawOutput = finalResult?.finalOutput ?? "";
|
|
1906
2086
|
const outputForPersistence = stripAcceptanceReport(rawOutput);
|
|
1907
2087
|
const resolvedOutput = step.outputPath && finalResult?.exitCode === 0
|
|
1908
|
-
? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot)
|
|
2088
|
+
? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot, step.outputClaimPath)
|
|
1909
2089
|
: { fullOutput: outputForPersistence };
|
|
2090
|
+
if (resolvedOutput.fatalError) {
|
|
2091
|
+
if (finalResult) {
|
|
2092
|
+
finalResult.exitCode = 1;
|
|
2093
|
+
finalResult.error = finalResult.error ? `${finalResult.error}\n${resolvedOutput.saveError}` : resolvedOutput.saveError;
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
1910
2096
|
const output = stripAcceptanceReport(resolvedOutput.fullOutput);
|
|
1911
2097
|
const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;
|
|
1912
2098
|
let outputForSummary = output;
|
|
@@ -1915,14 +2101,6 @@ async function runSingleStepInner(
|
|
|
1915
2101
|
}
|
|
1916
2102
|
if (finalResult?.stopped && !outputForSummary.trim()) {
|
|
1917
2103
|
outputForSummary = ctx.stopMessage ?? "Subagent stopped by user.";
|
|
1918
|
-
} else if (!finalResult?.timedOut && !finalResult?.stopped && finalResult?.turnBudgetExceeded && turnBudget) {
|
|
1919
|
-
outputForSummary = formatTurnBudgetOutput(turnBudgetExceededMessage(turnBudget, turnBudget.turnCount), outputForSummary);
|
|
1920
|
-
} else if (!finalResult?.timedOut && !finalResult?.stopped && turnBudget?.outcome === "termination-deferred") {
|
|
1921
|
-
const note = turnBudgetDeferredNote(turnBudget, turnBudget.terminationDeferredAtTurn ?? turnBudget.turnCount);
|
|
1922
|
-
outputForSummary = outputForSummary.trim() ? `${note}\n\n${outputForSummary}` : note;
|
|
1923
|
-
} else if (!finalResult?.timedOut && !finalResult?.stopped && turnBudget?.outcome === "wrap-up-requested") {
|
|
1924
|
-
const note = turnBudgetSoftNote(turnBudget, turnBudget.wrapUpRequestedAtTurn ?? turnBudget.turnCount);
|
|
1925
|
-
outputForSummary = outputForSummary.trim() ? `${note}\n\n${outputForSummary}` : note;
|
|
1926
2104
|
}
|
|
1927
2105
|
const outputForAcceptance = rawOutput;
|
|
1928
2106
|
const childWrittenOutput = step.outputPath
|
|
@@ -1960,7 +2138,7 @@ async function runSingleStepInner(
|
|
|
1960
2138
|
saveError: resolvedOutput.saveError,
|
|
1961
2139
|
}));
|
|
1962
2140
|
outputForSummary = finalizedOutput.displayOutput;
|
|
1963
|
-
const acceptance = step.effectiveAcceptance && !finalResult?.stopped && !
|
|
2141
|
+
const acceptance = step.effectiveAcceptance && !finalResult?.stopped && !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted && !ctx.skipAcceptance?.()
|
|
1964
2142
|
? await evaluateAcceptance(omitUndefinedProperties({
|
|
1965
2143
|
acceptance: step.effectiveAcceptance,
|
|
1966
2144
|
output: outputForAcceptance,
|
|
@@ -1979,29 +2157,31 @@ async function runSingleStepInner(
|
|
|
1979
2157
|
: undefined;
|
|
1980
2158
|
const stoppedAfterAcceptance = finalResult?.stopped === true || ctx.stopSignal?.aborted === true;
|
|
1981
2159
|
const timedOutAfterAcceptance = !stoppedAfterAcceptance && (finalResult?.timedOut === true || ctx.timeoutSignal?.aborted === true);
|
|
1982
|
-
const turnBudgetExceeded = finalResult?.turnBudgetExceeded === true;
|
|
1983
2160
|
const effectiveAcceptance = step.effectiveAcceptance
|
|
1984
2161
|
? stoppedAfterAcceptance
|
|
1985
2162
|
? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: "stopped", message: "Acceptance was not evaluated because the subagent was stopped." })
|
|
1986
2163
|
: timedOutAfterAcceptance
|
|
1987
2164
|
? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: "timeout", message: "Acceptance was not evaluated because the subagent timed out." })
|
|
1988
|
-
:
|
|
1989
|
-
? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: "turn-budget", message: "Acceptance was not evaluated because the subagent exceeded its turn budget." })
|
|
1990
|
-
: acceptance
|
|
2165
|
+
: acceptance
|
|
1991
2166
|
: undefined;
|
|
1992
2167
|
const acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;
|
|
1993
|
-
const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !
|
|
1994
|
-
const effectiveFinalExitCode = timedOutAfterAcceptance || stoppedAfterAcceptance
|
|
2168
|
+
const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !isAgentContractV1(step.agentContract);
|
|
2169
|
+
const effectiveFinalExitCode = timedOutAfterAcceptance || stoppedAfterAcceptance ? 1 : acceptanceCanFailRun ? 1 : finalResult?.exitCode ?? 1;
|
|
1995
2170
|
const intercomDetachReceipt = finalResult?.finalOutput === INTERCOM_DETACH_RECEIPT;
|
|
1996
|
-
const
|
|
2171
|
+
const baseFinalError = stoppedAfterAcceptance
|
|
1997
2172
|
? ctx.stopMessage ?? "Subagent stopped by user."
|
|
1998
2173
|
: timedOutAfterAcceptance
|
|
1999
2174
|
? finalResult?.error ?? ctx.timeoutMessage ?? "Subagent timed out."
|
|
2000
|
-
:
|
|
2001
|
-
? finalResult?.error ?? (turnBudget ? turnBudgetExceededMessage(turnBudget, turnBudget.turnCount) : "Subagent exceeded turn budget.")
|
|
2002
|
-
: acceptanceCanFailRun
|
|
2175
|
+
: acceptanceCanFailRun
|
|
2003
2176
|
? (finalResult?.error ? `${finalResult.error}\n${acceptanceFailure}` : acceptanceFailure)
|
|
2004
2177
|
: finalResult?.error ?? (intercomDetachReceipt ? INTERCOM_DETACH_RECEIPT : undefined);
|
|
2178
|
+
const effectiveFinalError = formatChildFailureDiagnostic({
|
|
2179
|
+
error: baseFinalError,
|
|
2180
|
+
afterCompactionSettlement: effectiveFinalExitCode !== 0 ? finalResult?.afterCompactionSettlement : undefined,
|
|
2181
|
+
abortRecoveryDiagnostic: effectiveFinalExitCode !== 0 ? finalResult?.abortRecoveryDiagnostic : undefined,
|
|
2182
|
+
requiredOutput: effectiveFinalExitCode !== 0 ? finalResult?.effects?.settlementDiagnostic?.requiredOutput : undefined,
|
|
2183
|
+
});
|
|
2184
|
+
const usage = usageFromAttempts(modelAttempts);
|
|
2005
2185
|
|
|
2006
2186
|
const artifactErrors = artifactPaths && ctx.artifactConfig?.enabled !== false
|
|
2007
2187
|
? persistStepArtifacts({
|
|
@@ -2021,6 +2201,7 @@ async function runSingleStepInner(
|
|
|
2021
2201
|
model: finalResult?.model,
|
|
2022
2202
|
attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
|
|
2023
2203
|
modelAttempts,
|
|
2204
|
+
usage,
|
|
2024
2205
|
error: effectiveFinalError,
|
|
2025
2206
|
acceptance: effectiveAcceptance,
|
|
2026
2207
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
@@ -2037,6 +2218,7 @@ async function runSingleStepInner(
|
|
|
2037
2218
|
|
|
2038
2219
|
const result: StepResult & { completionGuardTriggered?: boolean } = omitUndefinedProperties({
|
|
2039
2220
|
agent: step.agent,
|
|
2221
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
2040
2222
|
context: step.context,
|
|
2041
2223
|
...(step.agentContract ? { agentContract: step.agentContract } : {}),
|
|
2042
2224
|
launchContractDigest: actualLaunchContractDigest,
|
|
@@ -2052,26 +2234,24 @@ async function runSingleStepInner(
|
|
|
2052
2234
|
modelAttempts,
|
|
2053
2235
|
contextOverflow: contextOverflow || undefined,
|
|
2054
2236
|
totalCost: costSummaryFromAttempts(modelAttempts),
|
|
2237
|
+
usage,
|
|
2055
2238
|
artifactPaths,
|
|
2056
|
-
outputSaveError: artifactErrors.outputSaveError,
|
|
2239
|
+
outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
|
|
2057
2240
|
metadataSaveError: artifactErrors.metadataSaveError,
|
|
2058
2241
|
transcriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,
|
|
2059
2242
|
transcriptError: transcriptWriter?.getError(),
|
|
2060
|
-
interrupted: timedOutAfterAcceptance || stoppedAfterAcceptance
|
|
2243
|
+
interrupted: timedOutAfterAcceptance || stoppedAfterAcceptance ? false : finalResult?.interrupted,
|
|
2061
2244
|
timedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,
|
|
2062
2245
|
stopped: stoppedAfterAcceptance ? true : finalResult?.stopped,
|
|
2063
2246
|
processSignal: finalResult?.processSignal,
|
|
2064
2247
|
timeoutRecovery,
|
|
2065
|
-
turnBudget,
|
|
2066
|
-
turnBudgetExceeded: turnBudgetExceeded || undefined,
|
|
2067
|
-
wrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined,
|
|
2068
2248
|
toolBudget,
|
|
2069
2249
|
toolBudgetBlocked: toolBudgetBlocked || undefined,
|
|
2070
2250
|
completionGuardTriggered: completionGuardTriggeredFinal,
|
|
2071
2251
|
...((finalResult as (RunPiStreamingResult & { effects?: import("../../shared/types.ts").EffectsProjection }) | undefined)?.effects ? { effects: (finalResult as RunPiStreamingResult & { effects?: import("../../shared/types.ts").EffectsProjection }).effects } : {}),
|
|
2072
|
-
structuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance
|
|
2073
|
-
structuredOutputPath: timedOutAfterAcceptance || stoppedAfterAcceptance
|
|
2074
|
-
structuredOutputSchemaPath: timedOutAfterAcceptance || stoppedAfterAcceptance
|
|
2252
|
+
structuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : (finalResult as (RunPiStreamingResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput,
|
|
2253
|
+
structuredOutputPath: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : effectiveStructuredOutput?.outputPath,
|
|
2254
|
+
structuredOutputSchemaPath: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : effectiveStructuredOutput?.schemaPath,
|
|
2075
2255
|
acceptance: effectiveAcceptance,
|
|
2076
2256
|
watchdog: finalResult?.watchdog,
|
|
2077
2257
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
@@ -2098,13 +2278,7 @@ type RunnerStatusStep = NonNullable<AsyncStatus["steps"]>[number] & {
|
|
|
2098
2278
|
|
|
2099
2279
|
function externalRunnerStatus(runner: SubagentStep["runner"]): ExternalCliRunnerStatus | ExternalJobRunnerStatus | undefined {
|
|
2100
2280
|
if (runner?.type === "external-cli") {
|
|
2101
|
-
return
|
|
2102
|
-
type: "external-cli",
|
|
2103
|
-
command: runner.command,
|
|
2104
|
-
args: runner.args ?? [],
|
|
2105
|
-
promptDelivery: runner.promptDelivery ?? "stdin",
|
|
2106
|
-
capabilities: { stop: true, steer: false, resume: false, structuredOutput: false, toolEvents: false },
|
|
2107
|
-
};
|
|
2281
|
+
return resolveExternalCliRunnerStatus(runner);
|
|
2108
2282
|
}
|
|
2109
2283
|
if (runner?.type === "external-job") {
|
|
2110
2284
|
return {
|
|
@@ -2151,6 +2325,11 @@ function requiredStatusStep(statusPayload: RunnerStatusPayload, index: number):
|
|
|
2151
2325
|
return step;
|
|
2152
2326
|
}
|
|
2153
2327
|
|
|
2328
|
+
function setStatusWorktreeReference(statusStep: RunnerStatusStep, worktree: WorktreeSetup["worktrees"][number]): void {
|
|
2329
|
+
statusStep.worktreePath = worktree.path;
|
|
2330
|
+
statusStep.branch = worktree.branch;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2154
2333
|
function markParallelGroupSetupFailure(input: {
|
|
2155
2334
|
statusPayload: RunnerStatusPayload;
|
|
2156
2335
|
results: StepResult[];
|
|
@@ -2279,6 +2458,25 @@ function resolveAsyncStepTranscriptPath(input: {
|
|
|
2279
2458
|
|
|
2280
2459
|
type SingleStepResult = Awaited<ReturnType<typeof runSingleStep>>;
|
|
2281
2460
|
|
|
2461
|
+
function missingRequiredOutputAfterUsefulMutation(result: SingleStepResult): boolean {
|
|
2462
|
+
const effects = result.effects;
|
|
2463
|
+
return effects?.settlementDiagnostic?.requiredOutput?.missing === true
|
|
2464
|
+
&& (effects.settlementDiagnostic.mutation.attempted || effects.fileMutation?.attempted === true || Boolean(effects.fileMutation?.evidence?.changedFiles.length));
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
function partialExecutionWithUsefulMutation(result: SingleStepResult): boolean {
|
|
2468
|
+
const fileMutation = result.effects?.fileMutation;
|
|
2469
|
+
return result.execution?.status === "partial" && (fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length));
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
function partialEvidenceResult(result: SingleStepResult): boolean {
|
|
2473
|
+
return missingRequiredOutputAfterUsefulMutation(result) || partialExecutionWithUsefulMutation(result);
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
function concreteFailureResult(result: SingleStepResult): boolean {
|
|
2477
|
+
return result.success === false && !partialEvidenceResult(result);
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2282
2480
|
function combinedAbortSignal(signals: Array<AbortSignal | undefined>): AbortSignal | undefined {
|
|
2283
2481
|
const activeSignals = signals.filter((signal): signal is AbortSignal => Boolean(signal));
|
|
2284
2482
|
if (activeSignals.length === 0) return undefined;
|
|
@@ -2350,6 +2548,8 @@ async function runSubagent(
|
|
|
2350
2548
|
const overallStartTime = Date.now();
|
|
2351
2549
|
const shareEnabled = config.share === true;
|
|
2352
2550
|
const asyncDir = config.asyncDir;
|
|
2551
|
+
const handoffWorkflowKey = config.workflowKey;
|
|
2552
|
+
const handoffChildRunId = handoffWorkflowKey ? id : undefined;
|
|
2353
2553
|
const statusPath = path.join(asyncDir, "status.json");
|
|
2354
2554
|
const eventsPath = path.join(asyncDir, "events.jsonl");
|
|
2355
2555
|
const logPath = path.join(asyncDir, `subagent-log-${id}.md`);
|
|
@@ -2358,7 +2558,6 @@ async function runSubagent(
|
|
|
2358
2558
|
const activeChildTimeouts = new Map<number, () => void>();
|
|
2359
2559
|
const activeChildStops = new Map<number, () => void>();
|
|
2360
2560
|
const childStopRequests = new Map<number, { childId: string; requestedAt: number }>();
|
|
2361
|
-
const activeChildTurnBudgetAborts = new Map<number, (message: string, state?: TurnBudgetState) => void>();
|
|
2362
2561
|
const pendingStepSteers: SteerRequest[] = [];
|
|
2363
2562
|
const steeringCapabilities = new Map<number, SteerCapability>();
|
|
2364
2563
|
let interrupted = false;
|
|
@@ -2367,7 +2566,6 @@ async function runSubagent(
|
|
|
2367
2566
|
let timeoutTimer: NodeJS.Timeout | undefined;
|
|
2368
2567
|
let timedOut = false;
|
|
2369
2568
|
let stopped = false;
|
|
2370
|
-
let turnBudgetExceeded = false;
|
|
2371
2569
|
let usageBudgetExceeded = false;
|
|
2372
2570
|
const timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;
|
|
2373
2571
|
const stopMessage = "Subagent stopped by user.";
|
|
@@ -2388,8 +2586,11 @@ async function runSubagent(
|
|
|
2388
2586
|
for (const task of step.parallel) {
|
|
2389
2587
|
const taskFlatIndex = flatStepCount;
|
|
2390
2588
|
const transcriptPath = resolveAsyncStepTranscriptPath(omitUndefinedProperties({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount }));
|
|
2589
|
+
const taskSessionName = task.sessionName ?? deriveChildSessionName({ agent: task.agent, task: task.task, label: task.label });
|
|
2391
2590
|
initialStatusSteps.push(omitUndefinedProperties({
|
|
2392
2591
|
agent: task.agent,
|
|
2592
|
+
...(task.lane ? { lane: task.lane } : config.lane ? { lane: config.lane } : {}),
|
|
2593
|
+
...(taskSessionName ? { sessionName: taskSessionName } : {}),
|
|
2393
2594
|
...(externalRunnerStatus(task.runner) ? { runner: externalRunnerStatus(task.runner) } : {}),
|
|
2394
2595
|
...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
|
|
2395
2596
|
...(task.context ? { context: task.context } : {}),
|
|
@@ -2408,6 +2609,7 @@ async function runSubagent(
|
|
|
2408
2609
|
...(transcriptPath ? { transcriptPath } : {}),
|
|
2409
2610
|
skills: task.skills,
|
|
2410
2611
|
model: task.model,
|
|
2612
|
+
...(task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {}),
|
|
2411
2613
|
thinking: task.thinking,
|
|
2412
2614
|
attemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,
|
|
2413
2615
|
recentTools: [],
|
|
@@ -2425,6 +2627,7 @@ async function runSubagent(
|
|
|
2425
2627
|
label: step.label ?? step.parallel.label ?? `Dynamic fanout (${step.collect.as})`,
|
|
2426
2628
|
outputName: step.collect.as,
|
|
2427
2629
|
structured: Boolean(step.collect.outputSchema),
|
|
2630
|
+
...(step.parallel.contextLimit !== undefined ? { contextLimit: step.parallel.contextLimit } : {}),
|
|
2428
2631
|
...(step.agentContract ? { agentContract: step.agentContract } : {}),
|
|
2429
2632
|
...(step.capabilityCeiling ? { capabilityCeiling: step.capabilityCeiling } : {}),
|
|
2430
2633
|
...(step.thinkingCeiling ? { thinkingCeiling: step.thinkingCeiling } : {}),
|
|
@@ -2437,8 +2640,11 @@ async function runSubagent(
|
|
|
2437
2640
|
} else {
|
|
2438
2641
|
const stepFlatIndex = flatStepCount;
|
|
2439
2642
|
const transcriptPath = resolveAsyncStepTranscriptPath(omitUndefinedProperties({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount }));
|
|
2643
|
+
const stepSessionName = step.sessionName ?? deriveChildSessionName({ agent: step.agent, task: step.task, label: step.label });
|
|
2440
2644
|
initialStatusSteps.push(omitUndefinedProperties({
|
|
2441
2645
|
agent: step.agent,
|
|
2646
|
+
...(step.lane ? { lane: step.lane } : config.lane ? { lane: config.lane } : {}),
|
|
2647
|
+
...(stepSessionName ? { sessionName: stepSessionName } : {}),
|
|
2442
2648
|
...(externalRunnerStatus(step.runner) ? { runner: externalRunnerStatus(step.runner) } : {}),
|
|
2443
2649
|
...(statusStepDescription(step.task) ? { description: statusStepDescription(step.task) } : {}),
|
|
2444
2650
|
...(step.context ? { context: step.context } : {}),
|
|
@@ -2457,6 +2663,7 @@ async function runSubagent(
|
|
|
2457
2663
|
...(transcriptPath ? { transcriptPath } : {}),
|
|
2458
2664
|
skills: step.skills,
|
|
2459
2665
|
model: step.model,
|
|
2666
|
+
...(step.contextLimit !== undefined ? { contextLimit: step.contextLimit } : {}),
|
|
2460
2667
|
thinking: step.thinking,
|
|
2461
2668
|
attemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,
|
|
2462
2669
|
recentTools: [],
|
|
@@ -2500,7 +2707,6 @@ async function runSubagent(
|
|
|
2500
2707
|
lastUpdate: overallStartTime,
|
|
2501
2708
|
...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),
|
|
2502
2709
|
...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
|
|
2503
|
-
...(config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {}),
|
|
2504
2710
|
...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),
|
|
2505
2711
|
...(config.usageBudget ? { usageBudget: usageBudgetState(config.usageBudget, undefined) } : {}),
|
|
2506
2712
|
pid: process.pid,
|
|
@@ -2515,6 +2721,7 @@ async function runSubagent(
|
|
|
2515
2721
|
...(config.runFanoutBudget ? { runFanoutBudget: getRunFanoutBudgetSnapshot(config.runFanoutBudget) } : {}),
|
|
2516
2722
|
...(config.parentWorkflowRunId ? { parentWorkflowRunId: config.parentWorkflowRunId } : {}),
|
|
2517
2723
|
...(config.workflowKey ? { workflowKey: config.workflowKey } : {}),
|
|
2724
|
+
...(config.lane ? { lane: config.lane } : {}),
|
|
2518
2725
|
...(config.runnerProcessInstanceId ? { processTerminal: { version: 1 as const, state: "pending" as const, runId: id, runnerProcessInstanceId: config.runnerProcessInstanceId } } : {}),
|
|
2519
2726
|
steps: initialStatusSteps,
|
|
2520
2727
|
artifactsDir,
|
|
@@ -2632,6 +2839,7 @@ async function runSubagent(
|
|
|
2632
2839
|
const statusResultSummary = (state: AsyncStatus["state"]): string => {
|
|
2633
2840
|
if (statusPayload.error) return statusPayload.error;
|
|
2634
2841
|
if (state === "paused") return "Paused after interrupt. Waiting for explicit next action.";
|
|
2842
|
+
if (state === "partial") return "Subagent needs attention after partial work.";
|
|
2635
2843
|
if (state === "stopped") return stopMessage;
|
|
2636
2844
|
if (state === "rejected") return "Subagent rejected.";
|
|
2637
2845
|
return state === "complete" ? "Subagent completed." : "Subagent failed.";
|
|
@@ -2640,12 +2848,13 @@ async function runSubagent(
|
|
|
2640
2848
|
if (step.status === "complete" || step.status === "completed") return true;
|
|
2641
2849
|
if (step.status === "failed" || step.status === "stopped" || step.status === "rejected") return false;
|
|
2642
2850
|
if (state === "complete") return true;
|
|
2643
|
-
if (state === "failed" || state === "stopped" || state === "rejected") return false;
|
|
2851
|
+
if (state === "failed" || state === "partial" || state === "stopped" || state === "rejected") return false;
|
|
2644
2852
|
return undefined;
|
|
2645
2853
|
};
|
|
2646
2854
|
const writeRecoverableStatusResult = (): void => {
|
|
2647
2855
|
const state = statusResultState();
|
|
2648
2856
|
if (!state || finalResultCommitted || !config.sessionId) return;
|
|
2857
|
+
if ((state as string) === "complete") return;
|
|
2649
2858
|
const now = statusPayload.endedAt ?? statusPayload.lastUpdate ?? Date.now();
|
|
2650
2859
|
const summary = statusResultSummary(state);
|
|
2651
2860
|
runPersistence.write(resultPath, omitUndefinedProperties({
|
|
@@ -2657,10 +2866,11 @@ async function runSubagent(
|
|
|
2657
2866
|
success: state === "complete",
|
|
2658
2867
|
state,
|
|
2659
2868
|
summary,
|
|
2660
|
-
error: state === "failed" || state === "stopped" || state === "rejected" ? summary : undefined,
|
|
2869
|
+
error: state === "failed" || state === "partial" || state === "stopped" || state === "rejected" ? summary : undefined,
|
|
2661
2870
|
stopped: state === "stopped" ? true : undefined,
|
|
2662
2871
|
results: statusPayload.steps.map((step) => omitUndefinedProperties({
|
|
2663
2872
|
agent: step.agent,
|
|
2873
|
+
...(step.sessionName ? { sessionName: step.sessionName } : {}),
|
|
2664
2874
|
output: step.status === "complete" || step.status === "completed" ? "" : step.error ?? summary,
|
|
2665
2875
|
error: step.error,
|
|
2666
2876
|
success: statusResultSuccess(state, step),
|
|
@@ -2668,6 +2878,7 @@ async function runSubagent(
|
|
|
2668
2878
|
model: step.model,
|
|
2669
2879
|
attemptedModels: step.attemptedModels,
|
|
2670
2880
|
modelAttempts: step.modelAttempts,
|
|
2881
|
+
usage: usageFromAttempts(step.modelAttempts),
|
|
2671
2882
|
contextOverflow: step.contextOverflow,
|
|
2672
2883
|
})),
|
|
2673
2884
|
exitCode: state === "complete" || state === "paused" ? 0 : 1,
|
|
@@ -2762,7 +2973,7 @@ async function runSubagent(
|
|
|
2762
2973
|
};
|
|
2763
2974
|
const childStopResult = (index: number, agent: string, context?: "fresh" | "fork"): SingleStepResult => {
|
|
2764
2975
|
markChildStopped(index);
|
|
2765
|
-
return stoppedStepResult(agent, context);
|
|
2976
|
+
return stoppedStepResult(agent, context, requiredStatusStep(statusPayload, index).sessionName);
|
|
2766
2977
|
};
|
|
2767
2978
|
const stopChildStep = (request: StopRequest): void => {
|
|
2768
2979
|
if (request.targetIndex === undefined) {
|
|
@@ -2805,13 +3016,6 @@ async function runSubagent(
|
|
|
2805
3016
|
activeChildStops.set(flatIndex, stop);
|
|
2806
3017
|
if (stopped || childStopRequests.has(flatIndex)) stop();
|
|
2807
3018
|
};
|
|
2808
|
-
const registerStepTurnBudgetAbort = (flatIndex: number, abort: ((message: string, state?: TurnBudgetState) => void) | undefined): void => {
|
|
2809
|
-
if (!abort) {
|
|
2810
|
-
activeChildTurnBudgetAborts.delete(flatIndex);
|
|
2811
|
-
return;
|
|
2812
|
-
}
|
|
2813
|
-
activeChildTurnBudgetAborts.set(flatIndex, abort);
|
|
2814
|
-
};
|
|
2815
3019
|
const interruptActiveChildren = (): void => {
|
|
2816
3020
|
for (const interrupt of [...activeChildInterrupts.values()]) interrupt();
|
|
2817
3021
|
};
|
|
@@ -2921,23 +3125,26 @@ async function runSubagent(
|
|
|
2921
3125
|
}
|
|
2922
3126
|
}
|
|
2923
3127
|
};
|
|
2924
|
-
const pausedStepResult = (agent: string, context?: "fresh" | "fork"): SingleStepResult => omitUndefinedProperties({
|
|
3128
|
+
const pausedStepResult = (agent: string, context?: "fresh" | "fork", sessionName?: string): SingleStepResult => omitUndefinedProperties({
|
|
2925
3129
|
agent,
|
|
3130
|
+
sessionName,
|
|
2926
3131
|
context,
|
|
2927
3132
|
output: "Paused after interrupt. Waiting for explicit next action.",
|
|
2928
3133
|
exitCode: 0,
|
|
2929
3134
|
interrupted: true,
|
|
2930
3135
|
});
|
|
2931
|
-
const timedOutStepResult = (agent: string, context?: "fresh" | "fork"): SingleStepResult => omitUndefinedProperties({
|
|
3136
|
+
const timedOutStepResult = (agent: string, context?: "fresh" | "fork", sessionName?: string): SingleStepResult => omitUndefinedProperties({
|
|
2932
3137
|
agent,
|
|
3138
|
+
sessionName,
|
|
2933
3139
|
context,
|
|
2934
3140
|
output: timeoutMessage ?? "Subagent timed out.",
|
|
2935
3141
|
error: timeoutMessage ?? "Subagent timed out.",
|
|
2936
3142
|
exitCode: 1,
|
|
2937
3143
|
timedOut: true,
|
|
2938
3144
|
});
|
|
2939
|
-
const stoppedStepResult = (agent: string, context?: "fresh" | "fork"): SingleStepResult => omitUndefinedProperties({
|
|
3145
|
+
const stoppedStepResult = (agent: string, context?: "fresh" | "fork", sessionName?: string): SingleStepResult => omitUndefinedProperties({
|
|
2940
3146
|
agent,
|
|
3147
|
+
sessionName,
|
|
2941
3148
|
context,
|
|
2942
3149
|
output: stopMessage,
|
|
2943
3150
|
error: stopMessage,
|
|
@@ -3318,74 +3525,15 @@ async function runSubagent(
|
|
|
3318
3525
|
}
|
|
3319
3526
|
pendingStepSteers.push(...remaining);
|
|
3320
3527
|
};
|
|
3321
|
-
const updateStepModel = (flatIndex: number, model: string | undefined, thinking: string | undefined, now = Date.now()): void => {
|
|
3528
|
+
const updateStepModel = (flatIndex: number, model: string | undefined, thinking: string | undefined, contextLimit?: number, now = Date.now()): void => {
|
|
3322
3529
|
const step = statusPayload.steps[flatIndex];
|
|
3323
3530
|
if (!step) return;
|
|
3324
3531
|
setOptionalProperty(step, "model", model);
|
|
3325
3532
|
setOptionalProperty(step, "thinking", thinking);
|
|
3533
|
+
setOptionalProperty(step, "contextLimit", contextLimit);
|
|
3326
3534
|
statusPayload.lastUpdate = now;
|
|
3327
3535
|
writeStatusPayload();
|
|
3328
3536
|
};
|
|
3329
|
-
const updateStepTurnBudget = (
|
|
3330
|
-
flatIndex: number,
|
|
3331
|
-
turnCount: number,
|
|
3332
|
-
now: number,
|
|
3333
|
-
terminalAssistantStop: boolean,
|
|
3334
|
-
toolWorkActiveOrStarting: boolean,
|
|
3335
|
-
): void => {
|
|
3336
|
-
const budget = config.turnBudget;
|
|
3337
|
-
const step = statusPayload.steps[flatIndex];
|
|
3338
|
-
if (!budget || !step || timedOut || stopped || turnBudgetExceeded || step.turnBudgetExceeded) return;
|
|
3339
|
-
if (turnCount < budget.maxTurns) {
|
|
3340
|
-
const state: TurnBudgetState = { ...budget, outcome: "within-budget", turnCount };
|
|
3341
|
-
step.turnBudget = state;
|
|
3342
|
-
statusPayload.turnBudget = state;
|
|
3343
|
-
return;
|
|
3344
|
-
}
|
|
3345
|
-
if (!step.wrapUpRequested) {
|
|
3346
|
-
step.wrapUpRequested = true;
|
|
3347
|
-
statusPayload.wrapUpRequested = true;
|
|
3348
|
-
appendRecentStepOutput(step, [turnBudgetSoftNote(budget, turnCount)]);
|
|
3349
|
-
}
|
|
3350
|
-
const decision = turnBudgetDecision(budget, turnCount, terminalAssistantStop, toolWorkActiveOrStarting);
|
|
3351
|
-
if (decision === "defer") {
|
|
3352
|
-
const firstDeferredTurn = step.turnBudget?.terminationDeferredAtTurn;
|
|
3353
|
-
const deferredState = turnBudgetDeferredState(budget, turnCount, firstDeferredTurn);
|
|
3354
|
-
step.turnBudget = deferredState;
|
|
3355
|
-
statusPayload.turnBudget = deferredState;
|
|
3356
|
-
if (firstDeferredTurn === undefined) {
|
|
3357
|
-
appendJsonl(eventsPath, JSON.stringify({
|
|
3358
|
-
type: "subagent.step.turn_budget_deferred",
|
|
3359
|
-
ts: now,
|
|
3360
|
-
runId: id,
|
|
3361
|
-
stepIndex: flatIndex,
|
|
3362
|
-
agent: step.agent,
|
|
3363
|
-
turnCount,
|
|
3364
|
-
maxTurns: budget.maxTurns,
|
|
3365
|
-
graceTurns: budget.graceTurns,
|
|
3366
|
-
}));
|
|
3367
|
-
}
|
|
3368
|
-
return;
|
|
3369
|
-
}
|
|
3370
|
-
const state = turnBudgetState(budget, turnCount, false);
|
|
3371
|
-
step.turnBudget = state;
|
|
3372
|
-
statusPayload.turnBudget = state;
|
|
3373
|
-
if (decision !== "abort") return;
|
|
3374
|
-
const exceededState = turnBudgetState(budget, turnCount, true);
|
|
3375
|
-
const message = turnBudgetExceededMessage(budget, turnCount);
|
|
3376
|
-
step.turnBudget = exceededState;
|
|
3377
|
-
step.turnBudgetExceeded = true;
|
|
3378
|
-
step.wrapUpRequested = true;
|
|
3379
|
-
step.error = message;
|
|
3380
|
-
turnBudgetExceeded = true;
|
|
3381
|
-
statusPayload.turnBudget = exceededState;
|
|
3382
|
-
statusPayload.turnBudgetExceeded = true;
|
|
3383
|
-
statusPayload.wrapUpRequested = true;
|
|
3384
|
-
statusPayload.error = message;
|
|
3385
|
-
statusPayload.lastUpdate = now;
|
|
3386
|
-
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.turn_budget_exceeded", ts: now, runId: id, stepIndex: flatIndex, agent: step.agent, turnCount, maxTurns: budget.maxTurns, graceTurns: budget.graceTurns, message }));
|
|
3387
|
-
activeChildTurnBudgetAborts.get(flatIndex)?.(message, exceededState);
|
|
3388
|
-
};
|
|
3389
3537
|
const updateStepFromChildEvent = (flatIndex: number, event: ChildEvent): void => {
|
|
3390
3538
|
const step = statusPayload.steps[flatIndex];
|
|
3391
3539
|
if (!step) return;
|
|
@@ -3408,7 +3556,7 @@ async function runSubagent(
|
|
|
3408
3556
|
return;
|
|
3409
3557
|
}
|
|
3410
3558
|
if (event.type === "tool_execution_start" && event.toolName) {
|
|
3411
|
-
const mutates = isMutatingTool(event.toolName, event.args);
|
|
3559
|
+
const mutates = isMutatingTool(event.toolName, event.args, flatSteps[flatIndex]?.mutationTools);
|
|
3412
3560
|
const currentPath = resolveCurrentPath(event.toolName, event.args);
|
|
3413
3561
|
const argsPreview = extractToolArgsPreview(event.args ?? {});
|
|
3414
3562
|
const blocksSupervisor = isBlockingSupervisorTool(event.toolName, event.args);
|
|
@@ -3516,22 +3664,16 @@ async function runSubagent(
|
|
|
3516
3664
|
if (usage) {
|
|
3517
3665
|
const input = usage.input ?? usage.inputTokens ?? 0;
|
|
3518
3666
|
const output = usage.output ?? usage.outputTokens ?? 0;
|
|
3667
|
+
const window = input + (usage.cacheRead ?? usage.cacheReadTokens ?? 0);
|
|
3519
3668
|
const previousInput = step.tokens?.input ?? 0;
|
|
3520
3669
|
const previousOutput = step.tokens?.output ?? 0;
|
|
3521
|
-
step.tokens = { input: previousInput + input, output: previousOutput + output, total: previousInput + previousOutput + input + output };
|
|
3670
|
+
step.tokens = { input: previousInput + input, output: previousOutput + output, total: previousInput + previousOutput + input + output, window, windowPeak: Math.max(step.tokens?.windowPeak ?? 0, window) };
|
|
3522
3671
|
const totalInput = statusPayload.totalTokens?.input ?? 0;
|
|
3523
3672
|
const totalOutput = statusPayload.totalTokens?.output ?? 0;
|
|
3524
|
-
statusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };
|
|
3673
|
+
statusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output, window, windowPeak: Math.max(statusPayload.totalTokens?.windowPeak ?? 0, window) };
|
|
3525
3674
|
refreshUsageBudget();
|
|
3526
3675
|
}
|
|
3527
3676
|
statusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);
|
|
3528
|
-
updateStepTurnBudget(
|
|
3529
|
-
flatIndex,
|
|
3530
|
-
step.turnCount,
|
|
3531
|
-
now,
|
|
3532
|
-
isTerminalAssistantStop(event.message),
|
|
3533
|
-
assistantStartsToolCall(event.message) || Boolean(step.currentTool),
|
|
3534
|
-
);
|
|
3535
3677
|
}
|
|
3536
3678
|
syncTopLevelCurrentTool();
|
|
3537
3679
|
step.lastActivityAt = now;
|
|
@@ -3760,7 +3902,7 @@ async function runSubagent(
|
|
|
3760
3902
|
let flatIndex = 0;
|
|
3761
3903
|
let stepCursor = 0;
|
|
3762
3904
|
while (true) {
|
|
3763
|
-
if (interrupted || timedOut || stopped
|
|
3905
|
+
if (interrupted || timedOut || stopped) break;
|
|
3764
3906
|
consumePendingAppendRequests();
|
|
3765
3907
|
if (stepCursor >= steps.length) break;
|
|
3766
3908
|
refreshUsageBudget();
|
|
@@ -3905,10 +4047,12 @@ async function runSubagent(
|
|
|
3905
4047
|
: step.parallel.outputPath;
|
|
3906
4048
|
const taskText = task.task ?? step.parallel.task;
|
|
3907
4049
|
const materializedTask = step.parallel.namespaceOutputPath ? injectSingleOutputInstruction(taskText, outputPath, step.parallel) : taskText;
|
|
4050
|
+
const sessionName = deriveChildSessionName({ agent: step.parallel.agent, task: taskText, label: task.label ?? step.parallel.label });
|
|
3908
4051
|
return omitUndefinedProperties({
|
|
3909
4052
|
...step.parallel,
|
|
3910
4053
|
runFanoutPath: `chain[${stepIndex}].expand[${itemIndex}]`,
|
|
3911
4054
|
task: materializedTask,
|
|
4055
|
+
...(sessionName ? { sessionName } : {}),
|
|
3912
4056
|
effectiveAcceptance: resolveEffectiveAcceptance(omitUndefinedProperties({
|
|
3913
4057
|
explicit: step.parallel.acceptanceInput,
|
|
3914
4058
|
agentName: step.parallel.agent,
|
|
@@ -3939,6 +4083,7 @@ async function runSubagent(
|
|
|
3939
4083
|
const transcriptPath = resolveAsyncStepTranscriptPath(omitUndefinedProperties({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount }));
|
|
3940
4084
|
return omitUndefinedProperties({
|
|
3941
4085
|
agent: task.agent,
|
|
4086
|
+
...(task.sessionName ? { sessionName: task.sessionName } : {}),
|
|
3942
4087
|
...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
|
|
3943
4088
|
...(task.context ? { context: task.context } : {}),
|
|
3944
4089
|
...(task.phase ?? step.phase ? { phase: task.phase ?? step.phase } : {}),
|
|
@@ -3952,6 +4097,7 @@ async function runSubagent(
|
|
|
3952
4097
|
...(transcriptPath ? { transcriptPath } : {}),
|
|
3953
4098
|
...(task.skills ? { skills: task.skills } : {}),
|
|
3954
4099
|
...(task.model ? { model: task.model } : {}),
|
|
4100
|
+
...(task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {}),
|
|
3955
4101
|
...(task.thinking ? { thinking: task.thinking } : {}),
|
|
3956
4102
|
...(task.thinkingCeiling ? { thinkingCeiling: task.thinkingCeiling } : {}),
|
|
3957
4103
|
...(task.modelCandidates && task.modelCandidates.length > 0 ? { attemptedModels: task.modelCandidates } : task.model ? { attemptedModels: [task.model] } : {}),
|
|
@@ -4021,12 +4167,12 @@ async function runSubagent(
|
|
|
4021
4167
|
usageBudgetExceeded = true;
|
|
4022
4168
|
writeStatusPayload();
|
|
4023
4169
|
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0 }));
|
|
4024
|
-
return omitUndefinedProperties({ agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true });
|
|
4170
|
+
return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true });
|
|
4025
4171
|
}
|
|
4026
|
-
if (timedOut) return timedOutStepResult(task.agent, task.context);
|
|
4027
|
-
if (stopped) return stoppedStepResult(task.agent, task.context);
|
|
4172
|
+
if (timedOut) return timedOutStepResult(task.agent, task.context, task.sessionName);
|
|
4173
|
+
if (stopped) return stoppedStepResult(task.agent, task.context, task.sessionName);
|
|
4028
4174
|
if (childStopRequests.has(fi)) return childStopResult(fi, task.agent, task.context);
|
|
4029
|
-
if (interrupted) return pausedStepResult(task.agent, task.context);
|
|
4175
|
+
if (interrupted) return pausedStepResult(task.agent, task.context, task.sessionName);
|
|
4030
4176
|
if (aborted && failFast) {
|
|
4031
4177
|
const skippedAt = Date.now();
|
|
4032
4178
|
requiredStatusStep(statusPayload, fi).status = "failed";
|
|
@@ -4037,7 +4183,7 @@ async function runSubagent(
|
|
|
4037
4183
|
requiredStatusStep(statusPayload, fi).exitCode = -1;
|
|
4038
4184
|
statusPayload.lastUpdate = skippedAt;
|
|
4039
4185
|
writeStatusPayload();
|
|
4040
|
-
return omitUndefinedProperties({ agent: task.agent, context: task.context, output: "(skipped — fail-fast)", exitCode: -1 as number | null, skipped: true });
|
|
4186
|
+
return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: "(skipped — fail-fast)", exitCode: -1 as number | null, skipped: true });
|
|
4041
4187
|
}
|
|
4042
4188
|
const taskStartTime = Date.now();
|
|
4043
4189
|
statusPayload.currentStep = fi;
|
|
@@ -4073,20 +4219,19 @@ async function runSubagent(
|
|
|
4073
4219
|
registerInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),
|
|
4074
4220
|
registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
|
|
4075
4221
|
registerStop: (stop) => registerStepStop(fi, stop),
|
|
4076
|
-
registerTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),
|
|
4077
4222
|
timeoutSignal: timeoutAbortController.signal,
|
|
4078
4223
|
stopSignal: stopAbortController.signal,
|
|
4079
4224
|
trackedMutationEvidenceForCompletionGuard: false,
|
|
4080
4225
|
timeoutMessage,
|
|
4081
4226
|
stopMessage,
|
|
4082
|
-
turnBudget: config.turnBudget,
|
|
4083
4227
|
toolTimeoutMs: task.toolTimeoutMs ?? config.toolTimeoutMs,
|
|
4084
|
-
onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),
|
|
4228
|
+
onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
|
|
4085
4229
|
onChildEvent: (event) => updateStepFromChildEvent(fi, event),
|
|
4086
4230
|
onWriterProcess,
|
|
4087
4231
|
onExternalProcess: (process) => updateExternalProcess(fi, process),
|
|
4088
4232
|
onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
|
|
4089
4233
|
skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
|
|
4234
|
+
usageBudgetExhausted: () => refreshUsageBudget()?.exhausted === true,
|
|
4090
4235
|
orcaProgressTab,
|
|
4091
4236
|
}), config.deadlineAt);
|
|
4092
4237
|
const taskEndTime = Date.now();
|
|
@@ -4098,16 +4243,11 @@ async function runSubagent(
|
|
|
4098
4243
|
requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
|
|
4099
4244
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "timedOut", timedOut || singleResult.timedOut ? true : undefined);
|
|
4100
4245
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "stopped", stopped || childStopped ? true : undefined);
|
|
4101
|
-
setOptionalProperty(requiredStatusStep(statusPayload, fi), "turnBudget", singleResult.turnBudget);
|
|
4102
|
-
setOptionalProperty(requiredStatusStep(statusPayload, fi), "turnBudgetExceeded", singleResult.turnBudgetExceeded);
|
|
4103
|
-
setOptionalProperty(requiredStatusStep(statusPayload, fi), "wrapUpRequested", singleResult.wrapUpRequested);
|
|
4104
4246
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "toolBudget", singleResult.toolBudget);
|
|
4105
4247
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "toolBudgetBlocked", singleResult.toolBudgetBlocked);
|
|
4106
4248
|
if (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;
|
|
4107
4249
|
if (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;
|
|
4108
|
-
|
|
4109
|
-
if (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;
|
|
4110
|
-
if (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;
|
|
4250
|
+
setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
|
|
4111
4251
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
|
|
4112
4252
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
|
|
4113
4253
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
|
|
@@ -4159,6 +4299,7 @@ async function runSubagent(
|
|
|
4159
4299
|
for (const pr of parallelResults) {
|
|
4160
4300
|
results.push(omitUndefinedProperties({
|
|
4161
4301
|
agent: pr.agent,
|
|
4302
|
+
...(pr.sessionName ? { sessionName: pr.sessionName } : {}),
|
|
4162
4303
|
context: pr.context,
|
|
4163
4304
|
agentContract: pr.agentContract,
|
|
4164
4305
|
launchContractDigest: pr.launchContractDigest,
|
|
@@ -4174,9 +4315,6 @@ async function runSubagent(
|
|
|
4174
4315
|
interrupted: pr.interrupted,
|
|
4175
4316
|
timedOut: pr.timedOut,
|
|
4176
4317
|
stopped: pr.stopped,
|
|
4177
|
-
turnBudget: pr.turnBudget,
|
|
4178
|
-
turnBudgetExceeded: pr.turnBudgetExceeded,
|
|
4179
|
-
wrapUpRequested: pr.wrapUpRequested,
|
|
4180
4318
|
toolBudget: pr.toolBudget,
|
|
4181
4319
|
toolBudgetBlocked: pr.toolBudgetBlocked,
|
|
4182
4320
|
sessionFile: pr.sessionFile,
|
|
@@ -4186,6 +4324,7 @@ async function runSubagent(
|
|
|
4186
4324
|
modelAttempts: pr.modelAttempts,
|
|
4187
4325
|
contextOverflow: pr.contextOverflow,
|
|
4188
4326
|
totalCost: pr.totalCost,
|
|
4327
|
+
usage: pr.usage,
|
|
4189
4328
|
artifactPaths: pr.artifactPaths,
|
|
4190
4329
|
transcriptPath: pr.transcriptPath,
|
|
4191
4330
|
transcriptError: pr.transcriptError,
|
|
@@ -4329,6 +4468,23 @@ async function runSubagent(
|
|
|
4329
4468
|
? omitUndefinedProperties({ hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs })
|
|
4330
4469
|
: undefined,
|
|
4331
4470
|
baseDir: config.worktreeBaseDir,
|
|
4471
|
+
beforeCreate: (plannedSetup) => {
|
|
4472
|
+
for (const worktree of plannedSetup.worktrees) setStatusWorktreeReference(requiredStatusStep(statusPayload, groupStartFlatIndex + worktree.index), worktree);
|
|
4473
|
+
const pendingHandoff = writePendingParallelHandoff({
|
|
4474
|
+
manifestPath: parallelHandoffPath(asyncDir),
|
|
4475
|
+
runId: id,
|
|
4476
|
+
mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : "chain",
|
|
4477
|
+
source: "async",
|
|
4478
|
+
cwd,
|
|
4479
|
+
stepIndex,
|
|
4480
|
+
flatStartIndex: groupStartFlatIndex,
|
|
4481
|
+
setup: plannedSetup,
|
|
4482
|
+
laneBindings: handoffWorkflowKey || config.lane ? [{ index: groupStartFlatIndex, taskIndex: 0, ...(handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {}), ...(handoffChildRunId ? { runId: handoffChildRunId } : {}), ...(config.lane ? { lane: config.lane } : {}) }] : undefined,
|
|
4483
|
+
});
|
|
4484
|
+
statusPayload.parallelHandoff = pendingHandoff;
|
|
4485
|
+
statusPayload.lastUpdate = Date.now();
|
|
4486
|
+
writeStatusPayload();
|
|
4487
|
+
},
|
|
4332
4488
|
}));
|
|
4333
4489
|
} catch (error) {
|
|
4334
4490
|
const setupError = error instanceof Error ? error.message : String(error);
|
|
@@ -4353,18 +4509,6 @@ async function runSubagent(
|
|
|
4353
4509
|
}
|
|
4354
4510
|
|
|
4355
4511
|
try {
|
|
4356
|
-
if (worktreeSetup) {
|
|
4357
|
-
writePendingParallelHandoff({
|
|
4358
|
-
manifestPath: parallelHandoffPath(asyncDir),
|
|
4359
|
-
runId: id,
|
|
4360
|
-
mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : "chain",
|
|
4361
|
-
source: "async",
|
|
4362
|
-
cwd,
|
|
4363
|
-
stepIndex,
|
|
4364
|
-
flatStartIndex: groupStartFlatIndex,
|
|
4365
|
-
setup: worktreeSetup,
|
|
4366
|
-
});
|
|
4367
|
-
}
|
|
4368
4512
|
if (group.worktree) ensureParallelProgressFile(cwd, group);
|
|
4369
4513
|
const groupStartTime = Date.now();
|
|
4370
4514
|
markParallelGroupRunning({
|
|
@@ -4401,12 +4545,12 @@ async function runSubagent(
|
|
|
4401
4545
|
appendJsonl(eventsPath, JSON.stringify({
|
|
4402
4546
|
type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0,
|
|
4403
4547
|
}));
|
|
4404
|
-
return omitUndefinedProperties({ agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true });
|
|
4548
|
+
return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true });
|
|
4405
4549
|
}
|
|
4406
|
-
if (timedOut) return timedOutStepResult(task.agent, task.context);
|
|
4407
|
-
if (stopped) return stoppedStepResult(task.agent, task.context);
|
|
4550
|
+
if (timedOut) return timedOutStepResult(task.agent, task.context, task.sessionName);
|
|
4551
|
+
if (stopped) return stoppedStepResult(task.agent, task.context, task.sessionName);
|
|
4408
4552
|
if (childStopRequests.has(fi)) return childStopResult(fi, task.agent, task.context);
|
|
4409
|
-
if (interrupted) return pausedStepResult(task.agent, task.context);
|
|
4553
|
+
if (interrupted) return pausedStepResult(task.agent, task.context, task.sessionName);
|
|
4410
4554
|
if (aborted && failFast) {
|
|
4411
4555
|
const skippedAt = Date.now();
|
|
4412
4556
|
requiredStatusStep(statusPayload, fi).status = "failed";
|
|
@@ -4421,7 +4565,7 @@ async function runSubagent(
|
|
|
4421
4565
|
appendJsonl(eventsPath, JSON.stringify({
|
|
4422
4566
|
type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: -1, durationMs: 0,
|
|
4423
4567
|
}));
|
|
4424
|
-
return omitUndefinedProperties({ agent: task.agent, context: task.context, output: "(skipped — fail-fast)", exitCode: -1 as number | null, skipped: true });
|
|
4568
|
+
return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: "(skipped — fail-fast)", exitCode: -1 as number | null, skipped: true });
|
|
4425
4569
|
}
|
|
4426
4570
|
|
|
4427
4571
|
const taskStartTime = Date.now();
|
|
@@ -4469,20 +4613,19 @@ async function runSubagent(
|
|
|
4469
4613
|
registerInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),
|
|
4470
4614
|
registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
|
|
4471
4615
|
registerStop: (stop) => registerStepStop(fi, stop),
|
|
4472
|
-
registerTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),
|
|
4473
4616
|
timeoutSignal: timeoutAbortController.signal,
|
|
4474
4617
|
stopSignal: stopAbortController.signal,
|
|
4475
4618
|
trackedMutationEvidenceForCompletionGuard: Boolean(worktreeSetup),
|
|
4476
4619
|
timeoutMessage,
|
|
4477
4620
|
stopMessage,
|
|
4478
|
-
turnBudget: config.turnBudget,
|
|
4479
4621
|
toolTimeoutMs: taskForRun.toolTimeoutMs ?? config.toolTimeoutMs,
|
|
4480
|
-
onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),
|
|
4622
|
+
onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
|
|
4481
4623
|
onChildEvent: (event) => updateStepFromChildEvent(fi, event),
|
|
4482
4624
|
onWriterProcess,
|
|
4483
4625
|
onExternalProcess: (process) => updateExternalProcess(fi, process),
|
|
4484
4626
|
onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
|
|
4485
4627
|
skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
|
|
4628
|
+
usageBudgetExhausted: () => refreshUsageBudget()?.exhausted === true,
|
|
4486
4629
|
orcaProgressTab,
|
|
4487
4630
|
}), config.deadlineAt);
|
|
4488
4631
|
if (task.sessionFile) {
|
|
@@ -4500,16 +4643,11 @@ async function runSubagent(
|
|
|
4500
4643
|
requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
|
|
4501
4644
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "timedOut", timedOut || singleResult.timedOut ? true : undefined);
|
|
4502
4645
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "stopped", stopped || childStopped ? true : undefined);
|
|
4503
|
-
setOptionalProperty(requiredStatusStep(statusPayload, fi), "turnBudget", singleResult.turnBudget);
|
|
4504
|
-
setOptionalProperty(requiredStatusStep(statusPayload, fi), "turnBudgetExceeded", singleResult.turnBudgetExceeded);
|
|
4505
|
-
setOptionalProperty(requiredStatusStep(statusPayload, fi), "wrapUpRequested", singleResult.wrapUpRequested);
|
|
4506
4646
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "toolBudget", singleResult.toolBudget);
|
|
4507
4647
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "toolBudgetBlocked", singleResult.toolBudgetBlocked);
|
|
4508
4648
|
if (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;
|
|
4509
4649
|
if (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;
|
|
4510
|
-
|
|
4511
|
-
if (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;
|
|
4512
|
-
if (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;
|
|
4650
|
+
setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
|
|
4513
4651
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
|
|
4514
4652
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
|
|
4515
4653
|
setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
|
|
@@ -4580,13 +4718,21 @@ async function runSubagent(
|
|
|
4580
4718
|
const sessionTokens = config.sessionDir
|
|
4581
4719
|
? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`))
|
|
4582
4720
|
: null;
|
|
4583
|
-
const
|
|
4721
|
+
const fallbackTokens = tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);
|
|
4722
|
+
const observedTokens = requiredStatusStep(statusPayload, fi).tokens;
|
|
4723
|
+
const taskTokens = sessionTokens ?? (fallbackTokens
|
|
4724
|
+
? { ...fallbackTokens, ...(observedTokens?.window !== undefined ? { window: observedTokens.window } : {}), ...(observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {}) }
|
|
4725
|
+
: null);
|
|
4584
4726
|
if (!taskTokens) continue;
|
|
4585
4727
|
requiredStatusStep(statusPayload, fi).tokens = taskTokens;
|
|
4586
4728
|
previousCumulativeTokens = {
|
|
4587
4729
|
input: previousCumulativeTokens.input + taskTokens.input,
|
|
4588
4730
|
output: previousCumulativeTokens.output + taskTokens.output,
|
|
4589
4731
|
total: previousCumulativeTokens.total + taskTokens.total,
|
|
4732
|
+
...(taskTokens.window !== undefined ? { window: taskTokens.window } : {}),
|
|
4733
|
+
...(previousCumulativeTokens.windowPeak !== undefined || taskTokens.windowPeak !== undefined
|
|
4734
|
+
? { windowPeak: Math.max(previousCumulativeTokens.windowPeak ?? 0, taskTokens.windowPeak ?? 0) }
|
|
4735
|
+
: {}),
|
|
4590
4736
|
};
|
|
4591
4737
|
}
|
|
4592
4738
|
statusPayload.totalTokens = { ...previousCumulativeTokens };
|
|
@@ -4610,9 +4756,6 @@ async function runSubagent(
|
|
|
4610
4756
|
interrupted: pr.interrupted,
|
|
4611
4757
|
timedOut: pr.timedOut,
|
|
4612
4758
|
stopped: pr.stopped,
|
|
4613
|
-
turnBudget: pr.turnBudget,
|
|
4614
|
-
turnBudgetExceeded: pr.turnBudgetExceeded,
|
|
4615
|
-
wrapUpRequested: pr.wrapUpRequested,
|
|
4616
4759
|
toolBudget: pr.toolBudget,
|
|
4617
4760
|
toolBudgetBlocked: pr.toolBudgetBlocked,
|
|
4618
4761
|
sessionFile: pr.sessionFile,
|
|
@@ -4622,6 +4765,7 @@ async function runSubagent(
|
|
|
4622
4765
|
modelAttempts: pr.modelAttempts,
|
|
4623
4766
|
contextOverflow: pr.contextOverflow,
|
|
4624
4767
|
totalCost: pr.totalCost,
|
|
4768
|
+
usage: pr.usage,
|
|
4625
4769
|
artifactPaths: pr.artifactPaths,
|
|
4626
4770
|
transcriptPath: pr.transcriptPath,
|
|
4627
4771
|
transcriptError: pr.transcriptError,
|
|
@@ -4675,12 +4819,14 @@ async function runSubagent(
|
|
|
4675
4819
|
diffs: captured.diffs,
|
|
4676
4820
|
results: parallelResults.map((result) => ({
|
|
4677
4821
|
agent: result.agent,
|
|
4822
|
+
...(handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {}),
|
|
4823
|
+
...(handoffChildRunId ? { runId: handoffChildRunId } : {}),
|
|
4824
|
+
...(config.lane ? { lane: config.lane } : {}),
|
|
4678
4825
|
status: result.stopped || (result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
|
|
4679
4826
|
processSignal: result.processSignal,
|
|
4680
4827
|
interrupted: result.interrupted,
|
|
4681
4828
|
timedOut: result.timedOut,
|
|
4682
4829
|
stopped: result.stopped,
|
|
4683
|
-
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
4684
4830
|
}))) ? "stopped" as const : result.interrupted ? "paused" as const : result.exitCode === 0 ? "completed" as const : "failed" as const,
|
|
4685
4831
|
summary: result.output || result.error || "(no output)",
|
|
4686
4832
|
...(result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {}),
|
|
@@ -4726,12 +4872,12 @@ async function runSubagent(
|
|
|
4726
4872
|
} else {
|
|
4727
4873
|
const seqStep = step as SubagentStep;
|
|
4728
4874
|
if (timedOut) {
|
|
4729
|
-
results.push(timedOutStepResult(seqStep.agent, seqStep.context));
|
|
4875
|
+
results.push(timedOutStepResult(seqStep.agent, seqStep.context, seqStep.sessionName));
|
|
4730
4876
|
flatIndex++;
|
|
4731
4877
|
continue;
|
|
4732
4878
|
}
|
|
4733
4879
|
if (stopped) {
|
|
4734
|
-
results.push(stoppedStepResult(seqStep.agent, seqStep.context));
|
|
4880
|
+
results.push(stoppedStepResult(seqStep.agent, seqStep.context, seqStep.sessionName));
|
|
4735
4881
|
flatIndex++;
|
|
4736
4882
|
continue;
|
|
4737
4883
|
}
|
|
@@ -4741,7 +4887,7 @@ async function runSubagent(
|
|
|
4741
4887
|
continue;
|
|
4742
4888
|
}
|
|
4743
4889
|
if (interrupted) {
|
|
4744
|
-
results.push(pausedStepResult(seqStep.agent, seqStep.context));
|
|
4890
|
+
results.push(pausedStepResult(seqStep.agent, seqStep.context, seqStep.sessionName));
|
|
4745
4891
|
flatIndex++;
|
|
4746
4892
|
continue;
|
|
4747
4893
|
}
|
|
@@ -4754,17 +4900,27 @@ async function runSubagent(
|
|
|
4754
4900
|
? omitUndefinedProperties({ hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs })
|
|
4755
4901
|
: undefined,
|
|
4756
4902
|
baseDir: config.worktreeBaseDir,
|
|
4903
|
+
beforeCreate: (plannedSetup) => {
|
|
4904
|
+
const worktree = plannedSetup.worktrees[0];
|
|
4905
|
+
if (worktree) {
|
|
4906
|
+
setStatusWorktreeReference(requiredStatusStep(statusPayload, flatIndex), worktree);
|
|
4907
|
+
}
|
|
4908
|
+
const pendingHandoff = writePendingParallelHandoff({
|
|
4909
|
+
manifestPath: parallelHandoffPath(asyncDir),
|
|
4910
|
+
runId: id,
|
|
4911
|
+
mode: "single",
|
|
4912
|
+
source: "async",
|
|
4913
|
+
cwd,
|
|
4914
|
+
stepIndex,
|
|
4915
|
+
flatStartIndex: flatIndex,
|
|
4916
|
+
setup: plannedSetup,
|
|
4917
|
+
laneBindings: handoffWorkflowKey || config.lane ? [{ index: flatIndex, taskIndex: 0, ...(handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {}), ...(handoffChildRunId ? { runId: handoffChildRunId } : {}), ...(config.lane ? { lane: config.lane } : {}) }] : undefined,
|
|
4918
|
+
});
|
|
4919
|
+
statusPayload.parallelHandoff = pendingHandoff;
|
|
4920
|
+
statusPayload.lastUpdate = Date.now();
|
|
4921
|
+
writeStatusPayload();
|
|
4922
|
+
},
|
|
4757
4923
|
}));
|
|
4758
|
-
writePendingParallelHandoff({
|
|
4759
|
-
manifestPath: parallelHandoffPath(asyncDir),
|
|
4760
|
-
runId: id,
|
|
4761
|
-
mode: "single",
|
|
4762
|
-
source: "async",
|
|
4763
|
-
cwd,
|
|
4764
|
-
stepIndex,
|
|
4765
|
-
flatStartIndex: flatIndex,
|
|
4766
|
-
setup: singleWorktreeSetup,
|
|
4767
|
-
});
|
|
4768
4924
|
} catch (error) {
|
|
4769
4925
|
if (singleWorktreeSetup) cleanupWorktrees(singleWorktreeSetup);
|
|
4770
4926
|
throw error;
|
|
@@ -4817,19 +4973,18 @@ async function runSubagent(
|
|
|
4817
4973
|
registerInterrupt: (interrupt) => registerStepInterrupt(flatIndex, interrupt),
|
|
4818
4974
|
registerTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),
|
|
4819
4975
|
registerStop: (stop) => registerStepStop(flatIndex, stop),
|
|
4820
|
-
registerTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(flatIndex, abort),
|
|
4821
4976
|
timeoutSignal: timeoutAbortController.signal,
|
|
4822
4977
|
stopSignal: stopAbortController.signal,
|
|
4823
4978
|
timeoutMessage,
|
|
4824
4979
|
stopMessage,
|
|
4825
|
-
turnBudget: config.turnBudget,
|
|
4826
4980
|
toolTimeoutMs: seqStep.toolTimeoutMs ?? config.toolTimeoutMs,
|
|
4827
|
-
onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking),
|
|
4981
|
+
onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking, attempt.contextLimit),
|
|
4828
4982
|
onChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),
|
|
4829
4983
|
onWriterProcess,
|
|
4830
4984
|
onExternalProcess: (process) => updateExternalProcess(flatIndex, process),
|
|
4831
4985
|
onExternalJob: (externalJob) => updateExternalJob(flatIndex, externalJob),
|
|
4832
4986
|
skipAcceptance: () => timedOut || stopped || childStopRequests.has(flatIndex),
|
|
4987
|
+
usageBudgetExhausted: () => refreshUsageBudget()?.exhausted === true,
|
|
4833
4988
|
orcaProgressTab,
|
|
4834
4989
|
}), config.deadlineAt);
|
|
4835
4990
|
} catch (error) {
|
|
@@ -4844,6 +4999,7 @@ async function runSubagent(
|
|
|
4844
4999
|
const childStopped = singleResult.stopped === true;
|
|
4845
5000
|
results.push(omitUndefinedProperties({
|
|
4846
5001
|
agent: singleResult.agent,
|
|
5002
|
+
...(singleResult.sessionName ? { sessionName: singleResult.sessionName } : {}),
|
|
4847
5003
|
context: singleResult.context,
|
|
4848
5004
|
agentContract: singleResult.agentContract,
|
|
4849
5005
|
launchContractDigest: singleResult.launchContractDigest,
|
|
@@ -4862,6 +5018,7 @@ async function runSubagent(
|
|
|
4862
5018
|
modelAttempts: singleResult.modelAttempts,
|
|
4863
5019
|
contextOverflow: singleResult.contextOverflow,
|
|
4864
5020
|
totalCost: singleResult.totalCost,
|
|
5021
|
+
usage: singleResult.usage,
|
|
4865
5022
|
artifactPaths: singleResult.artifactPaths,
|
|
4866
5023
|
transcriptPath: singleResult.transcriptPath,
|
|
4867
5024
|
transcriptError: singleResult.transcriptError,
|
|
@@ -4879,9 +5036,6 @@ async function runSubagent(
|
|
|
4879
5036
|
interrupted: singleResult.interrupted,
|
|
4880
5037
|
timedOut: timedOut || singleResult.timedOut ? true : undefined,
|
|
4881
5038
|
stopped: stopped || childStopped ? true : undefined,
|
|
4882
|
-
turnBudget: singleResult.turnBudget,
|
|
4883
|
-
turnBudgetExceeded: singleResult.turnBudgetExceeded,
|
|
4884
|
-
wrapUpRequested: singleResult.wrapUpRequested,
|
|
4885
5039
|
toolBudget: singleResult.toolBudget,
|
|
4886
5040
|
toolBudgetBlocked: singleResult.toolBudgetBlocked,
|
|
4887
5041
|
runner: singleResult.runner,
|
|
@@ -4903,17 +5057,27 @@ async function runSubagent(
|
|
|
4903
5057
|
input: cumulativeTokens.input - previousCumulativeTokens.input,
|
|
4904
5058
|
output: cumulativeTokens.output - previousCumulativeTokens.output,
|
|
4905
5059
|
total: cumulativeTokens.total - previousCumulativeTokens.total,
|
|
5060
|
+
...(cumulativeTokens.window !== undefined ? { window: cumulativeTokens.window } : {}),
|
|
5061
|
+
...(cumulativeTokens.windowPeak !== undefined ? { windowPeak: cumulativeTokens.windowPeak } : {}),
|
|
4906
5062
|
}
|
|
4907
5063
|
: null;
|
|
4908
5064
|
if (cumulativeTokens) {
|
|
4909
5065
|
previousCumulativeTokens = cumulativeTokens;
|
|
4910
5066
|
} else {
|
|
4911
|
-
|
|
5067
|
+
const fallbackTokens = tokenUsageFromAttempts(singleResult.modelAttempts);
|
|
5068
|
+
const observedTokens = requiredStatusStep(statusPayload, flatIndex).tokens;
|
|
5069
|
+
stepTokens = fallbackTokens
|
|
5070
|
+
? { ...fallbackTokens, ...(observedTokens?.window !== undefined ? { window: observedTokens.window } : {}), ...(observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {}) }
|
|
5071
|
+
: null;
|
|
4912
5072
|
if (stepTokens) {
|
|
4913
5073
|
previousCumulativeTokens = {
|
|
4914
5074
|
input: previousCumulativeTokens.input + stepTokens.input,
|
|
4915
5075
|
output: previousCumulativeTokens.output + stepTokens.output,
|
|
4916
5076
|
total: previousCumulativeTokens.total + stepTokens.total,
|
|
5077
|
+
...(stepTokens.window !== undefined ? { window: stepTokens.window } : {}),
|
|
5078
|
+
...(previousCumulativeTokens.windowPeak !== undefined || stepTokens.windowPeak !== undefined
|
|
5079
|
+
? { windowPeak: Math.max(previousCumulativeTokens.windowPeak ?? 0, stepTokens.windowPeak ?? 0) }
|
|
5080
|
+
: {}),
|
|
4917
5081
|
};
|
|
4918
5082
|
}
|
|
4919
5083
|
}
|
|
@@ -4926,16 +5090,11 @@ async function runSubagent(
|
|
|
4926
5090
|
requiredStatusStep(statusPayload, flatIndex).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
|
|
4927
5091
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "timedOut", timedOut || singleResult.timedOut ? true : undefined);
|
|
4928
5092
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "stopped", stopped || childStopped ? true : undefined);
|
|
4929
|
-
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "turnBudget", singleResult.turnBudget);
|
|
4930
|
-
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "turnBudgetExceeded", singleResult.turnBudgetExceeded);
|
|
4931
|
-
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "wrapUpRequested", singleResult.wrapUpRequested);
|
|
4932
5093
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "toolBudget", singleResult.toolBudget);
|
|
4933
5094
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "toolBudgetBlocked", singleResult.toolBudgetBlocked);
|
|
4934
5095
|
if (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;
|
|
4935
5096
|
if (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;
|
|
4936
|
-
|
|
4937
|
-
if (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;
|
|
4938
|
-
if (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;
|
|
5097
|
+
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "sessionName", singleResult.sessionName);
|
|
4939
5098
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "model", singleResult.model);
|
|
4940
5099
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, flatIndex).thinking));
|
|
4941
5100
|
setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "attemptedModels", singleResult.attemptedModels);
|
|
@@ -4996,6 +5155,9 @@ async function runSubagent(
|
|
|
4996
5155
|
diffs,
|
|
4997
5156
|
results: [{
|
|
4998
5157
|
agent: singleResult.agent,
|
|
5158
|
+
...(handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {}),
|
|
5159
|
+
...(handoffChildRunId ? { runId: handoffChildRunId } : {}),
|
|
5160
|
+
...(config.lane ? { lane: config.lane } : {}),
|
|
4999
5161
|
status: singleResult.stopped ? "stopped" as const : singleResult.interrupted ? "paused" as const : singleResult.exitCode === 0 ? "completed" as const : "failed" as const,
|
|
5000
5162
|
summary: singleResult.output || singleResult.error || "(no output)",
|
|
5001
5163
|
...(singleResult.artifactPaths?.outputPath ? { outputPath: singleResult.artifactPaths.outputPath } : {}),
|
|
@@ -5048,7 +5210,7 @@ async function runSubagent(
|
|
|
5048
5210
|
}
|
|
5049
5211
|
}
|
|
5050
5212
|
|
|
5051
|
-
let summary = results.map((r) => `${r.agent}:\n${r.output}`).join("\n\n");
|
|
5213
|
+
let summary = results.map((r) => `${r.agent}:\n${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join("\n\n");
|
|
5052
5214
|
let truncated = false;
|
|
5053
5215
|
|
|
5054
5216
|
if (maxOutput) {
|
|
@@ -5116,14 +5278,14 @@ async function runSubagent(
|
|
|
5116
5278
|
if (!timedOut && !stopped && !interrupted && config.timeoutMs !== undefined && results.some((result) => result.timedOut === true && result.error === timeoutMessage)) {
|
|
5117
5279
|
timedOut = true;
|
|
5118
5280
|
}
|
|
5119
|
-
const signalTerminated = !stopped && !timedOut && !
|
|
5281
|
+
const signalTerminated = !stopped && !timedOut && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
|
|
5120
5282
|
processSignal: result.processSignal,
|
|
5121
5283
|
interrupted: result.interrupted,
|
|
5122
5284
|
timedOut: result.timedOut,
|
|
5123
5285
|
stopped: result.stopped,
|
|
5124
|
-
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
5125
5286
|
})));
|
|
5126
|
-
|
|
5287
|
+
const partialWithEvidence = !stopped && !signalTerminated && !timedOut && !usageBudgetExceeded && !interrupted && results.some(partialEvidenceResult) && !results.some(concreteFailureResult);
|
|
5288
|
+
statusPayload.state = stopped || signalTerminated ? "stopped" : timedOut || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : partialWithEvidence ? "partial" : "failed";
|
|
5127
5289
|
closeSteerInbox(asyncDir, statusPayload.state, (filePath, payload) => runPersistence.write(filePath, payload));
|
|
5128
5290
|
disposeControlInbox();
|
|
5129
5291
|
for (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);
|
|
@@ -5153,13 +5315,17 @@ async function runSubagent(
|
|
|
5153
5315
|
statusPayload.timedOut = true;
|
|
5154
5316
|
statusPayload.error = timeoutMessage ?? "Subagent timed out.";
|
|
5155
5317
|
}
|
|
5156
|
-
if (turnBudgetExceeded && !statusPayload.error) {
|
|
5157
|
-
const budget = statusPayload.turnBudget;
|
|
5158
|
-
statusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : "Subagent exceeded turn budget.";
|
|
5159
|
-
}
|
|
5160
5318
|
if (usageBudgetExceeded && statusPayload.usageBudget && !statusPayload.error) {
|
|
5161
5319
|
statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
5162
5320
|
}
|
|
5321
|
+
if (partialWithEvidence) {
|
|
5322
|
+
const partialResult = results.find(partialEvidenceResult);
|
|
5323
|
+
statusPayload.activityState = "needs_attention";
|
|
5324
|
+
statusPayload.error = partialResult?.error ?? statusPayload.error;
|
|
5325
|
+
for (const step of statusPayload.steps) {
|
|
5326
|
+
if (step.status === "failed") step.activityState = "needs_attention";
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5163
5329
|
statusPayload.endedAt = runEndedAt;
|
|
5164
5330
|
statusPayload.lastUpdate = runEndedAt;
|
|
5165
5331
|
setOptionalProperty(statusPayload, "sessionFile", effectiveSessionFile);
|
|
@@ -5169,8 +5335,10 @@ async function runSubagent(
|
|
|
5169
5335
|
setOptionalProperty(statusPayload, "shareUrl", shareUrl);
|
|
5170
5336
|
setOptionalProperty(statusPayload, "gistUrl", gistUrl);
|
|
5171
5337
|
setOptionalProperty(statusPayload, "shareError", shareError);
|
|
5172
|
-
if (statusPayload.state === "failed" && !statusPayload.error) {
|
|
5173
|
-
const
|
|
5338
|
+
if ((statusPayload.state === "failed" || statusPayload.state === "partial") && !statusPayload.error) {
|
|
5339
|
+
const concreteFailure = results.find(concreteFailureResult);
|
|
5340
|
+
const failedStep = concreteFailure ? undefined : statusPayload.steps.find((s) => s.status === "failed");
|
|
5341
|
+
if (concreteFailure?.error) statusPayload.error = concreteFailure.error;
|
|
5174
5342
|
if (failedStep?.agent) {
|
|
5175
5343
|
statusPayload.error = `Step failed: ${failedStep.agent}`;
|
|
5176
5344
|
}
|
|
@@ -5182,20 +5350,18 @@ async function runSubagent(
|
|
|
5182
5350
|
id,
|
|
5183
5351
|
agent: agentName,
|
|
5184
5352
|
mode: resultMode,
|
|
5185
|
-
success:
|
|
5186
|
-
state:
|
|
5187
|
-
summary: stopped ? stopMessage : signalTerminated ? (statusPayload.error ?? "Subagent process terminated by signal.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") :
|
|
5353
|
+
success: statusPayload.state === "complete",
|
|
5354
|
+
state: statusPayload.state,
|
|
5355
|
+
summary: stopped ? stopMessage : signalTerminated ? (statusPayload.error ?? "Subagent process terminated by signal.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : usageBudgetExceeded ? (statusPayload.error ?? "Usage budget exhausted.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : statusPayload.state === "partial" ? (statusPayload.error ?? summary) : summary,
|
|
5188
5356
|
...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),
|
|
5189
5357
|
...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
|
|
5190
|
-
...(statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {}),
|
|
5191
|
-
...(statusPayload.turnBudgetExceeded ? { turnBudgetExceeded: true } : {}),
|
|
5192
|
-
...(statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {}),
|
|
5193
5358
|
...(statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {}),
|
|
5194
5359
|
...(statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {}),
|
|
5195
5360
|
...(statusPayload.usageBudget ? { usageBudget: statusPayload.usageBudget } : {}),
|
|
5196
|
-
...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } :
|
|
5361
|
+
...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } : usageBudgetExceeded ? { error: statusPayload.error ?? "Usage budget exhausted." } : {}),
|
|
5197
5362
|
results: results.map((r) => omitUndefinedProperties({
|
|
5198
5363
|
agent: r.agent,
|
|
5364
|
+
...(r.sessionName ? { sessionName: r.sessionName } : {}),
|
|
5199
5365
|
context: r.context,
|
|
5200
5366
|
output: r.output,
|
|
5201
5367
|
outputState: r.outputState,
|
|
@@ -5207,9 +5373,6 @@ async function runSubagent(
|
|
|
5207
5373
|
timedOut: r.timedOut || undefined,
|
|
5208
5374
|
stopped: r.stopped || undefined,
|
|
5209
5375
|
processSignal: r.processSignal || undefined,
|
|
5210
|
-
turnBudget: r.turnBudget,
|
|
5211
|
-
turnBudgetExceeded: r.turnBudgetExceeded || undefined,
|
|
5212
|
-
wrapUpRequested: r.wrapUpRequested || undefined,
|
|
5213
5376
|
toolBudget: r.toolBudget,
|
|
5214
5377
|
toolBudgetBlocked: r.toolBudgetBlocked || undefined,
|
|
5215
5378
|
sessionFile: r.sessionFile,
|
|
@@ -5219,6 +5382,7 @@ async function runSubagent(
|
|
|
5219
5382
|
modelAttempts: r.modelAttempts,
|
|
5220
5383
|
contextOverflow: r.contextOverflow,
|
|
5221
5384
|
totalCost: r.totalCost,
|
|
5385
|
+
usage: r.usage,
|
|
5222
5386
|
artifactPaths: r.artifactPaths,
|
|
5223
5387
|
outputSaveError: r.outputSaveError,
|
|
5224
5388
|
metadataSaveError: r.metadataSaveError,
|
|
@@ -5251,7 +5415,7 @@ async function runSubagent(
|
|
|
5251
5415
|
capabilityAudit: statusPayload.capabilityAudit,
|
|
5252
5416
|
...(config.parentWorkflowRunId ? { parentWorkflowRunId: config.parentWorkflowRunId } : {}),
|
|
5253
5417
|
...(config.workflowKey ? { workflowKey: config.workflowKey } : {}),
|
|
5254
|
-
exitCode:
|
|
5418
|
+
exitCode: statusPayload.state === "complete" || statusPayload.state === "paused" ? 0 : 1,
|
|
5255
5419
|
timestamp: runEndedAt,
|
|
5256
5420
|
durationMs: runEndedAt - overallStartTime,
|
|
5257
5421
|
totalTokens: statusPayload.totalTokens,
|
|
@@ -5359,7 +5523,7 @@ async function waitForStartupControl(
|
|
|
5359
5523
|
} catch (error) {
|
|
5360
5524
|
throw new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);
|
|
5361
5525
|
}
|
|
5362
|
-
if (payload.token !== token) throw new Error("Runner startup control token does not match
|
|
5526
|
+
if (payload.token !== token) throw new Error("Runner startup control token does not match.");
|
|
5363
5527
|
if (payload.action === action) return;
|
|
5364
5528
|
if (payload.action !== "ack" && payload.action !== "proceed") throw new Error("Runner startup control action is invalid.");
|
|
5365
5529
|
}
|
|
@@ -5370,7 +5534,7 @@ async function waitForStartupControl(
|
|
|
5370
5534
|
|
|
5371
5535
|
async function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {
|
|
5372
5536
|
let lease: ReturnType<typeof acquireSessionLease> | undefined;
|
|
5373
|
-
let startupCommitted = config.revivalLease === undefined;
|
|
5537
|
+
let startupCommitted = config.revivalLease === undefined && config.launchBarrierToken === undefined;
|
|
5374
5538
|
const startupPath = path.join(config.asyncDir, "runner-startup.json");
|
|
5375
5539
|
const startupAckPath = path.join(config.asyncDir, "runner-startup-ack.json");
|
|
5376
5540
|
const startupProceedPath = path.join(config.asyncDir, "runner-startup-proceed.json");
|
|
@@ -5383,7 +5547,15 @@ async function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
5383
5547
|
};
|
|
5384
5548
|
process.once("exit", releaseOnExit);
|
|
5385
5549
|
try {
|
|
5386
|
-
if (config.
|
|
5550
|
+
if (config.launchBarrierToken) {
|
|
5551
|
+
await waitForStartupControl(startupProceedPath, config.launchBarrierToken, "proceed");
|
|
5552
|
+
startupCommitted = true;
|
|
5553
|
+
try {
|
|
5554
|
+
fs.rmSync(startupProceedPath, { force: true });
|
|
5555
|
+
} catch {
|
|
5556
|
+
// Startup control cleanup is best effort after the parent commits the run.
|
|
5557
|
+
}
|
|
5558
|
+
} else if (config.revivalLease) {
|
|
5387
5559
|
lease = acquireSessionLease(config.revivalLease);
|
|
5388
5560
|
config.revivalLeaseToken = lease.owner.token;
|
|
5389
5561
|
writeAtomicJson(startupPath, { state: "ready", token: lease.owner.token, pid: process.pid, owner: lease.owner });
|
|
@@ -5401,7 +5573,7 @@ async function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
5401
5573
|
}
|
|
5402
5574
|
await runSubagent(config, lease ? (writer) => lease!.updateWriter(writer) : undefined);
|
|
5403
5575
|
} catch (error) {
|
|
5404
|
-
if (
|
|
5576
|
+
if (!startupCommitted) {
|
|
5405
5577
|
try {
|
|
5406
5578
|
writeAtomicJson(startupPath, { state: "error", pid: process.pid, error: error instanceof Error ? error.message : String(error) });
|
|
5407
5579
|
} catch {
|