pi-subagents 0.70.1 → 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.
Files changed (209) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +3 -1
  3. package/agents/worker.md +2 -2
  4. package/docs/agents.md +1 -1
  5. package/docs/configuration.md +15 -1
  6. package/docs/extension-api.md +3 -1
  7. package/docs/observability.md +16 -12
  8. package/docs/tool-reference.md +6 -4
  9. package/docs/workflows.md +1 -1
  10. package/package.json +2 -2
  11. package/skills/pi-subagents/references/constraints-and-recipes.md +5 -2
  12. package/skills/pi-subagents/references/execution-controls.md +2 -2
  13. package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  14. package/src/agents/proactive-skills.d.ts +1 -0
  15. package/src/agents/proactive-skills.d.ts.map +1 -1
  16. package/src/agents/proactive-skills.js +3 -1
  17. package/src/agents/proactive-skills.js.map +1 -1
  18. package/src/agents/skills.d.ts +2 -0
  19. package/src/agents/skills.d.ts.map +1 -1
  20. package/src/agents/skills.js +41 -8
  21. package/src/agents/skills.js.map +1 -1
  22. package/src/api/delegation.d.ts +14 -0
  23. package/src/api/delegation.d.ts.map +1 -1
  24. package/src/extension/index.d.ts.map +1 -1
  25. package/src/extension/index.js +4 -0
  26. package/src/extension/index.js.map +1 -1
  27. package/src/extension/rpc.d.ts +1 -1
  28. package/src/extension/rpc.d.ts.map +1 -1
  29. package/src/extension/rpc.js +11 -1
  30. package/src/extension/rpc.js.map +1 -1
  31. package/src/extension/tool-activation.d.ts +9 -0
  32. package/src/extension/tool-activation.d.ts.map +1 -0
  33. package/src/extension/tool-activation.js +172 -0
  34. package/src/extension/tool-activation.js.map +1 -0
  35. package/src/extension/tool-description.d.ts +4 -4
  36. package/src/extension/tool-description.d.ts.map +1 -1
  37. package/src/extension/tool-description.js +1 -1
  38. package/src/intercom/intercom-bridge.d.ts.map +1 -1
  39. package/src/intercom/intercom-bridge.js +2 -0
  40. package/src/intercom/intercom-bridge.js.map +1 -1
  41. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  42. package/src/runs/background/active-async-capacity.js +4 -33
  43. package/src/runs/background/active-async-capacity.js.map +1 -1
  44. package/src/runs/background/async-execution.d.ts.map +1 -1
  45. package/src/runs/background/async-execution.js +5 -33
  46. package/src/runs/background/async-execution.js.map +1 -1
  47. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  48. package/src/runs/background/async-job-tracker.js +25 -19
  49. package/src/runs/background/async-job-tracker.js.map +1 -1
  50. package/src/runs/background/async-resume.d.ts +1 -1
  51. package/src/runs/background/async-resume.d.ts.map +1 -1
  52. package/src/runs/background/async-resume.js +7 -2
  53. package/src/runs/background/async-resume.js.map +1 -1
  54. package/src/runs/background/async-status.d.ts +1 -0
  55. package/src/runs/background/async-status.d.ts.map +1 -1
  56. package/src/runs/background/async-status.js +1 -0
  57. package/src/runs/background/async-status.js.map +1 -1
  58. package/src/runs/background/binary-bootstrap.d.ts.map +1 -1
  59. package/src/runs/background/binary-bootstrap.js +28 -6
  60. package/src/runs/background/binary-bootstrap.js.map +1 -1
  61. package/src/runs/background/fleet-view.d.ts.map +1 -1
  62. package/src/runs/background/fleet-view.js +26 -7
  63. package/src/runs/background/fleet-view.js.map +1 -1
  64. package/src/runs/background/notify.d.ts +11 -0
  65. package/src/runs/background/notify.d.ts.map +1 -1
  66. package/src/runs/background/notify.js +71 -3
  67. package/src/runs/background/notify.js.map +1 -1
  68. package/src/runs/background/process-terminal-candidate.d.ts +18 -0
  69. package/src/runs/background/process-terminal-candidate.d.ts.map +1 -0
  70. package/src/runs/background/process-terminal-candidate.js +97 -0
  71. package/src/runs/background/process-terminal-candidate.js.map +1 -0
  72. package/src/runs/background/process-terminal.d.ts +3 -15
  73. package/src/runs/background/process-terminal.d.ts.map +1 -1
  74. package/src/runs/background/process-terminal.js +19 -96
  75. package/src/runs/background/process-terminal.js.map +1 -1
  76. package/src/runs/background/retained-children.d.ts.map +1 -1
  77. package/src/runs/background/retained-children.js +3 -2
  78. package/src/runs/background/retained-children.js.map +1 -1
  79. package/src/runs/background/run-child-session.d.ts +1 -0
  80. package/src/runs/background/run-child-session.d.ts.map +1 -1
  81. package/src/runs/background/run-child-session.js.map +1 -1
  82. package/src/runs/background/run-status.d.ts.map +1 -1
  83. package/src/runs/background/run-status.js +5 -1
  84. package/src/runs/background/run-status.js.map +1 -1
  85. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  86. package/src/runs/background/runner-aliases.js +2 -1
  87. package/src/runs/background/runner-aliases.js.map +1 -1
  88. package/src/runs/background/runner-startup-failure.d.ts +14 -0
  89. package/src/runs/background/runner-startup-failure.d.ts.map +1 -0
  90. package/src/runs/background/runner-startup-failure.js +47 -0
  91. package/src/runs/background/runner-startup-failure.js.map +1 -0
  92. package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
  93. package/src/runs/background/stale-run-reconciler.js +9 -1
  94. package/src/runs/background/stale-run-reconciler.js.map +1 -1
  95. package/src/runs/background/subagent-runner-bootstrap.d.ts +14 -0
  96. package/src/runs/background/subagent-runner-bootstrap.d.ts.map +1 -0
  97. package/src/runs/background/subagent-runner-bootstrap.js +277 -0
  98. package/src/runs/background/subagent-runner-bootstrap.js.map +1 -0
  99. package/src/runs/background/subagent-runner.d.ts +4 -2
  100. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  101. package/src/runs/background/subagent-runner.js +53 -178
  102. package/src/runs/background/subagent-runner.js.map +1 -1
  103. package/src/runs/background/workflow-terminal-proof.d.ts +18 -0
  104. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -0
  105. package/src/runs/background/workflow-terminal-proof.js +68 -0
  106. package/src/runs/background/workflow-terminal-proof.js.map +1 -0
  107. package/src/runs/foreground/execution.d.ts.map +1 -1
  108. package/src/runs/foreground/execution.js +43 -14
  109. package/src/runs/foreground/execution.js.map +1 -1
  110. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  111. package/src/runs/foreground/subagent-executor.js +108 -15
  112. package/src/runs/foreground/subagent-executor.js.map +1 -1
  113. package/src/runs/shared/child-launch.d.ts.map +1 -1
  114. package/src/runs/shared/child-launch.js +3 -0
  115. package/src/runs/shared/child-launch.js.map +1 -1
  116. package/src/runs/shared/child-runtime-config.d.ts +4 -0
  117. package/src/runs/shared/child-runtime-config.d.ts.map +1 -1
  118. package/src/runs/shared/child-runtime-config.js.map +1 -1
  119. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  120. package/src/runs/shared/external-cli-runner.js +3 -1
  121. package/src/runs/shared/external-cli-runner.js.map +1 -1
  122. package/src/runs/shared/git-environment.d.ts +3 -0
  123. package/src/runs/shared/git-environment.d.ts.map +1 -0
  124. package/src/runs/shared/git-environment.js +28 -0
  125. package/src/runs/shared/git-environment.js.map +1 -0
  126. package/src/runs/shared/mcp-config-sources.d.ts +3 -0
  127. package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
  128. package/src/runs/shared/mcp-config-sources.js.map +1 -1
  129. package/src/runs/shared/mcp-direct-tool-allowlist.js +1 -1
  130. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  131. package/src/runs/shared/mcp-direct-tool-grant.d.ts +3 -1
  132. package/src/runs/shared/mcp-direct-tool-grant.d.ts.map +1 -1
  133. package/src/runs/shared/mcp-direct-tool-grant.js +19 -5
  134. package/src/runs/shared/mcp-direct-tool-grant.js.map +1 -1
  135. package/src/runs/shared/pi-spawn.d.ts +10 -1
  136. package/src/runs/shared/pi-spawn.d.ts.map +1 -1
  137. package/src/runs/shared/pi-spawn.js +86 -7
  138. package/src/runs/shared/pi-spawn.js.map +1 -1
  139. package/src/runs/shared/single-output.js +1 -1
  140. package/src/runs/shared/single-output.js.map +1 -1
  141. package/src/runs/shared/structured-output.d.ts +7 -0
  142. package/src/runs/shared/structured-output.d.ts.map +1 -1
  143. package/src/runs/shared/structured-output.js +74 -0
  144. package/src/runs/shared/structured-output.js.map +1 -1
  145. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  146. package/src/runs/shared/subagent-prompt-runtime.js +23 -7
  147. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  148. package/src/runs/shared/tool-availability.js +1 -1
  149. package/src/runs/shared/tool-availability.js.map +1 -1
  150. package/src/shared/child-session-name.d.ts.map +1 -1
  151. package/src/shared/child-session-name.js +4 -2
  152. package/src/shared/child-session-name.js.map +1 -1
  153. package/src/shared/fork-context.d.ts +4 -0
  154. package/src/shared/fork-context.d.ts.map +1 -1
  155. package/src/shared/fork-context.js +9 -4
  156. package/src/shared/fork-context.js.map +1 -1
  157. package/src/shared/pruned-fork.d.ts.map +1 -1
  158. package/src/shared/pruned-fork.js +68 -56
  159. package/src/shared/pruned-fork.js.map +1 -1
  160. package/src/shared/types.d.ts +29 -3
  161. package/src/shared/types.d.ts.map +1 -1
  162. package/src/shared/types.js +2 -0
  163. package/src/shared/types.js.map +1 -1
  164. package/src/slash/delegation-adapters.d.ts +7 -1
  165. package/src/slash/delegation-adapters.d.ts.map +1 -1
  166. package/src/slash/delegation-adapters.js +17 -0
  167. package/src/slash/delegation-adapters.js.map +1 -1
  168. package/src/slash/prompt-template-bridge.d.ts.map +1 -1
  169. package/src/slash/prompt-template-bridge.js +14 -1
  170. package/src/slash/prompt-template-bridge.js.map +1 -1
  171. package/src/slash/prompt-workflows.d.ts.map +1 -1
  172. package/src/slash/prompt-workflows.js +16 -2
  173. package/src/slash/prompt-workflows.js.map +1 -1
  174. package/src/slash/slash-commands.d.ts.map +1 -1
  175. package/src/slash/slash-commands.js +4 -250
  176. package/src/slash/slash-commands.js.map +1 -1
  177. package/src/slash/subagent-cost.d.ts +29 -0
  178. package/src/slash/subagent-cost.d.ts.map +1 -0
  179. package/src/slash/subagent-cost.js +271 -0
  180. package/src/slash/subagent-cost.js.map +1 -0
  181. package/src/tui/fleet.d.ts.map +1 -1
  182. package/src/tui/fleet.js +4 -0
  183. package/src/tui/fleet.js.map +1 -1
  184. package/src/tui/render.d.ts.map +1 -1
  185. package/src/tui/render.js +8 -4
  186. package/src/tui/render.js.map +1 -1
  187. package/src/watchdog/diff-tool.d.ts +2 -1
  188. package/src/watchdog/diff-tool.d.ts.map +1 -1
  189. package/src/watchdog/diff-tool.js +9 -3
  190. package/src/watchdog/diff-tool.js.map +1 -1
  191. package/src/watchdog/permission-arbiter.d.ts.map +1 -1
  192. package/src/watchdog/permission-arbiter.js +1 -2
  193. package/src/watchdog/permission-arbiter.js.map +1 -1
  194. package/src/watchdog/register-child.d.ts +3 -1
  195. package/src/watchdog/register-child.d.ts.map +1 -1
  196. package/src/watchdog/register-child.js +12 -3
  197. package/src/watchdog/register-child.js.map +1 -1
  198. package/src/watchdog/review.d.ts +1 -1
  199. package/src/watchdog/review.d.ts.map +1 -1
  200. package/src/watchdog/review.js +1 -2
  201. package/src/watchdog/review.js.map +1 -1
  202. package/src/watchdog/runtime.d.ts +1 -1
  203. package/src/watchdog/runtime.d.ts.map +1 -1
  204. package/src/watchdog/runtime.js +2 -1
  205. package/src/watchdog/runtime.js.map +1 -1
  206. package/src/watchdog/turn-delta.d.ts +5 -1
  207. package/src/watchdog/turn-delta.d.ts.map +1 -1
  208. package/src/watchdog/turn-delta.js +9 -5
  209. package/src/watchdog/turn-delta.js.map +1 -1
