pi-subagents 0.70.0 → 0.71.0
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 +72 -0
- package/README.md +4 -2
- package/agents/claude-code-writer.md +1 -0
- package/agents/codex-exec-writer.md +1 -0
- package/agents/cursor-agent-writer.md +1 -0
- package/agents/worker.md +3 -2
- package/docs/agents.md +7 -8
- package/docs/configuration.md +17 -1
- package/docs/extension-api.md +5 -1
- package/docs/models.md +1 -1
- package/docs/observability.md +17 -13
- package/docs/standalone-background.md +4 -4
- package/docs/tool-reference.md +9 -11
- package/docs/workflows.md +1 -1
- package/inspector-runner.mjs +1 -1
- package/package.json +2 -2
- package/skills/pi-subagents/SKILL.md +1 -0
- package/skills/pi-subagents/references/constraints-and-recipes.md +5 -2
- package/skills/pi-subagents/references/execution-controls.md +2 -2
- package/skills/pi-subagents/references/management-authoring-rpc.md +3 -3
- package/skills/pi-subagents/references/multi-lane-orchestration.md +8 -0
- package/skills/pi-subagents/references/prompting-and-roles.md +14 -13
- package/src/agents/agent-management.d.ts.map +1 -1
- package/src/agents/agent-management.js +11 -25
- package/src/agents/agent-management.js.map +1 -1
- package/src/agents/agent-serializer.d.ts.map +1 -1
- package/src/agents/agent-serializer.js +0 -4
- package/src/agents/agent-serializer.js.map +1 -1
- package/src/agents/agents.d.ts +17 -4
- package/src/agents/agents.d.ts.map +1 -1
- package/src/agents/agents.js +39 -22
- package/src/agents/agents.js.map +1 -1
- package/src/agents/proactive-skills.d.ts +1 -0
- package/src/agents/proactive-skills.d.ts.map +1 -1
- package/src/agents/proactive-skills.js +3 -1
- package/src/agents/proactive-skills.js.map +1 -1
- package/src/agents/runtime-agent-registry.d.ts +8 -3
- package/src/agents/runtime-agent-registry.d.ts.map +1 -1
- package/src/agents/runtime-agent-registry.js +14 -9
- package/src/agents/runtime-agent-registry.js.map +1 -1
- package/src/agents/skills.d.ts +2 -0
- package/src/agents/skills.d.ts.map +1 -1
- package/src/agents/skills.js +41 -8
- package/src/agents/skills.js.map +1 -1
- package/src/api/delegation.d.ts +14 -0
- package/src/api/delegation.d.ts.map +1 -1
- package/src/extension/index.d.ts.map +1 -1
- package/src/extension/index.js +5 -1
- package/src/extension/index.js.map +1 -1
- package/src/extension/rpc.d.ts +1 -1
- package/src/extension/rpc.d.ts.map +1 -1
- package/src/extension/rpc.js +11 -1
- package/src/extension/rpc.js.map +1 -1
- package/src/extension/tool-activation.d.ts +9 -0
- package/src/extension/tool-activation.d.ts.map +1 -0
- package/src/extension/tool-activation.js +172 -0
- package/src/extension/tool-activation.js.map +1 -0
- package/src/extension/tool-description.d.ts +4 -4
- package/src/extension/tool-description.d.ts.map +1 -1
- package/src/extension/tool-description.js +1 -1
- package/src/intercom/intercom-bridge.d.ts.map +1 -1
- package/src/intercom/intercom-bridge.js +2 -0
- package/src/intercom/intercom-bridge.js.map +1 -1
- package/src/runs/background/active-async-capacity.d.ts.map +1 -1
- package/src/runs/background/active-async-capacity.js +4 -33
- package/src/runs/background/active-async-capacity.js.map +1 -1
- package/src/runs/background/async-execution.d.ts.map +1 -1
- package/src/runs/background/async-execution.js +5 -67
- package/src/runs/background/async-execution.js.map +1 -1
- package/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/src/runs/background/async-job-tracker.js +25 -19
- package/src/runs/background/async-job-tracker.js.map +1 -1
- package/src/runs/background/async-resume.d.ts +1 -1
- package/src/runs/background/async-resume.d.ts.map +1 -1
- package/src/runs/background/async-resume.js +8 -6
- package/src/runs/background/async-resume.js.map +1 -1
- package/src/runs/background/async-status.d.ts +1 -0
- package/src/runs/background/async-status.d.ts.map +1 -1
- package/src/runs/background/async-status.js +1 -0
- package/src/runs/background/async-status.js.map +1 -1
- package/src/runs/background/binary-bootstrap.d.ts.map +1 -1
- package/src/runs/background/binary-bootstrap.js +28 -6
- package/src/runs/background/binary-bootstrap.js.map +1 -1
- package/src/runs/background/fleet-view.d.ts.map +1 -1
- package/src/runs/background/fleet-view.js +26 -7
- package/src/runs/background/fleet-view.js.map +1 -1
- package/src/runs/background/notify.d.ts +11 -0
- package/src/runs/background/notify.d.ts.map +1 -1
- package/src/runs/background/notify.js +71 -3
- package/src/runs/background/notify.js.map +1 -1
- package/src/runs/background/process-terminal-candidate.d.ts +18 -0
- package/src/runs/background/process-terminal-candidate.d.ts.map +1 -0
- package/src/runs/background/process-terminal-candidate.js +97 -0
- package/src/runs/background/process-terminal-candidate.js.map +1 -0
- package/src/runs/background/process-terminal.d.ts +3 -15
- package/src/runs/background/process-terminal.d.ts.map +1 -1
- package/src/runs/background/process-terminal.js +19 -96
- package/src/runs/background/process-terminal.js.map +1 -1
- package/src/runs/background/retained-children.d.ts.map +1 -1
- package/src/runs/background/retained-children.js +3 -2
- package/src/runs/background/retained-children.js.map +1 -1
- package/src/runs/background/run-child-session.d.ts +1 -0
- package/src/runs/background/run-child-session.d.ts.map +1 -1
- package/src/runs/background/run-child-session.js.map +1 -1
- package/src/runs/background/run-status.d.ts.map +1 -1
- package/src/runs/background/run-status.js +11 -5
- package/src/runs/background/run-status.js.map +1 -1
- package/src/runs/background/runner-aliases.d.ts.map +1 -1
- package/src/runs/background/runner-aliases.js +28 -16
- package/src/runs/background/runner-aliases.js.map +1 -1
- package/src/runs/background/runner-startup-failure.d.ts +14 -0
- package/src/runs/background/runner-startup-failure.d.ts.map +1 -0
- package/src/runs/background/runner-startup-failure.js +47 -0
- package/src/runs/background/runner-startup-failure.js.map +1 -0
- package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
- package/src/runs/background/stale-run-reconciler.js +9 -1
- package/src/runs/background/stale-run-reconciler.js.map +1 -1
- package/src/runs/background/subagent-runner-bootstrap.d.ts +14 -0
- package/src/runs/background/subagent-runner-bootstrap.d.ts.map +1 -0
- package/src/runs/background/subagent-runner-bootstrap.js +277 -0
- package/src/runs/background/subagent-runner-bootstrap.js.map +1 -0
- package/src/runs/background/subagent-runner.d.ts +5 -7
- package/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/src/runs/background/subagent-runner.js +67 -274
- package/src/runs/background/subagent-runner.js.map +1 -1
- package/src/runs/background/workflow-terminal-proof.d.ts +18 -0
- package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -0
- package/src/runs/background/workflow-terminal-proof.js +68 -0
- package/src/runs/background/workflow-terminal-proof.js.map +1 -0
- package/src/runs/foreground/execution.d.ts.map +1 -1
- package/src/runs/foreground/execution.js +43 -111
- package/src/runs/foreground/execution.js.map +1 -1
- package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/src/runs/foreground/subagent-executor.js +108 -17
- package/src/runs/foreground/subagent-executor.js.map +1 -1
- package/src/runs/shared/acceptance.d.ts.map +1 -1
- package/src/runs/shared/acceptance.js +7 -40
- package/src/runs/shared/acceptance.js.map +1 -1
- package/src/runs/shared/child-hooks.d.ts +1 -3
- package/src/runs/shared/child-hooks.d.ts.map +1 -1
- package/src/runs/shared/child-hooks.js +1 -16
- package/src/runs/shared/child-hooks.js.map +1 -1
- package/src/runs/shared/child-launch.d.ts +0 -2
- package/src/runs/shared/child-launch.d.ts.map +1 -1
- package/src/runs/shared/child-launch.js +4 -2
- package/src/runs/shared/child-launch.js.map +1 -1
- package/src/runs/shared/child-runtime-config.d.ts +4 -0
- package/src/runs/shared/child-runtime-config.d.ts.map +1 -1
- package/src/runs/shared/child-runtime-config.js.map +1 -1
- package/src/runs/shared/child-session.d.ts +8 -9
- package/src/runs/shared/child-session.d.ts.map +1 -1
- package/src/runs/shared/child-session.js +67 -2
- package/src/runs/shared/child-session.js.map +1 -1
- package/src/runs/shared/dynamic-fanout.js +1 -1
- package/src/runs/shared/dynamic-fanout.js.map +1 -1
- package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
- package/src/runs/shared/external-cli-runner.js +3 -1
- package/src/runs/shared/external-cli-runner.js.map +1 -1
- package/src/runs/shared/git-environment.d.ts +3 -0
- package/src/runs/shared/git-environment.d.ts.map +1 -0
- package/src/runs/shared/git-environment.js +28 -0
- package/src/runs/shared/git-environment.js.map +1 -0
- package/src/runs/shared/mcp-config-sources.d.ts +3 -0
- package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
- package/src/runs/shared/mcp-config-sources.js.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.js +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
- package/src/runs/shared/mcp-direct-tool-grant.d.ts +3 -1
- package/src/runs/shared/mcp-direct-tool-grant.d.ts.map +1 -1
- package/src/runs/shared/mcp-direct-tool-grant.js +19 -5
- package/src/runs/shared/mcp-direct-tool-grant.js.map +1 -1
- package/src/runs/shared/parallel-utils.d.ts +0 -1
- package/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/src/runs/shared/parallel-utils.js.map +1 -1
- package/src/runs/shared/pi-spawn.d.ts +10 -1
- package/src/runs/shared/pi-spawn.d.ts.map +1 -1
- package/src/runs/shared/pi-spawn.js +86 -7
- package/src/runs/shared/pi-spawn.js.map +1 -1
- package/src/runs/shared/single-output.d.ts.map +1 -1
- package/src/runs/shared/single-output.js +10 -2
- package/src/runs/shared/single-output.js.map +1 -1
- package/src/runs/shared/structured-output.d.ts +7 -0
- package/src/runs/shared/structured-output.d.ts.map +1 -1
- package/src/runs/shared/structured-output.js +74 -0
- package/src/runs/shared/structured-output.js.map +1 -1
- package/src/runs/shared/subagent-control.d.ts.map +1 -1
- package/src/runs/shared/subagent-control.js +6 -19
- package/src/runs/shared/subagent-control.js.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.js +23 -7
- package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/src/runs/shared/tool-availability.js +1 -1
- package/src/runs/shared/tool-availability.js.map +1 -1
- package/src/shared/child-session-name.d.ts.map +1 -1
- package/src/shared/child-session-name.js +4 -2
- package/src/shared/child-session-name.js.map +1 -1
- package/src/shared/fork-context.d.ts +4 -0
- package/src/shared/fork-context.d.ts.map +1 -1
- package/src/shared/fork-context.js +9 -4
- package/src/shared/fork-context.js.map +1 -1
- package/src/shared/launch-contract.d.ts.map +1 -1
- package/src/shared/launch-contract.js +0 -1
- package/src/shared/launch-contract.js.map +1 -1
- package/src/shared/pruned-fork.d.ts +1 -1
- package/src/shared/pruned-fork.d.ts.map +1 -1
- package/src/shared/pruned-fork.js +70 -65
- package/src/shared/pruned-fork.js.map +1 -1
- package/src/shared/types.d.ts +32 -13
- package/src/shared/types.d.ts.map +1 -1
- package/src/shared/types.js +2 -0
- package/src/shared/types.js.map +1 -1
- package/src/slash/delegation-adapters.d.ts +7 -1
- package/src/slash/delegation-adapters.d.ts.map +1 -1
- package/src/slash/delegation-adapters.js +17 -0
- package/src/slash/delegation-adapters.js.map +1 -1
- package/src/slash/prompt-template-bridge.d.ts.map +1 -1
- package/src/slash/prompt-template-bridge.js +14 -1
- package/src/slash/prompt-template-bridge.js.map +1 -1
- package/src/slash/prompt-workflows.d.ts.map +1 -1
- package/src/slash/prompt-workflows.js +16 -2
- package/src/slash/prompt-workflows.js.map +1 -1
- package/src/slash/slash-commands.d.ts.map +1 -1
- package/src/slash/slash-commands.js +5 -251
- package/src/slash/slash-commands.js.map +1 -1
- package/src/slash/subagent-cost.d.ts +29 -0
- package/src/slash/subagent-cost.d.ts.map +1 -0
- package/src/slash/subagent-cost.js +271 -0
- package/src/slash/subagent-cost.js.map +1 -0
- package/src/slash/subagents-admin.d.ts.map +1 -1
- package/src/slash/subagents-admin.js +4 -5
- package/src/slash/subagents-admin.js.map +1 -1
- package/src/tui/fleet.d.ts.map +1 -1
- package/src/tui/fleet.js +4 -0
- package/src/tui/fleet.js.map +1 -1
- package/src/tui/render.d.ts.map +1 -1
- package/src/tui/render.js +16 -11
- package/src/tui/render.js.map +1 -1
- package/src/watchdog/diff-tool.d.ts +2 -1
- package/src/watchdog/diff-tool.d.ts.map +1 -1
- package/src/watchdog/diff-tool.js +9 -3
- package/src/watchdog/diff-tool.js.map +1 -1
- package/src/watchdog/permission-arbiter.d.ts.map +1 -1
- package/src/watchdog/permission-arbiter.js +12 -8
- package/src/watchdog/permission-arbiter.js.map +1 -1
- package/src/watchdog/register-child.d.ts +3 -1
- package/src/watchdog/register-child.d.ts.map +1 -1
- package/src/watchdog/register-child.js +12 -3
- package/src/watchdog/register-child.js.map +1 -1
- package/src/watchdog/review.d.ts +1 -0
- package/src/watchdog/review.d.ts.map +1 -1
- package/src/watchdog/review.js +12 -6
- package/src/watchdog/review.js.map +1 -1
- package/src/watchdog/runtime.d.ts +1 -1
- package/src/watchdog/runtime.d.ts.map +1 -1
- package/src/watchdog/runtime.js +2 -1
- package/src/watchdog/runtime.js.map +1 -1
- package/src/watchdog/turn-delta.d.ts +5 -1
- package/src/watchdog/turn-delta.d.ts.map +1 -1
- package/src/watchdog/turn-delta.js +9 -5
- package/src/watchdog/turn-delta.js.map +1 -1
- package/src/workflows/scripted-workflow.d.ts.map +1 -1
- package/src/workflows/scripted-workflow.js +1 -3
- package/src/workflows/scripted-workflow.js.map +1 -1
- package/src/runs/shared/completion-evidence.d.ts +0 -31
- package/src/runs/shared/completion-evidence.d.ts.map +0 -1
- package/src/runs/shared/completion-evidence.js +0 -54
- package/src/runs/shared/completion-evidence.js.map +0 -1
- package/src/runs/shared/completion-guard.d.ts +0 -35
- package/src/runs/shared/completion-guard.d.ts.map +0 -1
- package/src/runs/shared/completion-guard.js +0 -214
- package/src/runs/shared/completion-guard.js.map +0 -1
- package/src/runs/shared/llm-intent-arbiter.d.ts +0 -48
- package/src/runs/shared/llm-intent-arbiter.d.ts.map +0 -1
- package/src/runs/shared/llm-intent-arbiter.js +0 -235
- package/src/runs/shared/llm-intent-arbiter.js.map +0 -1
- package/src/runs/shared/task-intent.d.ts +0 -38
- package/src/runs/shared/task-intent.d.ts.map +0 -1
- package/src/runs/shared/task-intent.js +0 -213
- package/src/runs/shared/task-intent.js.map +0 -1
|
@@ -11,12 +11,7 @@ import * as fs from "node:fs";
|
|
|
11
11
|
import * as path from "node:path";
|
|
12
12
|
import { performance } from "node:perf_hooks";
|
|
13
13
|
import { pathToFileURL } from "node:url";
|
|
14
|
-
import { arbitrateCompletionGuardRescue, createTaskMutationArbiter } from "../shared/llm-intent-arbiter.js";
|
|
15
14
|
import { installRunnerHttpDispatcher } from "./runner-http-dispatcher.js";
|
|
16
|
-
const isRunnerEntrypoint = Boolean(process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href);
|
|
17
|
-
// Detached Node runners skip Pi's CLI dispatcher setup; install the runner's own.
|
|
18
|
-
if (isRunnerEntrypoint)
|
|
19
|
-
installRunnerHttpDispatcher({ agentDir: getAgentDir(), cwd: process.cwd() });
|
|
20
15
|
import { writeAtomicJson } from "../../shared/atomic-json.js";
|
|
21
16
|
import { writeAsyncResultFile, writePendingAsyncResultFile } from "./result-files.js";
|
|
22
17
|
import { createFileCoalescer } from "../../shared/file-coalescer.js";
|
|
@@ -42,7 +37,7 @@ import { SUBAGENT_CHILD_ENV } from "../shared/child-runtime-config.js";
|
|
|
42
37
|
import { deriveChildSessionName } from "../../shared/child-session-name.js";
|
|
43
38
|
import { alignForkedSessionCwd } from "../../shared/fork-session-cwd.js";
|
|
44
39
|
import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.js";
|
|
45
|
-
import { clearStructuredOutputCaptures, createStructuredOutputFileCapture, createStructuredOutputRuntime, MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput, readStructuredOutputAcceptanceReport } from "../shared/structured-output.js";
|
|
40
|
+
import { clearStructuredOutputCaptures, createStructuredOutputFileCapture, createStructuredOutputRuntime, formatStructuredOutputRejectionError, MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput, readStructuredOutputAcceptanceReport } from "../shared/structured-output.js";
|
|
46
41
|
import { formatMidToolExitError, isOrdinaryToolForMidToolExit, isUnexplainedProcessSignal } from "../shared/process-signal.js";
|
|
47
42
|
import { formatChildToolDiagnostic } from "../shared/tool-availability.js";
|
|
48
43
|
import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTrackedMutations } from "../shared/mutation-evidence.js";
|
|
@@ -50,11 +45,10 @@ import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelSt
|
|
|
50
45
|
import { claimRunFanoutBatch, getRunFanoutBudgetSnapshot } from "../shared/run-fanout-budget.js";
|
|
51
46
|
import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.js";
|
|
52
47
|
import { isContextOverflow } from "../shared/model-resolution.js";
|
|
53
|
-
import {
|
|
48
|
+
import { processTerminalPath, writeProcessTerminalCandidate } from "./process-terminal.js";
|
|
49
|
+
import { persistRunnerStartupFailure } from "./runner-startup-failure.js";
|
|
54
50
|
import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, unconsumedSteerReason, updateSteeringTarget } from "./steering.js";
|
|
55
51
|
import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getAgentDir, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.js";
|
|
56
|
-
import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.js";
|
|
57
|
-
import { planCompletionEvidence, projectSettlementDiagnostic } from "../shared/completion-evidence.js";
|
|
58
52
|
import { planAbortRecovery } from "../shared/abort-recovery.js";
|
|
59
53
|
import { createMutatingFailureState, didMutatingToolFail, isMutatingTool, nextLongRunningTrigger, recordMutatingFailure, resetMutatingFailureState, resolveCurrentPath, shouldEscalateMutatingFailures, summarizeRecentMutatingFailures, } from "../shared/long-running-guard.js";
|
|
60
54
|
import { parseSessionTokens } from "../../shared/session-tokens.js";
|
|
@@ -74,7 +68,6 @@ import { toolTimeoutCallKey } from "../shared/tool-timeout.js";
|
|
|
74
68
|
import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.js";
|
|
75
69
|
import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.js";
|
|
76
70
|
import { resolveWatchdogConfig } from "../../watchdog/settings.js";
|
|
77
|
-
import { acquireSessionLease } from "../shared/session-lease.js";
|
|
78
71
|
import { buildExternalCliPrompt, runExternalCli } from "../shared/external-cli-runner.js";
|
|
79
72
|
import { resolveClaudeCodeLaunch } from "../shared/claude-code-adapter.js";
|
|
80
73
|
import { resolveCodexExecLaunch } from "../shared/codex-exec-adapter.js";
|
|
@@ -507,7 +500,6 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
507
500
|
let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
|
|
508
501
|
if (ctx.outputs)
|
|
509
502
|
task = resolveOutputReferences(task, ctx.outputs);
|
|
510
|
-
const taskForCompletionGuard = task;
|
|
511
503
|
let resolvedTaskToolPlan;
|
|
512
504
|
if (!step.runner) {
|
|
513
505
|
resolvedTaskToolPlan = resolvePiLaunchToolPlan(omitUndefinedProperties({
|
|
@@ -527,28 +519,6 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
527
519
|
requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
|
|
528
520
|
permissionRules: step.permissionRules,
|
|
529
521
|
}));
|
|
530
|
-
const contractTools = resolvedTaskToolPlan.explicitToolAllowlist ? resolvedTaskToolPlan.effectiveToolAllowlist : undefined;
|
|
531
|
-
const contractError = validateImplementationToolContract({
|
|
532
|
-
agent: step.agent,
|
|
533
|
-
task: taskForCompletionGuard,
|
|
534
|
-
tools: contractTools,
|
|
535
|
-
mcpDirectTools: resolvedTaskToolPlan.effectiveMcpTools,
|
|
536
|
-
configuredExtensions: resolvedTaskToolPlan.configuredExtensions,
|
|
537
|
-
requestedTools: resolvedTaskToolPlan.requestedBuiltinTools,
|
|
538
|
-
acceptanceRole: step.acceptanceRole,
|
|
539
|
-
completionGuard: step.completionGuard,
|
|
540
|
-
});
|
|
541
|
-
if (contractError) {
|
|
542
|
-
return omitUndefinedProperties({
|
|
543
|
-
agent: step.agent,
|
|
544
|
-
context: step.context,
|
|
545
|
-
output: contractError,
|
|
546
|
-
error: contractError,
|
|
547
|
-
exitCode: 1,
|
|
548
|
-
capabilityCeiling: resolvedTaskToolPlan.capabilityCeiling,
|
|
549
|
-
capabilityAudit: resolvedTaskToolPlan.capabilityAudit,
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
522
|
}
|
|
553
523
|
// Derive from the pre-acceptance task so internal acceptance/recovery
|
|
554
524
|
// instructions never leak into the display name.
|
|
@@ -818,7 +788,6 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
818
788
|
let finalOutputSnapshot;
|
|
819
789
|
let structuredAcceptanceReport;
|
|
820
790
|
let structuredAcceptanceReportError;
|
|
821
|
-
let completionGuardTriggeredFinal = false;
|
|
822
791
|
let toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;
|
|
823
792
|
let toolBudgetBlocked = false;
|
|
824
793
|
let actualLaunchContractDigest = step.launchContractDigest;
|
|
@@ -980,9 +949,9 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
980
949
|
aggregateUsage.cacheWrite += run.usage.cacheWrite;
|
|
981
950
|
aggregateUsage.cost += run.usage.cost;
|
|
982
951
|
aggregateUsage.turns += run.usage.turns;
|
|
983
|
-
// A parked run still owes
|
|
984
|
-
// Stopped/timedOut runs already have terminal failures
|
|
985
|
-
const
|
|
952
|
+
// A parked run still owes output diagnostics when it actually finishes.
|
|
953
|
+
// Stopped/timedOut runs already have terminal failures, so terminal output diagnostics are deferred.
|
|
954
|
+
const terminalDiagnosticsEligible = !run.interrupted && !run.stopped && !run.timedOut;
|
|
986
955
|
const toolDiagnostic = run.exitCode === 0 && !run.error ? launch.capture.toolDiagnostic() : undefined;
|
|
987
956
|
const toolAvailabilityError = toolDiagnostic ? formatChildToolDiagnostic(toolDiagnostic) : undefined;
|
|
988
957
|
const runtimeAcknowledgedExtensions = launch.capture.runtimeAcknowledgedExtensions();
|
|
@@ -997,18 +966,24 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
997
966
|
let structuredOutput;
|
|
998
967
|
let structuredError;
|
|
999
968
|
let validatedStructuredOutput = false;
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
969
|
+
if (effectiveStructuredOutput) {
|
|
970
|
+
const otherwiseSuccessful = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError;
|
|
971
|
+
if (!run.structuredOutputToolInvoked && otherwiseSuccessful) {
|
|
1002
972
|
structuredError = MISSING_STRUCTURED_OUTPUT_CALL_ERROR;
|
|
1003
973
|
}
|
|
1004
|
-
else {
|
|
974
|
+
else if (run.structuredOutputToolInvoked) {
|
|
1005
975
|
const structured = await readStructuredOutput({
|
|
1006
976
|
schema: effectiveStructuredOutput.schema,
|
|
1007
977
|
schemaPath: effectiveStructuredOutput.schemaPath,
|
|
1008
978
|
outputPath: effectiveStructuredOutput.outputPath,
|
|
1009
979
|
});
|
|
1010
|
-
if (structured.error)
|
|
1011
|
-
|
|
980
|
+
if (structured.error) {
|
|
981
|
+
if (otherwiseSuccessful) {
|
|
982
|
+
structuredError = structured.error === MISSING_STRUCTURED_OUTPUT_CALL_ERROR
|
|
983
|
+
? formatStructuredOutputRejectionError(run.messages)
|
|
984
|
+
: structured.error;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
1012
987
|
else {
|
|
1013
988
|
structuredOutput = structured.value;
|
|
1014
989
|
const acceptanceReport = readStructuredOutputAcceptanceReport(effectiveStructuredOutput);
|
|
@@ -1021,13 +996,13 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
1021
996
|
const errorMessages = validatedStructuredOutput
|
|
1022
997
|
? run.messages.slice(run.structuredOutputMessageStartIndex ?? run.messages.length)
|
|
1023
998
|
: run.messages;
|
|
1024
|
-
const hiddenError =
|
|
999
|
+
const hiddenError = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError
|
|
1025
1000
|
? detectSubagentError(errorMessages)
|
|
1026
1001
|
: null;
|
|
1027
1002
|
const terminalEmptyAfterUsefulWork = !validatedStructuredOutput
|
|
1028
1003
|
&& hasEmptyTerminalAssistantResponse(run.messages)
|
|
1029
1004
|
&& (run.toolCount > 0 || Boolean(run.finalOutput.trim()));
|
|
1030
|
-
const emptyOutputError =
|
|
1005
|
+
const emptyOutputError = terminalDiagnosticsEligible && run.exitCode === 0
|
|
1031
1006
|
&& !run.error
|
|
1032
1007
|
&& !toolAvailabilityError
|
|
1033
1008
|
&& !structuredError
|
|
@@ -1036,48 +1011,10 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
1036
1011
|
&& (!hiddenError?.hasError || hasEmptyTerminalAssistantResponse(run.messages))
|
|
1037
1012
|
? formatEmptyTerminalAssistantResponseError(run.messages)
|
|
1038
1013
|
: undefined;
|
|
1039
|
-
const completionGuardEnabled = isAgentContract(step.agentContract) ? step.completionGuard === true : step.completionGuard !== false;
|
|
1040
|
-
const completionToolPlan = resolvedTaskToolPlan;
|
|
1041
|
-
const completionTools = completionToolPlan ? (completionToolPlan.explicitToolAllowlist ? completionToolPlan.effectiveToolAllowlist : undefined) : step.tools;
|
|
1042
1014
|
const remoteGitChanged = run.nativeMachine?.initialGit && run.nativeMachine.finalGit ? run.nativeMachine.initialGit.head !== run.nativeMachine.finalGit.head || run.nativeMachine.initialGit.dirty !== run.nativeMachine.finalGit.dirty : undefined;
|
|
1043
1015
|
const mutationEvidence = run.nativeMachine ? { source: "tracked-files", trackedOnly: true, changedFiles: [], attemptedMutation: remoteGitChanged === true, ...(remoteGitChanged === undefined ? { unavailable: "Remote Git before/after evidence was incomplete." } : {}) } : collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
|
|
1044
1016
|
finalMutationEvidence = mutationEvidence;
|
|
1045
|
-
const
|
|
1046
|
-
const completionGuard = completionDiagnosticsEligible && run.exitCode === 0 && !run.error && !structuredError && !hiddenError?.hasError && !midToolExitError && !emptyOutputError && completionGuardEnabled
|
|
1047
|
-
? evaluateCompletionMutationGuard(omitUndefinedProperties({
|
|
1048
|
-
agent: step.agent,
|
|
1049
|
-
task: taskForCompletionGuard,
|
|
1050
|
-
messages: run.messages,
|
|
1051
|
-
tools: completionTools,
|
|
1052
|
-
mcpDirectTools: completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools,
|
|
1053
|
-
mutationTools: step.mutationTools,
|
|
1054
|
-
toolAvailabilityError,
|
|
1055
|
-
mutationEvidence: completionMutationEvidence,
|
|
1056
|
-
}))
|
|
1057
|
-
: undefined;
|
|
1058
|
-
const mutationAttemptObserved = run.observedMutationAttempt === true || completionMutationEvidence?.attemptedMutation === true;
|
|
1059
|
-
let arbitration = { triggered: completionGuard?.triggered === true && !mutationAttemptObserved, rescued: false };
|
|
1060
|
-
if (arbitration.triggered) {
|
|
1061
|
-
const modelContext = launch.capture.completionIntentContext?.();
|
|
1062
|
-
arbitration = await arbitrateCompletionGuardRescue({
|
|
1063
|
-
guardTriggered: true,
|
|
1064
|
-
task: taskForCompletionGuard,
|
|
1065
|
-
// Construct lazily too: the shared gate refuses overlength tasks before
|
|
1066
|
-
// registry/auth/model work. The child has already shut down normally.
|
|
1067
|
-
arbiter: modelContext ? async (task) => createTaskMutationArbiter(modelContext)?.(task) ?? "unavailable" : undefined,
|
|
1068
|
-
});
|
|
1069
|
-
}
|
|
1070
|
-
const completionEvidence = planCompletionEvidence({
|
|
1071
|
-
guard: completionGuard,
|
|
1072
|
-
guardTriggered: arbitration.triggered,
|
|
1073
|
-
arbiterRescued: arbitration.rescued,
|
|
1074
|
-
completionGuardEnabled,
|
|
1075
|
-
mutationCapable: hasMutationToolCapability(completionTools, completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools),
|
|
1076
|
-
implementationMutationExpected: expectsImplementationMutation(step.agent, taskForCompletionGuard),
|
|
1077
|
-
mutationAttemptObserved,
|
|
1078
|
-
mutationEvidence: completionMutationEvidence,
|
|
1079
|
-
agentContractEnabled: isAgentContract(step.agentContract),
|
|
1080
|
-
});
|
|
1017
|
+
const mutationAttemptObserved = run.observedMutationAttempt === true || mutationEvidence.attemptedMutation === true;
|
|
1081
1018
|
const finalOutputHasPersistableFileContent = run.exitCode === 0 && !run.error && !emptyOutputError && Boolean(stripAcceptanceReport(run.finalOutput).trim());
|
|
1082
1019
|
const requiredOutput = step.outputMode === "file-only" && step.outputPath
|
|
1083
1020
|
? { kind: "file-only", path: step.outputPath, missing: !fs.existsSync(step.outputPath) && !finalOutputHasPersistableFileContent }
|
|
@@ -1085,9 +1022,9 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
1085
1022
|
? { kind: "structured", path: effectiveStructuredOutput.outputPath, missing: !fs.existsSync(effectiveStructuredOutput.outputPath) }
|
|
1086
1023
|
: undefined;
|
|
1087
1024
|
finalRequiredOutputMissing = requiredOutput?.missing;
|
|
1088
|
-
const missingRequiredOutputError =
|
|
1025
|
+
const missingRequiredOutputError = terminalDiagnosticsEligible ? formatRequiredOutputError(requiredOutput) : undefined;
|
|
1089
1026
|
const missingRequiredOutputAfterMutation = Boolean(missingRequiredOutputError) && (mutationAttemptObserved || Boolean(mutationEvidence.changedFiles.length));
|
|
1090
|
-
const effectiveExitCode = toolAvailabilityError ||
|
|
1027
|
+
const effectiveExitCode = toolAvailabilityError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError
|
|
1091
1028
|
? 1
|
|
1092
1029
|
: hiddenError?.hasError
|
|
1093
1030
|
? (hiddenError.exitCode ?? 1)
|
|
@@ -1105,8 +1042,7 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
1105
1042
|
? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
|
|
1106
1043
|
: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
|
|
1107
1044
|
: undefined);
|
|
1108
|
-
const error = underlyingError ?? missingRequiredOutputError
|
|
1109
|
-
completionGuardTriggeredFinal = completionEvidence.guardTriggered && !underlyingError && !missingRequiredOutputError;
|
|
1045
|
+
const error = underlyingError ?? missingRequiredOutputError;
|
|
1110
1046
|
finalOutputSnapshot = outputSnapshot;
|
|
1111
1047
|
if (step.toolBudget) {
|
|
1112
1048
|
const toolMessages = run.messages.filter((message) => message.role === "toolResult");
|
|
@@ -1114,21 +1050,18 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
1114
1050
|
toolBudgetBlocked = Boolean(blockedMessage);
|
|
1115
1051
|
toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? blockedMessage.toolName : undefined);
|
|
1116
1052
|
}
|
|
1117
|
-
const settlementDiagnostic =
|
|
1118
|
-
terminalFailed: effectiveExitCode !== 0,
|
|
1053
|
+
const settlementDiagnostic = effectiveExitCode !== 0 ? {
|
|
1119
1054
|
finalTextPresent: Boolean(stripAcceptanceReport(run.finalOutput).trim()),
|
|
1120
|
-
|
|
1121
|
-
requiredOutput,
|
|
1055
|
+
mutation: { attempted: mutationAttemptObserved, observed: mutationEvidence.attemptedMutation },
|
|
1056
|
+
...(requiredOutput ? { requiredOutput } : {}),
|
|
1122
1057
|
afterCompactionSettlement: run.afterCompactionSettlement === true,
|
|
1123
|
-
}
|
|
1124
|
-
const fileMutationEffect =
|
|
1125
|
-
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect || settlementDiagnostic ? { effects: { ...(fileMutationEffect ? { fileMutation: fileMutationEffect } : {}), ...(settlementDiagnostic ? { settlementDiagnostic } : {}) } } : {}) };
|
|
1058
|
+
} : undefined;
|
|
1059
|
+
const fileMutationEffect = missingRequiredOutputAfterMutation ? { status: "observed", attempted: true, evidence: mutationEvidence } : undefined;
|
|
1060
|
+
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, structuredOutputFailed: structuredError ? true : undefined, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect || settlementDiagnostic ? { effects: { ...(fileMutationEffect ? { fileMutation: fileMutationEffect } : {}), ...(settlementDiagnostic ? { settlementDiagnostic } : {}) } } : {}) };
|
|
1126
1061
|
if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.())
|
|
1127
1062
|
break singleLaunch;
|
|
1128
1063
|
if (effectiveExitCode === 0 && !error)
|
|
1129
1064
|
break singleLaunch;
|
|
1130
|
-
if (completionEvidence.guardTriggered)
|
|
1131
|
-
break singleLaunch;
|
|
1132
1065
|
const recovery = planAbortRecovery({
|
|
1133
1066
|
messages: run.messages,
|
|
1134
1067
|
error,
|
|
@@ -1330,11 +1263,11 @@ export async function runSingleStepInner(step, ctx) {
|
|
|
1330
1263
|
timeoutRecovery,
|
|
1331
1264
|
toolBudget,
|
|
1332
1265
|
toolBudgetBlocked: toolBudgetBlocked || undefined,
|
|
1333
|
-
completionGuardTriggered: completionGuardTriggeredFinal,
|
|
1334
1266
|
...(finalResult?.effects ? { effects: finalResult.effects } : {}),
|
|
1335
|
-
structuredOutput:
|
|
1336
|
-
|
|
1337
|
-
|
|
1267
|
+
structuredOutput: finalResult?.structuredOutput,
|
|
1268
|
+
structuredOutputFailed: finalResult?.structuredOutputFailed,
|
|
1269
|
+
structuredOutputPath: effectiveStructuredOutput?.outputPath,
|
|
1270
|
+
structuredOutputSchemaPath: effectiveStructuredOutput?.schemaPath,
|
|
1338
1271
|
acceptance: effectiveAcceptance,
|
|
1339
1272
|
watchdog: finalResult?.watchdog,
|
|
1340
1273
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
@@ -3546,7 +3479,6 @@ export async function runSubagent(config, childSessions) {
|
|
|
3546
3479
|
onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
|
|
3547
3480
|
timeoutSignal: timeoutAbortController.signal,
|
|
3548
3481
|
stopSignal: stopAbortController.signal,
|
|
3549
|
-
trackedMutationEvidenceForCompletionGuard: false,
|
|
3550
3482
|
timeoutMessage,
|
|
3551
3483
|
stopMessage,
|
|
3552
3484
|
toolTimeoutMs: task.toolTimeoutMs ?? config.toolTimeoutMs,
|
|
@@ -3665,6 +3597,7 @@ export async function runSubagent(config, childSessions) {
|
|
|
3665
3597
|
review: pr.review,
|
|
3666
3598
|
timeoutRecovery: pr.timeoutRecovery,
|
|
3667
3599
|
structuredOutput: pr.structuredOutput,
|
|
3600
|
+
structuredOutputFailed: pr.structuredOutputFailed,
|
|
3668
3601
|
structuredOutputPath: pr.structuredOutputPath,
|
|
3669
3602
|
structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
|
|
3670
3603
|
acceptance: pr.acceptance,
|
|
@@ -3969,7 +3902,6 @@ export async function runSubagent(config, childSessions) {
|
|
|
3969
3902
|
onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
|
|
3970
3903
|
timeoutSignal: timeoutAbortController.signal,
|
|
3971
3904
|
stopSignal: stopAbortController.signal,
|
|
3972
|
-
trackedMutationEvidenceForCompletionGuard: Boolean(worktreeSetup),
|
|
3973
3905
|
timeoutMessage,
|
|
3974
3906
|
stopMessage,
|
|
3975
3907
|
toolTimeoutMs: taskForRun.toolTimeoutMs ?? config.toolTimeoutMs,
|
|
@@ -4048,19 +3980,6 @@ export async function runSubagent(config, childSessions) {
|
|
|
4048
3980
|
}));
|
|
4049
3981
|
if (stopped || childStopped)
|
|
4050
3982
|
appendTerminalChildStatusEvent(fi, taskEndTime);
|
|
4051
|
-
if (singleResult.completionGuardTriggered) {
|
|
4052
|
-
const event = buildControlEvent(omitUndefinedProperties({
|
|
4053
|
-
from: requiredStatusStep(statusPayload, fi).activityState,
|
|
4054
|
-
to: "needs_attention",
|
|
4055
|
-
runId: id,
|
|
4056
|
-
agent: task.agent,
|
|
4057
|
-
index: fi,
|
|
4058
|
-
ts: taskEndTime,
|
|
4059
|
-
message: `${task.agent} completed without making edits for an implementation task`,
|
|
4060
|
-
reason: "completion_guard",
|
|
4061
|
-
}));
|
|
4062
|
-
appendControlEvent(event);
|
|
4063
|
-
}
|
|
4064
3983
|
if (singleResult.exitCode !== 0 && failFast && !childStopped)
|
|
4065
3984
|
aborted = true;
|
|
4066
3985
|
return stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: singleResult.output || (timeoutMessage ?? "Subagent timed out."), error: singleResult.error ?? timeoutMessage ?? "Subagent timed out.", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };
|
|
@@ -4128,6 +4047,7 @@ export async function runSubagent(config, childSessions) {
|
|
|
4128
4047
|
review: pr.review,
|
|
4129
4048
|
timeoutRecovery: pr.timeoutRecovery,
|
|
4130
4049
|
structuredOutput: pr.structuredOutput,
|
|
4050
|
+
structuredOutputFailed: pr.structuredOutputFailed,
|
|
4131
4051
|
structuredOutputPath: pr.structuredOutputPath,
|
|
4132
4052
|
structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
|
|
4133
4053
|
acceptance: pr.acceptance,
|
|
@@ -4433,6 +4353,7 @@ export async function runSubagent(config, childSessions) {
|
|
|
4433
4353
|
review: singleResult.review,
|
|
4434
4354
|
timeoutRecovery: singleResult.timeoutRecovery,
|
|
4435
4355
|
structuredOutput: singleResult.structuredOutput,
|
|
4356
|
+
structuredOutputFailed: singleResult.structuredOutputFailed,
|
|
4436
4357
|
structuredOutputPath: singleResult.structuredOutputPath,
|
|
4437
4358
|
structuredOutputSchemaPath: singleResult.structuredOutputSchemaPath,
|
|
4438
4359
|
acceptance: singleResult.acceptance,
|
|
@@ -4595,19 +4516,6 @@ export async function runSubagent(config, childSessions) {
|
|
|
4595
4516
|
writeStatusPayload();
|
|
4596
4517
|
});
|
|
4597
4518
|
}
|
|
4598
|
-
if (singleResult.completionGuardTriggered) {
|
|
4599
|
-
const event = buildControlEvent(omitUndefinedProperties({
|
|
4600
|
-
from: requiredStatusStep(statusPayload, flatIndex).activityState,
|
|
4601
|
-
to: "needs_attention",
|
|
4602
|
-
runId: id,
|
|
4603
|
-
agent: seqStep.agent,
|
|
4604
|
-
index: flatIndex,
|
|
4605
|
-
ts: stepEndTime,
|
|
4606
|
-
message: `${seqStep.agent} completed without making edits for an implementation task`,
|
|
4607
|
-
reason: "completion_guard",
|
|
4608
|
-
}));
|
|
4609
|
-
appendControlEvent(event);
|
|
4610
|
-
}
|
|
4611
4519
|
flatIndex++;
|
|
4612
4520
|
if (isAgentContract(seqStep.agentContract) && seqStep.gateOn === "acceptance" && singleResult.acceptance?.status === "rejected") {
|
|
4613
4521
|
statusPayload.error = acceptanceFailureMessage(singleResult.acceptance) ?? "Chain acceptance gate rejected the step.";
|
|
@@ -4856,6 +4764,7 @@ export async function runSubagent(config, childSessions) {
|
|
|
4856
4764
|
review: r.review,
|
|
4857
4765
|
effects: r.effects,
|
|
4858
4766
|
structuredOutput: r.structuredOutput,
|
|
4767
|
+
structuredOutputFailed: r.structuredOutputFailed,
|
|
4859
4768
|
structuredOutputPath: r.structuredOutputPath,
|
|
4860
4769
|
structuredOutputSchemaPath: r.structuredOutputSchemaPath,
|
|
4861
4770
|
acceptance: r.acceptance,
|
|
@@ -4973,162 +4882,46 @@ export async function runSubagent(config, childSessions) {
|
|
|
4973
4882
|
}
|
|
4974
4883
|
}
|
|
4975
4884
|
}
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
if (fs.existsSync(controlPath)) {
|
|
4980
|
-
let payload;
|
|
4981
|
-
try {
|
|
4982
|
-
payload = JSON.parse(fs.readFileSync(controlPath, "utf-8"));
|
|
4983
|
-
}
|
|
4984
|
-
catch (error) {
|
|
4985
|
-
throw new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);
|
|
4986
|
-
}
|
|
4987
|
-
if (payload.token !== token)
|
|
4988
|
-
throw new Error("Runner startup control token does not match.");
|
|
4989
|
-
if (payload.action === action)
|
|
4990
|
-
return;
|
|
4991
|
-
if (payload.action !== "ack" && payload.action !== "confirm" && payload.action !== "proceed")
|
|
4992
|
-
throw new Error("Runner startup control action is invalid.");
|
|
4993
|
-
}
|
|
4994
|
-
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
4995
|
-
}
|
|
4996
|
-
throw new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);
|
|
4997
|
-
}
|
|
4998
|
-
// Both hosts enter here: startup authorization, revival leases and disposal stay shared.
|
|
4999
|
-
export async function runConfiguredSubagent(config, options) {
|
|
5000
|
-
let lease;
|
|
5001
|
-
let startupCommitted = config.revivalLease === undefined && config.launchBarrierToken === undefined;
|
|
5002
|
-
const startupPath = path.join(config.asyncDir, "runner-startup.json");
|
|
5003
|
-
const startupAckPath = path.join(config.asyncDir, "runner-startup-ack.json");
|
|
5004
|
-
const startupConfirmPath = path.join(config.asyncDir, "runner-startup-confirm.json");
|
|
5005
|
-
const startupProceedPath = path.join(config.asyncDir, "runner-startup-proceed.json");
|
|
5006
|
-
const releaseOnExit = () => {
|
|
5007
|
-
try {
|
|
5008
|
-
lease?.release();
|
|
5009
|
-
}
|
|
5010
|
-
catch {
|
|
5011
|
-
// Exit cleanup is best effort; a dead-owner lease is reclaimed on the next revival.
|
|
5012
|
-
}
|
|
5013
|
-
};
|
|
5014
|
-
process.once("exit", releaseOnExit);
|
|
4885
|
+
/** Heavy execution entry loaded by the bootstrap only after startup commits. */
|
|
4886
|
+
export async function runConfiguredSubagentExecution(config, options) {
|
|
4887
|
+
let childSessions;
|
|
5015
4888
|
try {
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
}
|
|
5022
|
-
catch {
|
|
5023
|
-
// Startup control cleanup is best effort after the parent commits the run.
|
|
5024
|
-
}
|
|
5025
|
-
}
|
|
5026
|
-
else if (config.revivalLease) {
|
|
5027
|
-
lease = acquireSessionLease(config.revivalLease);
|
|
5028
|
-
config.revivalLeaseToken = lease.owner.token;
|
|
5029
|
-
writeAtomicJson(startupPath, { state: "ready", token: lease.owner.token, pid: process.pid, owner: lease.owner });
|
|
5030
|
-
await waitForStartupControl(startupAckPath, lease.owner.token, "ack");
|
|
5031
|
-
writeAtomicJson(startupPath, { state: "acknowledged", token: lease.owner.token, pid: process.pid });
|
|
5032
|
-
await waitForStartupControl(startupConfirmPath, lease.owner.token, "confirm");
|
|
5033
|
-
writeAtomicJson(startupPath, { state: "confirmed", token: lease.owner.token, pid: process.pid });
|
|
5034
|
-
await waitForStartupControl(startupProceedPath, lease.owner.token, "proceed");
|
|
5035
|
-
startupCommitted = true;
|
|
5036
|
-
for (const controlPath of [startupAckPath, startupConfirmPath, startupProceedPath]) {
|
|
5037
|
-
try {
|
|
5038
|
-
fs.rmSync(controlPath, { force: true });
|
|
5039
|
-
}
|
|
5040
|
-
catch {
|
|
5041
|
-
// Startup control cleanup is best effort after the parent commits the run.
|
|
5042
|
-
}
|
|
5043
|
-
}
|
|
5044
|
-
}
|
|
5045
|
-
const childSessions = await loadRunnerChildSessionFactory(config, options);
|
|
5046
|
-
try {
|
|
5047
|
-
await runSubagent(config, childSessions);
|
|
5048
|
-
}
|
|
5049
|
-
finally {
|
|
5050
|
-
try {
|
|
5051
|
-
await childSessions.dispose();
|
|
5052
|
-
}
|
|
5053
|
-
catch (error) {
|
|
5054
|
-
console.error("Failed to dispose runner child sessions:", error);
|
|
5055
|
-
}
|
|
5056
|
-
}
|
|
4889
|
+
// Detached Node runners do not receive Pi's CLI dispatcher setup. Binary
|
|
4890
|
+
// hosts install the same dispatcher before entering the shared bootstrap.
|
|
4891
|
+
if (!options?.loadPiCodingAgent)
|
|
4892
|
+
installRunnerHttpDispatcher({ agentDir: getAgentDir(), cwd: process.cwd() });
|
|
4893
|
+
childSessions = await loadRunnerChildSessionFactory(config, options);
|
|
5057
4894
|
}
|
|
5058
4895
|
catch (error) {
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
4896
|
+
try {
|
|
4897
|
+
persistRunnerStartupFailure({
|
|
4898
|
+
asyncDir: config.asyncDir,
|
|
4899
|
+
runId: config.id,
|
|
4900
|
+
runnerProcessInstanceId: config.runnerProcessInstanceId ?? "unknown-runner-instance",
|
|
4901
|
+
message: `Subagent runner startup failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
4902
|
+
...(config.sessionId ? { sessionId: config.sessionId } : {}),
|
|
4903
|
+
...(config.completionOwnerId ? { completionOwnerId: config.completionOwnerId } : {}),
|
|
4904
|
+
candidate: {
|
|
4905
|
+
...(config.revivalLease?.sessionFile ? { sessionFile: config.revivalLease.sessionFile } : {}),
|
|
4906
|
+
...(config.revivalLeaseToken ? { revivalLeaseToken: config.revivalLeaseToken } : {}),
|
|
4907
|
+
},
|
|
4908
|
+
});
|
|
4909
|
+
}
|
|
4910
|
+
catch (persistenceError) {
|
|
4911
|
+
console.error("Failed to persist runner setup failure:", persistenceError);
|
|
5066
4912
|
}
|
|
5067
4913
|
throw error;
|
|
5068
4914
|
}
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
if (lease) {
|
|
5072
|
-
let acknowledged = false;
|
|
5073
|
-
try {
|
|
5074
|
-
acknowledged = lease.release();
|
|
5075
|
-
}
|
|
5076
|
-
catch (error) {
|
|
5077
|
-
console.error("Failed to release session revival lease:", error);
|
|
5078
|
-
}
|
|
5079
|
-
try {
|
|
5080
|
-
markProcessTerminalCandidateLeaseRelease(config.asyncDir, lease.owner.token, acknowledged);
|
|
5081
|
-
}
|
|
5082
|
-
catch (error) {
|
|
5083
|
-
console.error("Failed to record session revival lease release:", error);
|
|
5084
|
-
}
|
|
5085
|
-
}
|
|
4915
|
+
try {
|
|
4916
|
+
await runSubagent(config, childSessions);
|
|
5086
4917
|
}
|
|
5087
|
-
|
|
5088
|
-
function startConfiguredSubagent(config) {
|
|
5089
|
-
// Child sessions and the extensions loaded into them may leave handles
|
|
5090
|
-
// behind even after shutdown; the run is fully persisted by now, so exit
|
|
5091
|
-
// explicitly instead of waiting for the event loop to drain.
|
|
5092
|
-
runConfiguredSubagent(config).then(() => process.exit(0), (runErr) => {
|
|
5093
|
-
console.error("Subagent runner error:", runErr);
|
|
5094
|
-
process.exit(1);
|
|
5095
|
-
});
|
|
5096
|
-
}
|
|
5097
|
-
if (isRunnerEntrypoint) {
|
|
5098
|
-
const configArg = process.argv[2];
|
|
5099
|
-
if (configArg) {
|
|
4918
|
+
finally {
|
|
5100
4919
|
try {
|
|
5101
|
-
|
|
5102
|
-
const config = JSON.parse(configJson);
|
|
5103
|
-
try {
|
|
5104
|
-
fs.unlinkSync(configArg);
|
|
5105
|
-
}
|
|
5106
|
-
catch {
|
|
5107
|
-
// Temp config cleanup is best effort.
|
|
5108
|
-
}
|
|
5109
|
-
startConfiguredSubagent(config);
|
|
4920
|
+
await childSessions.dispose();
|
|
5110
4921
|
}
|
|
5111
|
-
catch (
|
|
5112
|
-
console.error("
|
|
5113
|
-
process.exit(1);
|
|
4922
|
+
catch (error) {
|
|
4923
|
+
console.error("Failed to dispose runner child sessions:", error);
|
|
5114
4924
|
}
|
|
5115
4925
|
}
|
|
5116
|
-
else {
|
|
5117
|
-
let input = "";
|
|
5118
|
-
process.stdin.setEncoding("utf-8");
|
|
5119
|
-
process.stdin.on("data", (chunk) => {
|
|
5120
|
-
input += chunk;
|
|
5121
|
-
});
|
|
5122
|
-
process.stdin.on("end", () => {
|
|
5123
|
-
try {
|
|
5124
|
-
const config = JSON.parse(input);
|
|
5125
|
-
startConfiguredSubagent(config);
|
|
5126
|
-
}
|
|
5127
|
-
catch (err) {
|
|
5128
|
-
console.error("Subagent runner error:", err);
|
|
5129
|
-
process.exit(1);
|
|
5130
|
-
}
|
|
5131
|
-
});
|
|
5132
|
-
}
|
|
5133
4926
|
}
|
|
5134
4927
|
//# sourceMappingURL=subagent-runner.js.map
|