pi-subagents 0.75.0 → 0.76.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 (137) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/docs/agents.md +1 -1
  3. package/docs/configuration.md +4 -2
  4. package/docs/extension-api.md +1 -1
  5. package/docs/missions.md +12 -2
  6. package/docs/tool-reference.md +21 -6
  7. package/docs/workflows.md +1 -1
  8. package/package.json +2 -1
  9. package/src/agents/agent-memory.js +3 -3
  10. package/src/agents/agent-memory.js.map +1 -1
  11. package/src/agents/agent-serializer.d.ts.map +1 -1
  12. package/src/agents/agent-serializer.js +8 -1
  13. package/src/agents/agent-serializer.js.map +1 -1
  14. package/src/agents/agents.d.ts.map +1 -1
  15. package/src/agents/agents.js +101 -121
  16. package/src/agents/agents.js.map +1 -1
  17. package/src/extension/index.d.ts.map +1 -1
  18. package/src/extension/index.js +37 -4
  19. package/src/extension/index.js.map +1 -1
  20. package/src/extension/reply-workflow-script.d.ts.map +1 -1
  21. package/src/extension/reply-workflow-script.js +20 -11
  22. package/src/extension/reply-workflow-script.js.map +1 -1
  23. package/src/extension/schemas.d.ts +1 -1
  24. package/src/extension/schemas.js +8 -8
  25. package/src/extension/schemas.js.map +1 -1
  26. package/src/extension/tool-description.js +1 -1
  27. package/src/extension/tool-description.js.map +1 -1
  28. package/src/intercom/result-intercom.d.ts.map +1 -1
  29. package/src/intercom/result-intercom.js +2 -1
  30. package/src/intercom/result-intercom.js.map +1 -1
  31. package/src/profiles/profiles.d.ts.map +1 -1
  32. package/src/profiles/profiles.js +25 -22
  33. package/src/profiles/profiles.js.map +1 -1
  34. package/src/runs/background/active-async-capacity.d.ts +15 -1
  35. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  36. package/src/runs/background/active-async-capacity.js +51 -6
  37. package/src/runs/background/active-async-capacity.js.map +1 -1
  38. package/src/runs/background/async-job-tracker.d.ts +3 -2
  39. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  40. package/src/runs/background/async-job-tracker.js +2 -1
  41. package/src/runs/background/async-job-tracker.js.map +1 -1
  42. package/src/runs/background/calendar-schedule.d.ts +27 -0
  43. package/src/runs/background/calendar-schedule.d.ts.map +1 -0
  44. package/src/runs/background/calendar-schedule.js +94 -0
  45. package/src/runs/background/calendar-schedule.js.map +1 -0
  46. package/src/runs/background/notify.d.ts +6 -0
  47. package/src/runs/background/notify.d.ts.map +1 -1
  48. package/src/runs/background/notify.js +24 -4
  49. package/src/runs/background/notify.js.map +1 -1
  50. package/src/runs/background/result-watcher.d.ts +5 -1
  51. package/src/runs/background/result-watcher.d.ts.map +1 -1
  52. package/src/runs/background/result-watcher.js +44 -7
  53. package/src/runs/background/result-watcher.js.map +1 -1
  54. package/src/runs/background/run-child-session.d.ts +2 -0
  55. package/src/runs/background/run-child-session.d.ts.map +1 -1
  56. package/src/runs/background/run-child-session.js +12 -1
  57. package/src/runs/background/run-child-session.js.map +1 -1
  58. package/src/runs/background/scheduled-runs.d.ts +3 -1
  59. package/src/runs/background/scheduled-runs.d.ts.map +1 -1
  60. package/src/runs/background/scheduled-runs.js +184 -47
  61. package/src/runs/background/scheduled-runs.js.map +1 -1
  62. package/src/runs/background/subagent-runner.d.ts +1 -0
  63. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  64. package/src/runs/background/subagent-runner.js +14 -6
  65. package/src/runs/background/subagent-runner.js.map +1 -1
  66. package/src/runs/background/wait-completions.d.ts.map +1 -1
  67. package/src/runs/background/wait-completions.js +1 -0
  68. package/src/runs/background/wait-completions.js.map +1 -1
  69. package/src/runs/background/workflow-terminal-proof.d.ts +14 -1
  70. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -1
  71. package/src/runs/background/workflow-terminal-proof.js +41 -28
  72. package/src/runs/background/workflow-terminal-proof.js.map +1 -1
  73. package/src/runs/foreground/execution.d.ts.map +1 -1
  74. package/src/runs/foreground/execution.js +23 -3
  75. package/src/runs/foreground/execution.js.map +1 -1
  76. package/src/runs/foreground/foreground-history.d.ts.map +1 -1
  77. package/src/runs/foreground/foreground-history.js +1 -0
  78. package/src/runs/foreground/foreground-history.js.map +1 -1
  79. package/src/runs/foreground/subagent-executor.d.ts +1 -1
  80. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  81. package/src/runs/foreground/subagent-executor.js +44 -6
  82. package/src/runs/foreground/subagent-executor.js.map +1 -1
  83. package/src/runs/shared/child-session.d.ts.map +1 -1
  84. package/src/runs/shared/child-session.js +10 -2
  85. package/src/runs/shared/child-session.js.map +1 -1
  86. package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
  87. package/src/runs/shared/mcp-direct-tool-allowlist.js +5 -3
  88. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  89. package/src/runs/shared/parallel-handoff.d.ts +10 -4
  90. package/src/runs/shared/parallel-handoff.d.ts.map +1 -1
  91. package/src/runs/shared/parallel-handoff.js +53 -6
  92. package/src/runs/shared/parallel-handoff.js.map +1 -1
  93. package/src/runs/shared/partial-output.d.ts +18 -0
  94. package/src/runs/shared/partial-output.d.ts.map +1 -0
  95. package/src/runs/shared/partial-output.js +29 -0
  96. package/src/runs/shared/partial-output.js.map +1 -0
  97. package/src/runs/shared/worktree-cleanup-apply.d.ts +37 -0
  98. package/src/runs/shared/worktree-cleanup-apply.d.ts.map +1 -0
  99. package/src/runs/shared/worktree-cleanup-apply.js +179 -0
  100. package/src/runs/shared/worktree-cleanup-apply.js.map +1 -0
  101. package/src/runs/shared/worktree-cleanup-plan.d.ts +7 -0
  102. package/src/runs/shared/worktree-cleanup-plan.d.ts.map +1 -1
  103. package/src/runs/shared/worktree-cleanup-plan.js +41 -19
  104. package/src/runs/shared/worktree-cleanup-plan.js.map +1 -1
  105. package/src/runs/shared/worktree-lock.d.ts +6 -0
  106. package/src/runs/shared/worktree-lock.d.ts.map +1 -0
  107. package/src/runs/shared/worktree-lock.js +41 -0
  108. package/src/runs/shared/worktree-lock.js.map +1 -0
  109. package/src/runs/shared/worktree.d.ts +3 -0
  110. package/src/runs/shared/worktree.d.ts.map +1 -1
  111. package/src/runs/shared/worktree.js +9 -1
  112. package/src/runs/shared/worktree.js.map +1 -1
  113. package/src/shared/file-lease.d.ts +5 -0
  114. package/src/shared/file-lease.d.ts.map +1 -0
  115. package/src/shared/file-lease.js +101 -0
  116. package/src/shared/file-lease.js.map +1 -0
  117. package/src/shared/settings-file-lease.d.ts +5 -0
  118. package/src/shared/settings-file-lease.d.ts.map +1 -0
  119. package/src/shared/settings-file-lease.js +39 -0
  120. package/src/shared/settings-file-lease.js.map +1 -0
  121. package/src/shared/types.d.ts +10 -0
  122. package/src/shared/types.d.ts.map +1 -1
  123. package/src/shared/types.js.map +1 -1
  124. package/src/tui/render.d.ts.map +1 -1
  125. package/src/tui/render.js +7 -2
  126. package/src/tui/render.js.map +1 -1
  127. package/src/watchdog/diff-tool.js +2 -2
  128. package/src/watchdog/diff-tool.js.map +1 -1
  129. package/src/watchdog/register-main.js +1 -2
  130. package/src/watchdog/register-main.js.map +1 -1
  131. package/src/watchdog/runtime.d.ts +3 -3
  132. package/src/watchdog/runtime.d.ts.map +1 -1
  133. package/src/watchdog/runtime.js +7 -3
  134. package/src/watchdog/runtime.js.map +1 -1
  135. package/src/watchdog/settings.d.ts.map +1 -1
  136. package/src/watchdog/settings.js +22 -17
  137. package/src/watchdog/settings.js.map +1 -1