@@ -12,10 +12,6 @@ import * as path from "node:path";
12
12
  import { performance } from "node:perf_hooks";
13
13
  import { pathToFileURL } from "node:url";
14
14
  import { installRunnerHttpDispatcher } from "./runner-http-dispatcher.js";
15
- const isRunnerEntrypoint = Boolean(process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href);
16
- // Detached Node runners skip Pi's CLI dispatcher setup; install the runner's own.
17
- if (isRunnerEntrypoint)
18
- installRunnerHttpDispatcher({ agentDir: getAgentDir(), cwd: process.cwd() });
19
15
  import { writeAtomicJson } from "../../shared/atomic-json.js";
20
16
  import { writeAsyncResultFile, writePendingAsyncResultFile } from "./result-files.js";
21
17
  import { createFileCoalescer } from "../../shared/file-coalescer.js";
@@ -41,7 +37,7 @@ import { SUBAGENT_CHILD_ENV } from "../shared/child-runtime-config.js";
41
37
  import { deriveChildSessionName } from "../../shared/child-session-name.js";
42
38
  import { alignForkedSessionCwd } from "../../shared/fork-session-cwd.js";
43
39
  import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.js";
44
- 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";
45
41
  import { formatMidToolExitError, isOrdinaryToolForMidToolExit, isUnexplainedProcessSignal } from "../shared/process-signal.js";
