pi-subagents 0.74.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.
- package/CHANGELOG.md +83 -0
- package/docs/agents.md +15 -5
- package/docs/configuration.md +14 -2
- package/docs/extension-api.md +2 -2
- package/docs/missions.md +27 -3
- package/docs/models.md +6 -2
- package/docs/observability.md +8 -3
- package/docs/tool-reference.md +48 -8
- package/docs/workflows.md +3 -3
- package/package.json +2 -1
- package/src/agents/agent-memory.js +3 -3
- package/src/agents/agent-memory.js.map +1 -1
- package/src/agents/agent-serializer.d.ts.map +1 -1
- package/src/agents/agent-serializer.js +8 -1
- package/src/agents/agent-serializer.js.map +1 -1
- package/src/agents/agents.d.ts +1 -0
- package/src/agents/agents.d.ts.map +1 -1
- package/src/agents/agents.js +137 -95
- package/src/agents/agents.js.map +1 -1
- package/src/api/preflight.d.ts +1 -1
- package/src/api/preflight.d.ts.map +1 -1
- package/src/api/preflight.js +44 -1
- package/src/api/preflight.js.map +1 -1
- package/src/extension/config.d.ts.map +1 -1
- package/src/extension/config.js +4 -1
- package/src/extension/config.js.map +1 -1
- package/src/extension/index.d.ts.map +1 -1
- package/src/extension/index.js +62 -22
- package/src/extension/index.js.map +1 -1
- package/src/extension/public-execution.d.ts.map +1 -1
- package/src/extension/public-execution.js +4 -0
- package/src/extension/public-execution.js.map +1 -1
- package/src/extension/reply-workflow-script.d.ts.map +1 -1
- package/src/extension/reply-workflow-script.js +21 -12
- package/src/extension/reply-workflow-script.js.map +1 -1
- package/src/extension/rpc.js +1 -1
- package/src/extension/rpc.js.map +1 -1
- package/src/extension/schemas.d.ts +2 -1
- package/src/extension/schemas.d.ts.map +1 -1
- package/src/extension/schemas.js +13 -11
- package/src/extension/schemas.js.map +1 -1
- package/src/extension/tool-description.js +2 -2
- package/src/extension/tool-description.js.map +1 -1
- package/src/intercom/result-intercom.d.ts.map +1 -1
- package/src/intercom/result-intercom.js +2 -1
- package/src/intercom/result-intercom.js.map +1 -1
- package/src/missions/goal-driver.d.ts +1 -0
- package/src/missions/goal-driver.d.ts.map +1 -1
- package/src/missions/goal-driver.js +49 -34
- package/src/missions/goal-driver.js.map +1 -1
- package/src/missions/store.d.ts.map +1 -1
- package/src/missions/store.js +11 -1
- package/src/missions/store.js.map +1 -1
- package/src/profiles/profiles.d.ts +1 -1
- package/src/profiles/profiles.d.ts.map +1 -1
- package/src/profiles/profiles.js +29 -22
- package/src/profiles/profiles.js.map +1 -1
- package/src/runs/background/active-async-capacity.d.ts +15 -1
- package/src/runs/background/active-async-capacity.d.ts.map +1 -1
- package/src/runs/background/active-async-capacity.js +51 -6
- package/src/runs/background/active-async-capacity.js.map +1 -1
- package/src/runs/background/async-execution.d.ts +13 -0
- package/src/runs/background/async-execution.d.ts.map +1 -1
- package/src/runs/background/async-execution.js +89 -6
- package/src/runs/background/async-execution.js.map +1 -1
- package/src/runs/background/async-job-tracker.d.ts +4 -2
- package/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/src/runs/background/async-job-tracker.js +4 -3
- package/src/runs/background/async-job-tracker.js.map +1 -1
- package/src/runs/background/await-async-run.d.ts.map +1 -1
- package/src/runs/background/await-async-run.js +4 -2
- package/src/runs/background/await-async-run.js.map +1 -1
- package/src/runs/background/calendar-schedule.d.ts +27 -0
- package/src/runs/background/calendar-schedule.d.ts.map +1 -0
- package/src/runs/background/calendar-schedule.js +94 -0
- package/src/runs/background/calendar-schedule.js.map +1 -0
- package/src/runs/background/control-channel.d.ts +10 -0
- package/src/runs/background/control-channel.d.ts.map +1 -1
- package/src/runs/background/control-channel.js +51 -0
- package/src/runs/background/control-channel.js.map +1 -1
- package/src/runs/background/notify.d.ts +6 -0
- package/src/runs/background/notify.d.ts.map +1 -1
- package/src/runs/background/notify.js +24 -4
- package/src/runs/background/notify.js.map +1 -1
- package/src/runs/background/result-watcher.d.ts +5 -1
- package/src/runs/background/result-watcher.d.ts.map +1 -1
- package/src/runs/background/result-watcher.js +44 -7
- package/src/runs/background/result-watcher.js.map +1 -1
- package/src/runs/background/run-child-session.d.ts +2 -0
- package/src/runs/background/run-child-session.d.ts.map +1 -1
- package/src/runs/background/run-child-session.js +32 -7
- package/src/runs/background/run-child-session.js.map +1 -1
- package/src/runs/background/runner-aliases.d.ts +1 -0
- package/src/runs/background/runner-aliases.d.ts.map +1 -1
- package/src/runs/background/runner-aliases.js +6 -2
- package/src/runs/background/runner-aliases.js.map +1 -1
- package/src/runs/background/scheduled-runs.d.ts +5 -2
- package/src/runs/background/scheduled-runs.d.ts.map +1 -1
- package/src/runs/background/scheduled-runs.js +210 -56
- package/src/runs/background/scheduled-runs.js.map +1 -1
- package/src/runs/background/stale-run-reconciler.d.ts +1 -1
- package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
- package/src/runs/background/stale-run-reconciler.js +15 -2
- package/src/runs/background/stale-run-reconciler.js.map +1 -1
- package/src/runs/background/subagent-runner.d.ts +1 -0
- package/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/src/runs/background/subagent-runner.js +58 -9
- package/src/runs/background/subagent-runner.js.map +1 -1
- package/src/runs/background/wait-completions.d.ts.map +1 -1
- package/src/runs/background/wait-completions.js +1 -0
- package/src/runs/background/wait-completions.js.map +1 -1
- package/src/runs/background/workflow-terminal-proof.d.ts +14 -1
- package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -1
- package/src/runs/background/workflow-terminal-proof.js +41 -28
- package/src/runs/background/workflow-terminal-proof.js.map +1 -1
- package/src/runs/foreground/command-action.d.ts +13 -0
- package/src/runs/foreground/command-action.d.ts.map +1 -0
- package/src/runs/foreground/command-action.js +38 -0
- package/src/runs/foreground/command-action.js.map +1 -0
- package/src/runs/foreground/execution.d.ts.map +1 -1
- package/src/runs/foreground/execution.js +42 -8
- package/src/runs/foreground/execution.js.map +1 -1
- package/src/runs/foreground/foreground-history.d.ts.map +1 -1
- package/src/runs/foreground/foreground-history.js +1 -0
- package/src/runs/foreground/foreground-history.js.map +1 -1
- package/src/runs/foreground/subagent-executor.d.ts +2 -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/child-commands.d.ts +28 -0
- package/src/runs/shared/child-commands.d.ts.map +1 -0
- package/src/runs/shared/child-commands.js +250 -0
- package/src/runs/shared/child-commands.js.map +1 -0
- package/src/runs/shared/child-session.d.ts +4 -0
- package/src/runs/shared/child-session.d.ts.map +1 -1
- package/src/runs/shared/child-session.js +107 -22
- package/src/runs/shared/child-session.js.map +1 -1
- package/src/runs/shared/child-tool-plan.js +1 -1
- package/src/runs/shared/child-tool-plan.js.map +1 -1
- package/src/runs/shared/claude-code-adapter.d.ts +56 -0
- package/src/runs/shared/claude-code-adapter.d.ts.map +1 -1
- package/src/runs/shared/claude-code-adapter.js +138 -2
- package/src/runs/shared/claude-code-adapter.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-preflight.d.ts +10 -0
- package/src/runs/shared/external-cli-preflight.d.ts.map +1 -1
- package/src/runs/shared/external-cli-preflight.js +50 -6
- package/src/runs/shared/external-cli-preflight.js.map +1 -1
- package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
- package/src/runs/shared/external-cli-runner.js +4 -2
- package/src/runs/shared/external-cli-runner.js.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.js +8 -5
- package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
- package/src/runs/shared/model-resolution.d.ts +6 -2
- package/src/runs/shared/model-resolution.d.ts.map +1 -1
- package/src/runs/shared/model-resolution.js +9 -2
- package/src/runs/shared/model-resolution.js.map +1 -1
- package/src/runs/shared/parallel-handoff.d.ts +10 -4
- package/src/runs/shared/parallel-handoff.d.ts.map +1 -1
- package/src/runs/shared/parallel-handoff.js +53 -6
- package/src/runs/shared/parallel-handoff.js.map +1 -1
- package/src/runs/shared/parallel-utils.d.ts +2 -0
- 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/partial-output.d.ts +18 -0
- package/src/runs/shared/partial-output.d.ts.map +1 -0
- package/src/runs/shared/partial-output.js +29 -0
- package/src/runs/shared/partial-output.js.map +1 -0
- package/src/runs/shared/run-history.d.ts +47 -0
- package/src/runs/shared/run-history.d.ts.map +1 -1
- package/src/runs/shared/run-history.js +70 -0
- package/src/runs/shared/run-history.js.map +1 -1
- package/src/runs/shared/subagent-control.d.ts.map +1 -1
- package/src/runs/shared/subagent-control.js +30 -17
- package/src/runs/shared/subagent-control.js.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.d.ts +1 -0
- package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.js +12 -5
- package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/src/runs/shared/worktree-cleanup-apply.d.ts +37 -0
- package/src/runs/shared/worktree-cleanup-apply.d.ts.map +1 -0
- package/src/runs/shared/worktree-cleanup-apply.js +179 -0
- package/src/runs/shared/worktree-cleanup-apply.js.map +1 -0
- package/src/runs/shared/worktree-cleanup-plan.d.ts +7 -0
- package/src/runs/shared/worktree-cleanup-plan.d.ts.map +1 -1
- package/src/runs/shared/worktree-cleanup-plan.js +41 -19
- package/src/runs/shared/worktree-cleanup-plan.js.map +1 -1
- package/src/runs/shared/worktree-lock.d.ts +6 -0
- package/src/runs/shared/worktree-lock.d.ts.map +1 -0
- package/src/runs/shared/worktree-lock.js +41 -0
- package/src/runs/shared/worktree-lock.js.map +1 -0
- package/src/runs/shared/worktree.d.ts +3 -0
- package/src/runs/shared/worktree.d.ts.map +1 -1
- package/src/runs/shared/worktree.js +9 -1
- package/src/runs/shared/worktree.js.map +1 -1
- package/src/shared/file-lease.d.ts +5 -0
- package/src/shared/file-lease.d.ts.map +1 -0
- package/src/shared/file-lease.js +101 -0
- package/src/shared/file-lease.js.map +1 -0
- package/src/shared/required-child-extensions.d.ts +16 -1
- package/src/shared/required-child-extensions.d.ts.map +1 -1
- package/src/shared/required-child-extensions.js +37 -5
- package/src/shared/required-child-extensions.js.map +1 -1
- package/src/shared/settings-file-lease.d.ts +5 -0
- package/src/shared/settings-file-lease.d.ts.map +1 -0
- package/src/shared/settings-file-lease.js +39 -0
- package/src/shared/settings-file-lease.js.map +1 -0
- package/src/shared/types.d.ts +16 -1
- package/src/shared/types.d.ts.map +1 -1
- package/src/shared/types.js +1 -1
- package/src/shared/types.js.map +1 -1
- package/src/slash/subagent-cost.d.ts.map +1 -1
- package/src/slash/subagent-cost.js +8 -4
- package/src/slash/subagent-cost.js.map +1 -1
- package/src/tui/render.d.ts +1 -1
- package/src/tui/render.d.ts.map +1 -1
- package/src/tui/render.js +11 -6
- package/src/tui/render.js.map +1 -1
- package/src/watchdog/diff-tool.js +2 -2
- package/src/watchdog/diff-tool.js.map +1 -1
- package/src/watchdog/register-main.js +1 -2
- package/src/watchdog/register-main.js.map +1 -1
- package/src/watchdog/runtime.d.ts +3 -3
- package/src/watchdog/runtime.d.ts.map +1 -1
- package/src/watchdog/runtime.js +7 -3
- package/src/watchdog/runtime.js.map +1 -1
- package/src/watchdog/settings.d.ts.map +1 -1
- package/src/watchdog/settings.js +22 -17
- package/src/watchdog/settings.js.map +1 -1
- package/src/workflows/workflow-receipt.js +2 -2
- package/src/workflows/workflow-receipt.js.map +1 -1
- package/src/workflows/workflow-resources.d.ts +4 -0
- package/src/workflows/workflow-resources.d.ts.map +1 -1
- package/src/workflows/workflow-resources.js +7 -4
- package/src/workflows/workflow-resources.js.map +1 -1
|
@@ -19,6 +19,7 @@ import { isWorkflowScriptPath, normalizePublicSubagentExecution, validateWorkflo
|
|
|
19
19
|
import { readReplyWorkflowScript } from "../../extension/reply-workflow-script.js";
|
|
20
20
|
import { disabledFeatureNotice, disabledFeatureUseError, resolveDisabledFeatureSurface } from "../../shared/disabled-features.js";
|
|
21
21
|
import { runSync } from "./execution.js";
|
|
22
|
+
import { commandAction } from "./command-action.js";
|
|
22
23
|
import { handleWatchdogToolAction, WATCHDOG_TOOL_ACTIONS } from "../../watchdog/tool-actions.js";
|
|
23
24
|
import { applyWatchdogLaunchRules } from "../../watchdog/rules.js";
|
|
24
25
|
import { childWatchdogProgressForModel } from "../../watchdog/child-status.js";
|
|
@@ -54,11 +55,11 @@ import { usageBudgetExceededMessage, usageBudgetState, validateUsageBudgetConfig
|
|
|
54
55
|
import { assertAgentAllowedByCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling } from "../shared/capability-ceiling.js";
|
|
55
56
|
import { isAgentContract } from "../shared/agent-contract.js";
|
|
56
57
|
import { normalizeExtensionBindings } from "../shared/extension-bindings.js";
|
|
57
|
-
import { resolveRequiredChildExtensions } from "../../shared/required-child-extensions.js";
|
|
58
|
+
import { assertRequiredChildExtensionsAdmitted, hasMandatoryRequiredChildExtensions, readRetainedRequiredChildExtensions, resolveRequiredChildExtensions } from "../../shared/required-child-extensions.js";
|
|
58
59
|
import { finalizeSingleOutput, injectSingleOutputInstruction, normalizeSingleOutputOverride, outputPathMappingFromTask, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.js";
|
|
59
60
|
import { assertJsonSchemaObject, cleanupStructuredOutputRuntime, createStructuredOutputRuntime } from "../shared/structured-output.js";
|
|
60
61
|
import { compactForegroundDetails, getSingleResultOutput, PROMPT_REDACTED, readStatus, resolveChildCwd, sumResultsCost, sumResultsUsage, toAgentToolUsage } from "../../shared/utils.js";
|
|
61
|
-
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";
|
|
62
63
|
import { summarizeContextModes } from "../shared/context-mode.js";
|
|
63
64
|
import { attachNestedChildrenToResultChildren, buildSubagentResultIntercomPayload, deliverSubagentResultIntercomEvent, formatSubagentResultReceipt, resolveSubagentResultStatus, stripDetailsOutputsForIntercomReceipt, } from "../../intercom/result-intercom.js";
|
|
64
65
|
import { applySteeringRecoveryAgentConfig, asyncReviveRequiresRecoveryDescriptor, buildRevivedAsyncTask, readAsyncRecoveryDescriptor, resolveAsyncResumeTarget, resolveAsyncRunLocation } from "../background/async-resume.js";
|
|
@@ -106,11 +107,12 @@ import { authorizeWorkflowResourceHost, claimWorkflowChildPermit, consumeWorkflo
|
|
|
106
107
|
import { deepFreezeWorkflowArgs, normalizeWorkflowArgs, resolveStructuredWorkflowResource, resolveWorkflowResource } from "../../workflows/workflow-resources.js";
|
|
107
108
|
import { stableJsonDigest } from "../../shared/launch-contract.js";
|
|
108
109
|
import { cleanupWorktrees, createWorktrees, preflightWorktreeSource, withWorktreeTransaction, diffWorktrees, formatWorktreeDiffSummary, } from "../shared/worktree.js";
|
|
110
|
+
import { applyReviewedCleanupPlan, formatCleanupReceipt, loadReviewedCleanupPlan } from "../shared/worktree-cleanup-apply.js";
|
|
109
111
|
import { createWorktreeCleanupPlan, formatWorktreeCleanupPlan } from "../shared/worktree-cleanup-plan.js";
|
|
110
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";
|
|
111
113
|
import { deriveChildSessionName } from "../../shared/child-session-name.js";
|
|
112
|
-
const MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete", "eject", "disable", "enable", "reset", "grant-spawn-budget", "watchdog.configure", "mission.create", "mission.update", "mission.resolve-decision", "mission.attach-run", "mission.close", "inspector.open", "inspector.close", "project.open", "project.close", "worktree.discard", "worktree.cleanup", "lane.recordMerge", "lane.recordSupersession", "refine", "refine.rollback", "dismiss", "schedule.create", "schedule.pause", "schedule.resume", "schedule.run", "schedule.run-due", "schedule.delete"]);
|
|
113
|
-
const DESTRUCTIVE_MANAGEMENT_ACTIONS = new Set(["delete", "eject", "disable", "reset", "mission.close", "worktree.discard", "refine.rollback", "inspector.close", "project.close", "stop", "interrupt", "schedule.delete"]);
|
|
114
|
+
const MUTATING_MANAGEMENT_ACTIONS = new Set(["command.yield", "command.cancel", "create", "update", "delete", "eject", "disable", "enable", "reset", "grant-spawn-budget", "watchdog.configure", "mission.create", "mission.update", "mission.resolve-decision", "mission.attach-run", "mission.close", "inspector.open", "inspector.close", "project.open", "project.close", "worktree.discard", "worktree.cleanup", "lane.recordMerge", "lane.recordSupersession", "refine", "refine.rollback", "dismiss", "schedule.create", "schedule.pause", "schedule.resume", "schedule.run", "schedule.run-due", "schedule.delete"]);
|
|
115
|
+
const DESTRUCTIVE_MANAGEMENT_ACTIONS = new Set(["command.cancel", "delete", "eject", "disable", "reset", "mission.close", "worktree.discard", "refine.rollback", "inspector.close", "project.close", "stop", "interrupt", "schedule.delete"]);
|
|
114
116
|
function resolveSteerDeliveryMode(mode) {
|
|
115
117
|
return mode === "steer" || mode === "follow_up" || mode === "auto" ? mode : undefined;
|
|
116
118
|
}
|
|
@@ -464,6 +466,7 @@ function rememberForegroundRun(state, input) {
|
|
|
464
466
|
...(result.error ? { error: result.error } : {}),
|
|
465
467
|
...(result.finalOutput ? { finalOutput: result.finalOutput } : {}),
|
|
466
468
|
...(result.outputState ? { outputState: result.outputState } : {}),
|
|
469
|
+
...(result.outputPartial ? { outputPartial: true } : {}),
|
|
467
470
|
...(result.outputMode ? { outputMode: result.outputMode } : {}),
|
|
468
471
|
...(result.savedOutputPath ? { savedOutputPath: result.savedOutputPath } : {}),
|
|
469
472
|
...(result.outputSaveError ? { outputSaveError: result.outputSaveError } : {}),
|
|
@@ -548,6 +551,7 @@ function updateRememberedForegroundChild(state, input) {
|
|
|
548
551
|
...(input.result.error ? { error: input.result.error } : {}),
|
|
549
552
|
...(input.result.finalOutput ? { finalOutput: input.result.finalOutput } : {}),
|
|
550
553
|
outputState: input.result.outputState,
|
|
554
|
+
outputPartial: input.result.outputPartial,
|
|
551
555
|
outputMode: input.result.outputMode,
|
|
552
556
|
savedOutputPath: input.result.savedOutputPath,
|
|
553
557
|
outputSaveError: input.result.outputSaveError,
|
|
@@ -960,6 +964,17 @@ function appendStepToAsyncChain(input) {
|
|
|
960
964
|
details: { mode: "management", results: [] },
|
|
961
965
|
};
|
|
962
966
|
}
|
|
967
|
+
let retainedRequiredExtensions;
|
|
968
|
+
try {
|
|
969
|
+
retainedRequiredExtensions = readRetainedRequiredChildExtensions(resolved.location.asyncDir);
|
|
970
|
+
}
|
|
971
|
+
catch (error) {
|
|
972
|
+
return {
|
|
973
|
+
content: [{ type: "text", text: `Cannot append step to run '${resolved.id}': ${error instanceof Error ? error.message : String(error)}` }],
|
|
974
|
+
isError: true,
|
|
975
|
+
details: { mode: "management", results: [] },
|
|
976
|
+
};
|
|
977
|
+
}
|
|
963
978
|
const pendingAppendRequests = readPendingChainAppendRequests(resolved.location.asyncDir);
|
|
964
979
|
const reservedOutputNames = new Set([
|
|
965
980
|
...Object.keys(status.outputs ?? {}),
|
|
@@ -1031,6 +1046,7 @@ function appendStepToAsyncChain(input) {
|
|
|
1031
1046
|
asyncDir: resolved.location.asyncDir,
|
|
1032
1047
|
validateOutputBindings: false,
|
|
1033
1048
|
capabilityCeiling: intersectSubagentCapabilityCeilings(status.capabilityCeiling, resolveCurrentSubagentCapabilityCeiling(asyncCtx.currentSessionId)),
|
|
1049
|
+
requiredExtensions: retainedRequiredExtensions,
|
|
1034
1050
|
}));
|
|
1035
1051
|
if ("error" in built) {
|
|
1036
1052
|
return {
|
|
@@ -1632,6 +1648,19 @@ async function resumeAsyncRun(input) {
|
|
|
1632
1648
|
: "External runners do not persist Pi sessions and cannot be resumed.";
|
|
1633
1649
|
return { content: [{ type: "text", text: message }], isError: true, details: { mode: "management", results: [] } };
|
|
1634
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
|
+
}
|
|
1635
1664
|
if (target.source === "async" && target.runner?.type === "external-job") {
|
|
1636
1665
|
if (attachChain)
|
|
1637
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: [] } };
|
|
@@ -1779,9 +1808,6 @@ async function resumeAsyncRun(input) {
|
|
|
1779
1808
|
if (!revivalSessionFile) {
|
|
1780
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: [] } };
|
|
1781
1810
|
}
|
|
1782
|
-
if (input.params.baseRef !== undefined && "managedWorktree" in target && target.managedWorktree === true) {
|
|
1783
|
-
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: [] } };
|
|
1784
|
-
}
|
|
1785
1811
|
if (target.source === "async" && asyncReviveRequiresRecoveryDescriptor(target)) {
|
|
1786
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: [] } };
|
|
1787
1813
|
}
|
|
@@ -2067,6 +2093,7 @@ async function emitForegroundResultIntercom(input) {
|
|
|
2067
2093
|
...(result.sessionName ? { sessionName: result.sessionName } : {}),
|
|
2068
2094
|
status: foregroundResultIntercomStatus(result),
|
|
2069
2095
|
outputState: result.outputState ?? "unknown",
|
|
2096
|
+
...(result.outputPartial ? { outputPartial: true } : {}),
|
|
2070
2097
|
summary: resultSummaryForIntercom(result),
|
|
2071
2098
|
index,
|
|
2072
2099
|
artifactPath: result.artifactPaths?.outputPath,
|
|
@@ -3069,6 +3096,7 @@ async function runAsyncPath(data, deps) {
|
|
|
3069
3096
|
goal: params.task ?? "",
|
|
3070
3097
|
agentConfig: a,
|
|
3071
3098
|
recoveryAgentConfig: data.recoveryAgents.find((agent) => agent.name === params.agent),
|
|
3099
|
+
requiredExtensions: data.requiredExtensions,
|
|
3072
3100
|
ctx: asyncCtx,
|
|
3073
3101
|
availableModels,
|
|
3074
3102
|
cwd: effectiveCwd,
|
|
@@ -3455,8 +3483,10 @@ async function runSinglePath(data, deps) {
|
|
|
3455
3483
|
}
|
|
3456
3484
|
let foregroundMachine;
|
|
3457
3485
|
const requestedMachine = params.machine ?? agentConfig.machine;
|
|
3486
|
+
const requiredExtensions = data.requiredExtensions ?? deps.childRuntime?.requiredExtensions ?? resolveRequiredChildExtensions(data.parentPiSessionId);
|
|
3458
3487
|
if (requestedMachine) {
|
|
3459
3488
|
try {
|
|
3489
|
+
assertRequiredChildExtensionsAdmitted([requiredExtensions], { agent: agentConfig.name, runnerType: agentConfig.runner?.type, machine: requestedMachine });
|
|
3460
3490
|
foregroundMachine = resolveHerdrMachinePlacement({ machine: requestedMachine, cwd: ctx.cwd, stepCwd: params.machineCwd }).machine;
|
|
3461
3491
|
}
|
|
3462
3492
|
catch (error) {
|
|
@@ -3643,7 +3673,6 @@ async function runSinglePath(data, deps) {
|
|
|
3643
3673
|
}
|
|
3644
3674
|
: undefined;
|
|
3645
3675
|
const deadlineAt = data.deadlineAt ?? (data.timeoutMs !== undefined ? Date.now() + data.timeoutMs : undefined);
|
|
3646
|
-
const requiredExtensions = deps.childRuntime?.requiredExtensions ?? resolveRequiredChildExtensions(data.parentPiSessionId);
|
|
3647
3676
|
let r;
|
|
3648
3677
|
let resolveDetachedWorkflowChild;
|
|
3649
3678
|
const detachedWorkflowChild = params.workflowAwaitDetached === true
|
|
@@ -3900,6 +3929,7 @@ function duplicateSubagentCallResult(params) {
|
|
|
3900
3929
|
}
|
|
3901
3930
|
const workflowLaunchObservers = new WeakMap();
|
|
3902
3931
|
const workflowOwnedUsageBudgets = new WeakMap();
|
|
3932
|
+
const workflowRetainedRequiredExtensions = new WeakMap();
|
|
3903
3933
|
/**
|
|
3904
3934
|
* Terminal-mission retention can remove a mission while its children still
|
|
3905
3935
|
* report. Remember it to prevent later heartbeats from warning repeatedly.
|
|
@@ -4087,7 +4117,11 @@ function workflowOutputPathMappingSummary(children) {
|
|
|
4087
4117
|
return mappings.length > 0 ? ` Output path mappings: ${mappings.join("; ")}.` : "";
|
|
4088
4118
|
}
|
|
4089
4119
|
function workflowDetailsResults(children) {
|
|
4090
|
-
return children.flatMap((child) => (child.results ?? []).map((result) =>
|
|
4120
|
+
return children.flatMap((child) => (child.results ?? []).map((result) => ({
|
|
4121
|
+
...result,
|
|
4122
|
+
workflowKey: result.workflowKey ?? child.key,
|
|
4123
|
+
...(child.runId && !result.runId ? { runId: child.runId } : {}),
|
|
4124
|
+
})));
|
|
4091
4125
|
}
|
|
4092
4126
|
function workflowSteerReceipt(key, result) {
|
|
4093
4127
|
const steering = result.details.steering;
|
|
@@ -4625,6 +4659,7 @@ export function createSubagentExecutor(deps) {
|
|
|
4625
4659
|
const execute = async (_id, params, signal, onUpdate, ctx, preserveActiveSession = false, parentModelOverride) => {
|
|
4626
4660
|
const workflowLaunchObserver = workflowLaunchObservers.get(params);
|
|
4627
4661
|
const inheritedUsageBudget = workflowOwnedUsageBudgets.get(params);
|
|
4662
|
+
const retainedRequiredExtensions = workflowRetainedRequiredExtensions.get(params);
|
|
4628
4663
|
const delegatedThinkingOverride = delegatedThinkingOverrides.get(params);
|
|
4629
4664
|
const allowZeroToolBudget = delegatedZeroToolBudgets.has(params);
|
|
4630
4665
|
const delegatedExecution = delegatedExecutions.has(params);
|
|
@@ -4655,6 +4690,12 @@ export function createSubagentExecutor(deps) {
|
|
|
4655
4690
|
? currentParentModel
|
|
4656
4691
|
: rememberParentModel(deps.state, resolveCurrentSessionId(ctx.sessionManager), currentParentModel)) ?? null;
|
|
4657
4692
|
})();
|
|
4693
|
+
// validate checks args with the same normalization launch uses, reported beside script errors.
|
|
4694
|
+
const validateWorkflowRequest = () => {
|
|
4695
|
+
const validation = validateWorkflowScript(requestParams.workflowScript ?? "", workflowValidationOptions(deps, requestParams, ctx.cwd, () => resolveWorkflowParentModel()?.provider));
|
|
4696
|
+
const normalizedArgs = normalizeWorkflowArgs(requestParams.args);
|
|
4697
|
+
return "error" in normalizedArgs ? { ...validation, ok: false, errors: [...validation.errors, { message: normalizedArgs.error }] } : validation;
|
|
4698
|
+
};
|
|
4658
4699
|
try {
|
|
4659
4700
|
if (requestParams.preflight !== undefined && requestParams.workflowScript === undefined) {
|
|
4660
4701
|
throw new Error("preflight requires workflow: true or a workflow script path.");
|
|
@@ -4666,7 +4707,7 @@ export function createSubagentExecutor(deps) {
|
|
|
4666
4707
|
catch (error) {
|
|
4667
4708
|
const message = error instanceof Error ? error.message : String(error);
|
|
4668
4709
|
if (requestParams.action?.trim() === "validate") {
|
|
4669
|
-
const validation =
|
|
4710
|
+
const validation = validateWorkflowRequest();
|
|
4670
4711
|
const invalidValidation = { ...validation, ok: false, errors: [...validation.errors, { message }] };
|
|
4671
4712
|
return {
|
|
4672
4713
|
content: [{ type: "text", text: JSON.stringify(invalidValidation) }],
|
|
@@ -4677,8 +4718,7 @@ export function createSubagentExecutor(deps) {
|
|
|
4677
4718
|
return buildRequestedModeError(requestParams, message);
|
|
4678
4719
|
}
|
|
4679
4720
|
if (requestParams.action?.trim() === "validate") {
|
|
4680
|
-
|
|
4681
|
-
return buildWorkflowValidationResult(validation, "management", workflowPreflight);
|
|
4721
|
+
return buildWorkflowValidationResult(validateWorkflowRequest(), "management", workflowPreflight);
|
|
4682
4722
|
}
|
|
4683
4723
|
const normalizedAction = typeof requestParams.action === "string" ? requestParams.action.trim() : requestParams.action;
|
|
4684
4724
|
if (normalizedAction === "resume" && requestParams.extensionBindings !== undefined)
|
|
@@ -4713,6 +4753,9 @@ export function createSubagentExecutor(deps) {
|
|
|
4713
4753
|
const acceptanceErrors = validateAcceptanceInput(requestParams.acceptance);
|
|
4714
4754
|
if (acceptanceErrors.length > 0)
|
|
4715
4755
|
return buildRequestedModeError(requestParams, acceptanceErrors.join(" "));
|
|
4756
|
+
// Capture mandatory host extensions at admission: script children may launch after the host disposes its registration.
|
|
4757
|
+
const admittedRequiredExtensions = retainedRequiredExtensions ?? deps.childRuntime?.requiredExtensions ?? resolveRequiredChildExtensions(ctx.sessionManager.getSessionId() ?? undefined);
|
|
4758
|
+
const workflowRequiredExtensions = hasMandatoryRequiredChildExtensions(admittedRequiredExtensions) ? admittedRequiredExtensions : undefined;
|
|
4716
4759
|
const foregroundWorkflowRunId = encodeIndexSegment(_id);
|
|
4717
4760
|
if (delegatedWorkflowPermit) {
|
|
4718
4761
|
const permitError = validateWorkflowChildPermitRoot(delegatedWorkflowPermit, foregroundWorkflowRunId);
|
|
@@ -5588,6 +5631,8 @@ export function createSubagentExecutor(deps) {
|
|
|
5588
5631
|
preparedChildParams = childRequest;
|
|
5589
5632
|
if (workflowUsageBudget.budget)
|
|
5590
5633
|
workflowOwnedUsageBudgets.set(childRequest, workflowUsageBudget.budget);
|
|
5634
|
+
if (workflowRequiredExtensions)
|
|
5635
|
+
workflowRetainedRequiredExtensions.set(childRequest, workflowRequiredExtensions);
|
|
5591
5636
|
workflowLaunchObservers.set(childRequest, (launch) => {
|
|
5592
5637
|
if (launch.runId)
|
|
5593
5638
|
appendWorkflowChildJournal(asyncDir, { type: "start", key, fingerprint: journalFingerprint, runId: launch.runId });
|
|
@@ -5910,6 +5955,8 @@ export function createSubagentExecutor(deps) {
|
|
|
5910
5955
|
preparedChildParams = childRequest;
|
|
5911
5956
|
if (workflowUsageBudget.budget)
|
|
5912
5957
|
workflowOwnedUsageBudgets.set(childRequest, workflowUsageBudget.budget);
|
|
5958
|
+
if (workflowRequiredExtensions)
|
|
5959
|
+
workflowRetainedRequiredExtensions.set(childRequest, workflowRequiredExtensions);
|
|
5913
5960
|
if (delegatedWorkflowPermit) {
|
|
5914
5961
|
if (childRequest.async !== false)
|
|
5915
5962
|
throw new Error("Workflow child permit supports one foreground child only.");
|
|
@@ -6089,11 +6136,35 @@ export function createSubagentExecutor(deps) {
|
|
|
6089
6136
|
if (deps.allowMutatingManagementActions === false) {
|
|
6090
6137
|
return { content: [{ type: "text", text: "Action 'worktree.cleanup' is not available from child-safe subagent fanout mode." }], isError: true, details: { mode: "management", results: [] } };
|
|
6091
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
|
+
}
|
|
6092
6163
|
if (paramsWithResolvedCwd.mode !== "plan") {
|
|
6093
|
-
return { content: [{ type: "text", text: "worktree.cleanup
|
|
6164
|
+
return { content: [{ type: "text", text: "worktree.cleanup requires mode='plan' or mode='apply'." }], isError: true, details: { mode: "management", results: [] } };
|
|
6094
6165
|
}
|
|
6095
6166
|
if (paramsWithResolvedCwd.planId !== undefined) {
|
|
6096
|
-
return { content: [{ type: "text", text: "worktree.cleanup plan mode does not accept planId
|
|
6167
|
+
return { content: [{ type: "text", text: "worktree.cleanup plan mode does not accept planId." }], isError: true, details: { mode: "management", results: [] } };
|
|
6097
6168
|
}
|
|
6098
6169
|
try {
|
|
6099
6170
|
const created = createWorktreeCleanupPlan({
|
|
@@ -6178,7 +6249,7 @@ export function createSubagentExecutor(deps) {
|
|
|
6178
6249
|
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "management", results: [] } };
|
|
6179
6250
|
}
|
|
6180
6251
|
}
|
|
6181
|
-
const policyAction = action === "stop" ? "stopRun" : action === "steer" ? "steerRun" : action === "schedule.create" ? "scheduleCreate" : action === "inspector.open" ? "inspectorOpen" : action === "project.open" ? "projectOpen" : undefined;
|
|
6252
|
+
const policyAction = action === "stop" || action === "command.cancel" ? "stopRun" : action === "steer" || action === "command.yield" ? "steerRun" : action === "schedule.create" ? "scheduleCreate" : action === "inspector.open" ? "inspectorOpen" : action === "project.open" ? "projectOpen" : undefined;
|
|
6182
6253
|
if (policyAction) {
|
|
6183
6254
|
// Child-safe mode is a hard capability boundary; the policy is an operator
|
|
6184
6255
|
// preference. Refuse first, so the gate never prompts for an action that is
|
|
@@ -6402,6 +6473,23 @@ export function createSubagentExecutor(deps) {
|
|
|
6402
6473
|
details: { mode: "management", results: [], spawnBudget, activeAsyncCapacity },
|
|
6403
6474
|
};
|
|
6404
6475
|
}
|
|
6476
|
+
if (["command.status", "command.yield", "command.cancel"].includes(action)) {
|
|
6477
|
+
try {
|
|
6478
|
+
if (deps.allowMutatingManagementActions === false && action !== "command.status")
|
|
6479
|
+
throw new Error(`Action '${action}' is not available from child-safe subagent fanout mode.`);
|
|
6480
|
+
const targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
|
|
6481
|
+
if (!targetRunId || paramsWithResolvedCwd.dir)
|
|
6482
|
+
throw new Error(`${action} requires id or runId; directory targets are not supported.`);
|
|
6483
|
+
deps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
|
|
6484
|
+
const target = resolveSubagentRunId(targetRunId, { state: deps.state, nested: nestedResolutionScopeForExecutor(deps) });
|
|
6485
|
+
if (!target)
|
|
6486
|
+
throw new Error(`No run found for '${targetRunId}'.`);
|
|
6487
|
+
return await commandAction({ state: deps.state, target, operation: action.slice("command.".length), index: paramsWithResolvedCwd.index, toolCallId: paramsWithResolvedCwd.toolCallId, signal });
|
|
6488
|
+
}
|
|
6489
|
+
catch (error) {
|
|
6490
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "management", results: [] } };
|
|
6491
|
+
}
|
|
6492
|
+
}
|
|
6405
6493
|
if (action === "status" || action === "debug.run") {
|
|
6406
6494
|
if (!preserveActiveSession)
|
|
6407
6495
|
deps.state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
|
|
@@ -7088,6 +7176,7 @@ export function createSubagentExecutor(deps) {
|
|
|
7088
7176
|
toolBudget: runToolBudget.toolBudget,
|
|
7089
7177
|
usageBudget: usageBudget.budget,
|
|
7090
7178
|
inheritedUsageBudget,
|
|
7179
|
+
requiredExtensions: retainedRequiredExtensions,
|
|
7091
7180
|
allowZeroToolBudget,
|
|
7092
7181
|
configToolBudget: configToolBudget.toolBudget,
|
|
7093
7182
|
configToolTimeoutMs: deps.config.toolTimeoutMs,
|
|
@@ -7373,7 +7462,9 @@ export function createSubagentExecutor(deps) {
|
|
|
7373
7462
|
}
|
|
7374
7463
|
else if (workflow !== undefined || publicParams.workflowScript !== undefined) {
|
|
7375
7464
|
const normalizedArgs = normalizeWorkflowArgs(publicParams.args);
|
|
7376
|
-
|
|
7465
|
+
// validate reports args errors with its script errors; launch rejects them here.
|
|
7466
|
+
const validateOnly = publicParams.action === "validate";
|
|
7467
|
+
if ("error" in normalizedArgs && !validateOnly)
|
|
7377
7468
|
return errorResult(normalizedArgs.error);
|
|
7378
7469
|
let workflowScript = publicParams.workflowScript;
|
|
7379
7470
|
if (workflow !== undefined) {
|
|
@@ -7383,7 +7474,7 @@ export function createSubagentExecutor(deps) {
|
|
|
7383
7474
|
workflowScript = source.script;
|
|
7384
7475
|
}
|
|
7385
7476
|
const { workflow: _workflow, ...withoutWorkflowSource } = publicParams;
|
|
7386
|
-
publicParams = { ...withoutWorkflowSource, workflowScript, args: deepFreezeWorkflowArgs(normalizedArgs.args) };
|
|
7477
|
+
publicParams = { ...withoutWorkflowSource, workflowScript, args: "error" in normalizedArgs ? publicParams.args : deepFreezeWorkflowArgs(normalizedArgs.args) };
|
|
7387
7478
|
}
|
|
7388
7479
|
publicExecutions.add(publicParams);
|
|
7389
7480
|
return executeWithSingleDispatchGuard(id, publicParams, signal, onUpdate, ctx);
|