@@ -59,7 +59,7 @@ import { assertRequiredChildExtensionsAdmitted, hasMandatoryRequiredChildExtensi
59
59
  import { finalizeSingleOutput, injectSingleOutputInstruction, normalizeSingleOutputOverride, outputPathMappingFromTask, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.js";
60
60
  import { assertJsonSchemaObject, cleanupStructuredOutputRuntime, createStructuredOutputRuntime } from "../shared/structured-output.js";
61
61
  import { compactForegroundDetails, getSingleResultOutput, PROMPT_REDACTED, readStatus, resolveChildCwd, sumResultsCost, sumResultsUsage, toAgentToolUsage } from "../../shared/utils.js";
62
- import { discardPreservedWorktrees, formatParallelHandoffError, formatParallelHandoffReference, formatStoredParallelHandoffCleanup, parallelHandoffPath, readParallelHandoffManifest, recordParallelHandoffMerge, recordParallelHandoffSupersession, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.js";
62
+ import { discardPreservedWorktrees, formatParallelHandoffError, formatParallelHandoffReference, protectRetainedWorktreeForResume, formatStoredParallelHandoffCleanup, parallelHandoffPath, readParallelHandoffManifest, recordParallelHandoffMerge, recordParallelHandoffSupersession, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.js";
63
63
  import { summarizeContextModes } from "../shared/context-mode.js";
64
64
  import { attachNestedChildrenToResultChildren, buildSubagentResultIntercomPayload, deliverSubagentResultIntercomEvent, formatSubagentResultReceipt, resolveSubagentResultStatus, stripDetailsOutputsForIntercomReceipt, } from "../../intercom/result-intercom.js";
65
65
  import { applySteeringRecoveryAgentConfig, asyncReviveRequiresRecoveryDescriptor, buildRevivedAsyncTask, readAsyncRecoveryDescriptor, resolveAsyncResumeTarget, resolveAsyncRunLocation } from "../background/async-resume.js";
@@ -107,6 +107,7 @@ import { authorizeWorkflowResourceHost, claimWorkflowChildPermit, consumeWorkflo
107
107
  import { deepFreezeWorkflowArgs, normalizeWorkflowArgs, resolveStructuredWorkflowResource, resolveWorkflowResource } from "../../workflows/workflow-resources.js";
108
108
  import { stableJsonDigest } from "../../shared/launch-contract.js";
109
109
  import { cleanupWorktrees, createWorktrees, preflightWorktreeSource, withWorktreeTransaction, diffWorktrees, formatWorktreeDiffSummary, } from "../shared/worktree.js";
110
+ import { applyReviewedCleanupPlan, formatCleanupReceipt, loadReviewedCleanupPlan } from "../shared/worktree-cleanup-apply.js";
110
111
  import { createWorktreeCleanupPlan, formatWorktreeCleanupPlan } from "../shared/worktree-cleanup-plan.js";
111
112
  import { DIRS, DEFAULT_ARTIFACT_CONFIG, DEFAULT_MAX_OUTPUT, DEFAULT_FORK_PREAMBLE, SUBAGENT_ACTIONS, SUBAGENT_ASYNC_STARTED_EVENT, SUBAGENT_CHILD_STATUS_EVENT, SUBAGENT_CONTROL_EVENT, SUBAGENT_CONTROL_INTERCOM_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, SUBAGENT_LIFECYCLE_ARTIFACT_VERSION, checkSubagentDepth, resolveChildMaxSubagentDepth, resolveCurrentMaxSubagentDepth, resolveMaxSubagentSpawnsPerRun, truncateOutput, wrapForkTask, } from "../../shared/types.js";
112
113
  import { deriveChildSessionName } from "../../shared/child-session-name.js";
@@ -465,6 +466,7 @@ function rememberForegroundRun(state, input) {
465
466
  ...(result.error ? { error: result.error } : {}),
466
467
  ...(result.finalOutput ? { finalOutput: result.finalOutput } : {}),
467
468
  ...(result.outputState ? { outputState: result.outputState } : {}),
469
+ ...(result.outputPartial ? { outputPartial: true } : {}),
468
470
  ...(result.outputMode ? { outputMode: result.outputMode } : {}),
469
471
  ...(result.savedOutputPath ? { savedOutputPath: result.savedOutputPath } : {}),
470
472
  ...(result.outputSaveError ? { outputSaveError: result.outputSaveError } : {}),
@@ -549,6 +551,7 @@ function updateRememberedForegroundChild(state, input) {
549
551
  ...(input.result.error ? { error: input.result.error } : {}),
550
552
  ...(input.result.finalOutput ? { finalOutput: input.result.finalOutput } : {}),
551
553
  outputState: input.result.outputState,
554
+ outputPartial: input.result.outputPartial,
552
555
  outputMode: input.result.outputMode,
553
556
  savedOutputPath: input.result.savedOutputPath,
554
557
  outputSaveError: input.result.outputSaveError,
@@ -1645,6 +1648,19 @@ async function resumeAsyncRun(input) {
1645
1648
  : "External runners do not persist Pi sessions and cannot be resumed.";
1646
1649
  return { content: [{ type: "text", text: message }], isError: true, details: { mode: "management", results: [] } };
1647
1650
  }
1651
+ if (input.params.baseRef !== undefined && "managedWorktree" in target && target.managedWorktree === true) {
1652
+ return { content: [{ type: "text", text: "Cannot resume with baseRef: retained managed-worktree children continue in their existing worktree. Start a new worktree run from that base ref instead." }], isError: true, details: { mode: "management", results: [] } };
1653
+ }
1654
+ if (target.source === "async" && target.managedWorktree && target.asyncDir) {
1655
+ try {
1656
+ const protectedCwd = await protectRetainedWorktreeForResume(parallelHandoffPath(target.asyncDir), target.runId, target.index, input.signal);
1657
+ if (path.resolve(protectedCwd) !== path.resolve(effectiveCwd))
1658
+ throw new Error("Retained worktree cwd changed during resume admission.");
1659
+ }
1660
+ catch (error) {
1661
+ return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "management", results: [] } };
1662
+ }
1663
+ }
1648
1664
  if (target.source === "async" && target.runner?.type === "external-job") {
1649
1665
  if (attachChain)
1650
1666
  return { content: [{ type: "text", text: "External-job follow-up does not support chain attachment. Use action='resume' with message instead." }], isError: true, details: { mode: "management", results: [] } };
@@ -1792,9 +1808,6 @@ async function resumeAsyncRun(input) {
1792
1808
  if (!revivalSessionFile) {
1793
1809
  return { content: [{ type: "text", text: `Async run '${target.runId}' child ${target.index} does not have a persisted session file to resume from.` }], isError: true, details: { mode: "management", results: [] } };
1794
1810
  }
1795
- if (input.params.baseRef !== undefined && "managedWorktree" in target && target.managedWorktree === true) {
1796
- return { content: [{ type: "text", text: "Cannot resume with baseRef: retained managed-worktree children continue in their existing worktree. Start a new worktree run from that base ref instead." }], isError: true, details: { mode: "management", results: [] } };
1797
- }
1798
1811
  if (target.source === "async" && asyncReviveRequiresRecoveryDescriptor(target)) {
1799
1812
  return { content: [{ type: "text", text: `Async child '${target.runId}' is missing its required run fan-out recovery identity. Start a new run instead.` }], isError: true, details: { mode: "management", results: [] } };
1800
1813
  }
@@ -2080,6 +2093,7 @@ async function emitForegroundResultIntercom(input) {
2080
2093
  ...(result.sessionName ? { sessionName: result.sessionName } : {}),
2081
2094
  status: foregroundResultIntercomStatus(result),
2082
2095
  outputState: result.outputState ?? "unknown",
2096
+ ...(result.outputPartial ? { outputPartial: true } : {}),
2083
2097
  summary: resultSummaryForIntercom(result),
2084
2098
  index,
2085
2099
  artifactPath: result.artifactPaths?.outputPath,
@@ -6122,11 +6136,35 @@ export function createSubagentExecutor(deps) {
6122
6136
  if (deps.allowMutatingManagementActions === false) {
6123
6137
  return { content: [{ type: "text", text: "Action 'worktree.cleanup' is not available from child-safe subagent fanout mode." }], isError: true, details: { mode: "management", results: [] } };
6124
6138
  }
6139
+ if (paramsWithResolvedCwd.mode === "apply") {
6140
+ try {
6141
+ if (!paramsWithResolvedCwd.repo?.trim() || !paramsWithResolvedCwd.planId?.trim() || paramsWithResolvedCwd.handoffPath !== undefined)
6142
+ throw new Error("worktree.cleanup apply requires explicit repo and planId, without handoffPath.");
6143
+ const repo = path.resolve(requestCwd, paramsWithResolvedCwd.repo);
6144
+ const plan = loadReviewedCleanupPlan(repo, paramsWithResolvedCwd.planId);
6145
+ const decision = resolveAuthorityDecision({ action: "discardWorktree", ...(deps.config.authorityPolicy === undefined ? {} : { policy: deps.config.authorityPolicy }) });
6146
+ if (decision === "forbid")
6147
+ throw new Error("Authority policy forbids worktree cleanup.");
6148
+ if (decision === "confirm") {
6149
+ if (!ctx.hasUI)
6150
+ throw new Error("Authority policy requires interactive confirmation for worktree cleanup.");
6151
+ if (!await ctx.ui.confirm("Apply reviewed worktree cleanup?", `Repository: ${plan.repoRoot}\nPlan: ${plan.planId}\nRemove up to ${plan.entries.filter((entry) => entry.decision === "remove").length} eligible worktrees. All local branches are retained.`))
6152
+ return { content: [{ type: "text", text: "Worktree cleanup canceled." }], details: { mode: "management", results: [] } };
6153
+ }
6154
+ const applied = await applyReviewedCleanupPlan({ repo: plan.repoRoot, planId: plan.planId, authorized: true, signal,
6155
+ foregroundRunOwnership: (runId) => deps.state.foregroundControls.has(runId) ? "active" : (deps.state.foregroundRuns?.get(runId)?.children.length && deps.state.foregroundRuns.get(runId).children.every((child) => child.status !== "detached")) ? "terminal" : "unknown",
6156
+ });
6157
+ return { content: [{ type: "text", text: formatCleanupReceipt(applied) }], details: { mode: "management", results: [] } };
6158
+ }
6159
+ catch (error) {
6160
+ return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "management", results: [] } };
6161
+ }
6162
+ }
6125
6163
  if (paramsWithResolvedCwd.mode !== "plan") {
6126
- return { content: [{ type: "text", text: "worktree.cleanup currently supports mode='plan' only; apply/removal is not available yet." }], isError: true, details: { mode: "management", results: [] } };
6164
+ return { content: [{ type: "text", text: "worktree.cleanup requires mode='plan' or mode='apply'." }], isError: true, details: { mode: "management", results: [] } };
6127
6165
  }
6128
6166
  if (paramsWithResolvedCwd.planId !== undefined) {
6129
- return { content: [{ type: "text", text: "worktree.cleanup plan mode does not accept planId; apply is not available yet." }], isError: true, details: { mode: "management", results: [] } };
6167
+ return { content: [{ type: "text", text: "worktree.cleanup plan mode does not accept planId." }], isError: true, details: { mode: "management", results: [] } };
6130
6168
  }
6131
6169
  try {
6132
6170
  const created = createWorktreeCleanupPlan({