46
42
  import { formatChildToolDiagnostic } from "../shared/tool-availability.js";
47
43
  import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTrackedMutations } from "../shared/mutation-evidence.js";
@@ -49,7 +45,8 @@ import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelSt
49
45
  import { claimRunFanoutBatch, getRunFanoutBudgetSnapshot } from "../shared/run-fanout-budget.js";
50
46
  import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.js";
51
47
  import { isContextOverflow } from "../shared/model-resolution.js";
52
- import { markProcessTerminalCandidateLeaseRelease, processTerminalPath, writeProcessTerminalCandidate } from "./process-terminal.js";
48
+ import { processTerminalPath, writeProcessTerminalCandidate } from "./process-terminal.js";
49
+ import { persistRunnerStartupFailure } from "./runner-startup-failure.js";
53
50
  import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, unconsumedSteerReason, updateSteeringTarget } from "./steering.js";
54
51
  import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getAgentDir, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.js";
55
52
  import { planAbortRecovery } from "../shared/abort-recovery.js";
@@ -71,7 +68,6 @@ import { toolTimeoutCallKey } from "../shared/tool-timeout.js";
71
68
  import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.js";
72
69
  import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.js";
73
70
  import { resolveWatchdogConfig } from "../../watchdog/settings.js";
74
- import { acquireSessionLease } from "../shared/session-lease.js";
75
71
  import { buildExternalCliPrompt, runExternalCli } from "../shared/external-cli-runner.js";
76
72
  import { resolveClaudeCodeLaunch } from "../shared/claude-code-adapter.js";
77
73
  import { resolveCodexExecLaunch } from "../shared/codex-exec-adapter.js";
@@ -970,18 +966,24 @@ export async function runSingleStepInner(step, ctx) {
970
966
  let structuredOutput;
971
967
  let structuredError;
972
968
  let validatedStructuredOutput = false;
973
- if (terminalDiagnosticsEligible && effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError) {
974
- if (!run.structuredOutputToolInvoked) {
969
+ if (effectiveStructuredOutput) {
970
+ const otherwiseSuccessful = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError;
971
+ if (!run.structuredOutputToolInvoked && otherwiseSuccessful) {
975
972
  structuredError = MISSING_STRUCTURED_OUTPUT_CALL_ERROR;
976
973
  }
977
- else {
974
+ else if (run.structuredOutputToolInvoked) {
978
975
  const structured = await readStructuredOutput({
979
976
  schema: effectiveStructuredOutput.schema,
980
977
  schemaPath: effectiveStructuredOutput.schemaPath,
981
978
  outputPath: effectiveStructuredOutput.outputPath,
982
979
  });
983
- if (structured.error)
984
- structuredError = structured.error;
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
+ }
985
987
  else {
986
988
  structuredOutput = structured.value;
987
989
  const acceptanceReport = readStructuredOutputAcceptanceReport(effectiveStructuredOutput);
@@ -1055,7 +1057,7 @@ export async function runSingleStepInner(step, ctx) {
1055
1057
  afterCompactionSettlement: run.afterCompactionSettlement === true,
1056
1058
  } : undefined;
1057
1059
  const fileMutationEffect = missingRequiredOutputAfterMutation ? { status: "observed", attempted: true, evidence: mutationEvidence } : undefined;
1058
- finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect || settlementDiagnostic ? { effects: { ...(fileMutationEffect ? { fileMutation: fileMutationEffect } : {}), ...(settlementDiagnostic ? { settlementDiagnostic } : {}) } } : {}) };
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 } : {}) } } : {}) };
1059
1061
  if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.())
1060
1062
  break singleLaunch;
1061
1063
  if (effectiveExitCode === 0 && !error)
@@ -1262,9 +1264,10 @@ export async function runSingleStepInner(step, ctx) {
1262
1264
  toolBudget,
1263
1265
  toolBudgetBlocked: toolBudgetBlocked || undefined,
1264
1266
  ...(finalResult?.effects ? { effects: finalResult.effects } : {}),
1265
- structuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : finalResult?.structuredOutput,
1266
- structuredOutputPath: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : effectiveStructuredOutput?.outputPath,
1267
- structuredOutputSchemaPath: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : effectiveStructuredOutput?.schemaPath,
1267
+ structuredOutput: finalResult?.structuredOutput,
1268
+ structuredOutputFailed: finalResult?.structuredOutputFailed,
1269
+ structuredOutputPath: effectiveStructuredOutput?.outputPath,
1270
+ structuredOutputSchemaPath: effectiveStructuredOutput?.schemaPath,
1268
1271
  acceptance: effectiveAcceptance,
1269
1272
  watchdog: finalResult?.watchdog,
1270
1273
  ...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
@@ -3594,6 +3597,7 @@ export async function runSubagent(config, childSessions) {
3594
3597
  review: pr.review,
3595
3598
  timeoutRecovery: pr.timeoutRecovery,
3596
3599
  structuredOutput: pr.structuredOutput,
3600
+ structuredOutputFailed: pr.structuredOutputFailed,
3597
3601
  structuredOutputPath: pr.structuredOutputPath,
3598
3602
  structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
3599
3603
  acceptance: pr.acceptance,
@@ -4043,6 +4047,7 @@ export async function runSubagent(config, childSessions) {
4043
4047
  review: pr.review,
4044
4048
  timeoutRecovery: pr.timeoutRecovery,
4045
4049
  structuredOutput: pr.structuredOutput,
4050
+ structuredOutputFailed: pr.structuredOutputFailed,
4046
4051
  structuredOutputPath: pr.structuredOutputPath,
4047
4052
  structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
4048
4053
  acceptance: pr.acceptance,
@@ -4348,6 +4353,7 @@ export async function runSubagent(config, childSessions) {
4348
4353
  review: singleResult.review,
4349
4354
  timeoutRecovery: singleResult.timeoutRecovery,
4350
4355
  structuredOutput: singleResult.structuredOutput,
4356
+ structuredOutputFailed: singleResult.structuredOutputFailed,
4351
4357
  structuredOutputPath: singleResult.structuredOutputPath,
4352
4358
  structuredOutputSchemaPath: singleResult.structuredOutputSchemaPath,
4353
4359
  acceptance: singleResult.acceptance,
@@ -4758,6 +4764,7 @@ export async function runSubagent(config, childSessions) {
4758
4764
  review: r.review,
4759
4765
  effects: r.effects,
4760
4766
  structuredOutput: r.structuredOutput,
4767
+ structuredOutputFailed: r.structuredOutputFailed,
4761
4768
  structuredOutputPath: r.structuredOutputPath,
4762
4769
  structuredOutputSchemaPath: r.structuredOutputSchemaPath,
4763
4770
  acceptance: r.acceptance,
@@ -4875,178 +4882,46 @@ export async function runSubagent(config, childSessions) {
4875
4882
  }
4876
4883
  }
4877
4884
  }
4878
- async function waitForStartupControl(controlPath, token, action, timeoutMs = 30_000) {
4879
- const deadline = Date.now() + timeoutMs;
4880
- while (Date.now() <= deadline) {
4881
- if (fs.existsSync(controlPath)) {
4882
- let payload;
4883
- try {
4884
- payload = JSON.parse(fs.readFileSync(controlPath, "utf-8"));
4885
- }
4886
- catch (error) {
4887
- throw new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);
4888
- }
4889
- if (payload.token !== token)
4890
- throw new Error("Runner startup control token does not match.");
4891
- if (payload.action === action)
4892
- return;
4893
- if (payload.action !== "ack" && payload.action !== "confirm" && payload.action !== "proceed")
4894
- throw new Error("Runner startup control action is invalid.");
4895
- }
4896
- await new Promise((resolve) => setTimeout(resolve, 20));
4897
- }
4898
- throw new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);
4899
- }
4900
- // Both hosts enter here: startup authorization, revival leases and disposal stay shared.
4901
- export async function runConfiguredSubagent(config, options) {
4902
- let lease;
4903
- let startupCommitted = config.revivalLease === undefined && config.launchBarrierToken === undefined;
4904
- const startupPath = path.join(config.asyncDir, "runner-startup.json");
4905
- const startupAckPath = path.join(config.asyncDir, "runner-startup-ack.json");
4906
- const startupConfirmPath = path.join(config.asyncDir, "runner-startup-confirm.json");
4907
- const startupProceedPath = path.join(config.asyncDir, "runner-startup-proceed.json");
4908
- const releaseOnExit = () => {
4909
- try {
4910
- lease?.release();
4911
- }
4912
- catch {
4913
- // Exit cleanup is best effort; a dead-owner lease is reclaimed on the next revival.
4914
- }
4915
- };
4916
- 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;
4917
4888
  try {
4918
- if (config.launchBarrierToken) {
4919
- await waitForStartupControl(startupProceedPath, config.launchBarrierToken, "proceed");
4920
- startupCommitted = true;
4921
- try {
4922
- fs.rmSync(startupProceedPath, { force: true });
4923
- }
4924
- catch {
4925
- // Startup control cleanup is best effort after the parent commits the run.
4926
- }
4927
- }
4928
- else if (config.revivalLease) {
4929
- lease = acquireSessionLease(config.revivalLease);
4930
- config.revivalLeaseToken = lease.owner.token;
4931
- writeAtomicJson(startupPath, { state: "ready", token: lease.owner.token, pid: process.pid, owner: lease.owner });
4932
- await waitForStartupControl(startupAckPath, lease.owner.token, "ack");
4933
- writeAtomicJson(startupPath, { state: "acknowledged", token: lease.owner.token, pid: process.pid });
4934
- await waitForStartupControl(startupConfirmPath, lease.owner.token, "confirm");
4935
- writeAtomicJson(startupPath, { state: "confirmed", token: lease.owner.token, pid: process.pid });
4936
- await waitForStartupControl(startupProceedPath, lease.owner.token, "proceed");
4937
- startupCommitted = true;
4938
- for (const controlPath of [startupAckPath, startupConfirmPath, startupProceedPath]) {
4939
- try {
4940
- fs.rmSync(controlPath, { force: true });
4941
- }
4942
- catch {
4943
- // Startup control cleanup is best effort after the parent commits the run.
4944
- }
4945
- }
4946
- }
4947
- const childSessions = await loadRunnerChildSessionFactory(config, options);
4948
- try {
4949
- await runSubagent(config, childSessions);
4950
- }
4951
- finally {
4952
- try {
4953
- await childSessions.dispose();
4954
- }
4955
- catch (error) {
4956
- console.error("Failed to dispose runner child sessions:", error);
4957
- }
4958
- }
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);
4959
4894
  }
4960
4895
  catch (error) {
4961
- if (!startupCommitted) {
4962
- try {
4963
- writeAtomicJson(startupPath, { state: "error", pid: process.pid, error: error instanceof Error ? error.message : String(error) });
4964
- }
4965
- catch {
4966
- // The parent will time out and terminate this runner if the handshake cannot be written.
4967
- }
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);
4968
4912
  }
4969
4913
  throw error;
4970
4914
  }
4971
- finally {
4972
- process.off("exit", releaseOnExit);
4973
- if (lease) {
4974
- let acknowledged = false;
4975
- try {
4976
- acknowledged = lease.release();
4977
- }
4978
- catch (error) {
4979
- console.error("Failed to release session revival lease:", error);
4980
- }
4981
- try {
4982
- markProcessTerminalCandidateLeaseRelease(config.asyncDir, lease.owner.token, acknowledged);
4983
- }
4984
- catch (error) {
4985
- console.error("Failed to record session revival lease release:", error);
4986
- }
4987
- }
4915
+ try {
4916
+ await runSubagent(config, childSessions);
4988
4917
  }
4989
- }
4990
- function startConfiguredSubagent(config) {
4991
- // Child sessions and the extensions loaded into them may leave handles
4992
- // behind even after shutdown; the run is fully persisted by now, so exit
4993
- // explicitly instead of waiting for the event loop to drain.
4994
- runConfiguredSubagent(config).then(() => process.exit(0), (runErr) => {
4995
- console.error("Subagent runner error:", runErr);
4996
- process.exit(1);
4997
- });
4998
- }
4999
- function monitorTestParent() {
5000
- const parentPid = Number(process.env.PI_SUBAGENTS_TEST_PARENT_PID);
5001
- if (!Number.isSafeInteger(parentPid) || parentPid <= 0 || parentPid === process.pid)
5002
- return;
5003
- const check = () => {
4918
+ finally {
5004
4919
  try {
5005
- process.kill(parentPid, 0);
5006
- }
5007
- catch {
5008
- process.exit(1);
4920
+ await childSessions.dispose();
5009
4921
  }
5010
- };
5011
- check();
5012
- setInterval(check, 250).unref();
5013
- }
5014
- if (isRunnerEntrypoint) {
5015
- monitorTestParent();
5016
- const configArg = process.argv[2];
5017
- if (configArg) {
5018
- try {
5019
- const configJson = fs.readFileSync(configArg, "utf-8");
5020
- const config = JSON.parse(configJson);
5021
- try {
5022
- fs.unlinkSync(configArg);
5023
- }
5024
- catch {
5025
- // Temp config cleanup is best effort.
5026
- }
5027
- startConfiguredSubagent(config);
5028
- }
5029
- catch (err) {
5030
- console.error("Subagent runner error:", err);
5031
- process.exit(1);
4922
+ catch (error) {
4923
+ console.error("Failed to dispose runner child sessions:", error);
5032
4924
  }
5033
4925
  }
5034
- else {
5035
- let input = "";
5036
- process.stdin.setEncoding("utf-8");
5037
- process.stdin.on("data", (chunk) => {
5038
- input += chunk;
5039
- });
5040
- process.stdin.on("end", () => {
5041
- try {
5042
- const config = JSON.parse(input);
5043
- startConfiguredSubagent(config);
5044
- }
5045
- catch (err) {
5046
- console.error("Subagent runner error:", err);
5047
- process.exit(1);
5048
- }
5049
- });
5050
- }
5051
4926
  }
5052
4927
  //# sourceMappingURL=subagent-runner.js.map