pi-subagents 0.57.0 → 0.59.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 +104 -0
- package/docs/agents.md +18 -9
- package/docs/configuration.md +4 -4
- package/docs/extension-api.md +40 -1
- package/docs/models.md +27 -4
- package/docs/observability.md +1 -1
- package/docs/tool-reference.md +92 -6
- package/docs/workflows.md +115 -0
- package/package.json +3 -1
- package/prompts/review-loop.md +2 -2
- package/skills/council-mode/SKILL.md +1 -1
- package/skills/pi-subagents/SKILL.md +3 -1
- package/skills/pi-subagents/references/execution-controls.md +6 -2
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/src/agents/agent-management.ts +28 -17
- package/src/agents/agent-serializer.ts +9 -2
- package/src/agents/agents.ts +103 -27
- package/src/agents/runtime-agent-events.ts +70 -0
- package/src/agents/runtime-agent-registry.ts +19 -18
- package/src/api/agents.ts +10 -5
- package/src/api/background-work.ts +5 -1
- package/src/api/delegation.ts +0 -7
- package/src/api/preflight.ts +32 -10
- package/src/extension/fanout-child.ts +5 -3
- package/src/extension/index.ts +66 -27
- package/src/extension/public-execution.ts +15 -2
- package/src/extension/rpc.ts +35 -14
- package/src/extension/schemas.ts +37 -12
- package/src/extension/tool-description.ts +25 -6
- package/src/integrations/herdr-status.ts +5 -0
- package/src/intercom/result-intercom.ts +2 -0
- package/src/profiles/profiles.ts +5 -6
- package/src/runs/background/active-async-capacity.ts +2 -2
- package/src/runs/background/async-execution.ts +78 -46
- package/src/runs/background/async-job-tracker.ts +14 -12
- package/src/runs/background/async-resume.ts +29 -27
- package/src/runs/background/async-status-snapshot.ts +23 -261
- package/src/runs/background/async-status.ts +68 -7
- package/src/runs/background/chain-append.ts +8 -3
- package/src/runs/background/chain-root-attachment.ts +60 -8
- package/src/runs/background/fleet-view.ts +21 -11
- package/src/runs/background/notify.ts +184 -9
- package/src/runs/background/result-delivery-ownership.ts +45 -0
- package/src/runs/background/result-files.ts +2 -1
- package/src/runs/background/result-watcher.ts +29 -10
- package/src/runs/background/resume-guidance.ts +1 -1
- package/src/runs/background/retained-children.ts +1 -1
- package/src/runs/background/run-status.ts +18 -8
- package/src/runs/background/scheduled-runs.ts +86 -7
- package/src/runs/background/stale-run-reconciler.ts +10 -4
- package/src/runs/background/steering.ts +4 -14
- package/src/runs/background/subagent-runner.ts +389 -350
- package/src/runs/background/subagent-wait.ts +58 -10
- package/src/runs/background/terminal-run-index.ts +1 -1
- package/src/runs/background/wait-completions.ts +22 -1
- package/src/runs/background/wait-config.ts +23 -9
- package/src/runs/background/wait-tool.ts +9 -2
- package/src/runs/foreground/async-steering-action.ts +2 -2
- package/src/runs/foreground/execution.ts +134 -121
- package/src/runs/foreground/foreground-control.ts +3 -0
- package/src/runs/foreground/foreground-history.ts +1 -0
- package/src/runs/foreground/subagent-executor.ts +527 -257
- package/src/runs/foreground/workflow-detach-reconcile.ts +130 -120
- package/src/runs/shared/abort-recovery.ts +119 -0
- package/src/runs/shared/async-status-projection.ts +463 -0
- package/src/runs/shared/child-identity.ts +19 -4
- package/src/runs/shared/child-launch-plan.ts +151 -0
- package/src/runs/shared/completion-evidence.ts +89 -0
- package/src/runs/shared/completion-guard.ts +5 -4
- package/src/runs/shared/dynamic-fanout.ts +3 -3
- package/src/runs/shared/fast-mode-extension.ts +5 -5
- package/src/runs/shared/host-step-status.ts +230 -0
- package/src/runs/shared/lane-metadata.ts +105 -0
- package/src/runs/shared/launch-cwd.ts +16 -0
- package/src/runs/shared/long-running-guard.ts +2 -1
- package/src/runs/shared/mcp-config-sources.ts +422 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/src/runs/shared/model-exclusions.ts +12 -0
- package/src/runs/shared/model-fallback.ts +25 -6
- package/src/runs/shared/nested-events.ts +6 -2
- package/src/runs/shared/nested-render.ts +7 -3
- package/src/runs/shared/parallel-handoff.ts +419 -7
- package/src/runs/shared/parallel-utils.ts +15 -1
- package/src/runs/shared/pi-args.ts +81 -8
- package/src/runs/shared/single-output.ts +44 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/src/runs/shared/worktree.ts +18 -0
- package/src/shared/child-session-name.ts +46 -0
- package/src/shared/extension-context.ts +24 -0
- package/src/shared/formatters.ts +11 -2
- package/src/shared/launch-contract.ts +5 -1
- package/src/shared/settings.ts +9 -103
- package/src/shared/types.ts +240 -30
- package/src/shared/utils.ts +41 -84
- package/src/slash/delegation-adapters.ts +1 -8
- package/src/slash/delegation-request.ts +0 -4
- package/src/slash/slash-bridge.ts +1 -2
- package/src/slash/slash-commands.ts +369 -90
- package/src/slash/slash-live-state.ts +22 -11
- package/src/slash/subagents-admin.ts +3 -0
- package/src/tui/fleet-status.ts +125 -74
- package/src/tui/fleet.ts +11 -5
- package/src/tui/render.ts +330 -33
- package/src/watchdog/turn-delta.ts +1 -1
- package/src/workflows/chat-progress.ts +6 -3
- package/src/workflows/host-command.ts +230 -0
- package/src/workflows/scripted-workflow.ts +496 -35
- package/src/workflows/workflow-child-summary.ts +9 -5
- package/src/workflows/workflow-preflight.ts +270 -0
- package/src/workflows/workflow-receipt.ts +79 -5
- package/src/workflows/workflow-settlement.ts +246 -0
- package/src/runs/shared/turn-budget.ts +0 -98
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
|
-
import * as os from "node:os";
|
|
9
8
|
import * as path from "node:path";
|
|
10
9
|
import { fileURLToPath } from "node:url";
|
|
11
10
|
import { createRequire } from "node:module";
|
|
@@ -14,20 +13,22 @@ import { discoverAgents, formatUnknownAgentError, unknownAgentDiagnosticContext,
|
|
|
14
13
|
import { appendAgentRefinementOverlay } from "../../agents/agent-refinements.ts";
|
|
15
14
|
import { writePrivateAtomicJson } from "../../shared/atomic-json.ts";
|
|
16
15
|
import { currentCompletionOwnerId } from "../../shared/completion-owner.ts";
|
|
16
|
+
import { planChildLaunch, resolveStepBehavior, suppressProgressForReadOnlyTask, type ResolvedStepBehavior } from "../shared/child-launch-plan.ts";
|
|
17
17
|
import { applyThinkingSuffix, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
18
18
|
import { injectOutputPathSystemPrompt, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
|
|
19
|
-
import { buildChainInstructions, isDynamicParallelStep, isParallelStep,
|
|
19
|
+
import { buildChainInstructions, isDynamicParallelStep, isParallelStep, resolveExistingReadPaths, writeInitialProgressFile, type ChainStep, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
|
|
20
20
|
import type { RunnerStep } from "../shared/parallel-utils.ts";
|
|
21
21
|
import type { ContextMode } from "../shared/context-mode.ts";
|
|
22
22
|
import { resolvePiPackageRoot } from "../shared/pi-spawn.ts";
|
|
23
|
+
import { preflightLaunchCwd } from "../shared/launch-cwd.ts";
|
|
23
24
|
import { resolveNodeExecutable } from "../../shared/node-executable.ts";
|
|
24
25
|
import { buildSkillInjection, normalizeSkillInput, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
25
26
|
import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
|
|
26
27
|
import { PI_CODING_AGENT_PACKAGE_ROOT_ENV, PROMPT_REDACTED, resolveChildCwd } from "../../shared/utils.ts";
|
|
27
|
-
import { buildModelCandidates, inheritsParentModel, resolveEffectiveSubagentModel,
|
|
28
|
+
import { buildModelCandidates, inheritsParentModel, resolveEffectiveSubagentModel, resolveSubagentModelOverride, type AvailableModelInfo, type ParentModel } from "../shared/model-fallback.ts";
|
|
28
29
|
import { resolveToolTimeoutMs, toolTimeoutFromEnv } from "../shared/tool-timeout.ts";
|
|
29
30
|
import { resolveModelScopesForAgent, type ModelScopeConfig } from "../shared/model-scope.ts";
|
|
30
|
-
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
31
|
+
import { findModelInfo, resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
31
32
|
import { assertThinkingWithinCeiling, decodeThinkingCeiling, intersectThinkingCeilings, SUBAGENT_THINKING_CEILING_ENV, type ThinkingLevel } from "../../shared/thinking-ceiling.ts";
|
|
32
33
|
import { resolveExpectedWorktreeAgentCwd } from "../shared/worktree.ts";
|
|
33
34
|
import { buildWorkflowGraphSnapshot } from "../shared/workflow-graph.ts";
|
|
@@ -48,12 +49,12 @@ import {
|
|
|
48
49
|
type MaxOutputConfig,
|
|
49
50
|
type NestedRouteInfo,
|
|
50
51
|
type ResolvedControlConfig,
|
|
51
|
-
type ResolvedTurnBudget,
|
|
52
52
|
type ResolvedToolBudget,
|
|
53
53
|
type RunFanoutBudgetDescriptor,
|
|
54
54
|
type ToolBudgetConfig,
|
|
55
55
|
type SubagentRunMode,
|
|
56
56
|
type SteeringRecoveryDescriptor,
|
|
57
|
+
type WorkflowLaneMetadata,
|
|
57
58
|
type UsageBudgetConfig,
|
|
58
59
|
DIRS,
|
|
59
60
|
SUBAGENT_ASYNC_STARTED_EVENT,
|
|
@@ -64,7 +65,6 @@ import {
|
|
|
64
65
|
} from "../../shared/types.ts";
|
|
65
66
|
import { nestedResultsPath, nestedSummaryFromAsyncStatus, resolveInheritedNestedRouteFromEnv, resolveNestedParentAddressFromEnv, writeNestedEvent } from "../shared/nested-events.ts";
|
|
66
67
|
import { resultFilePath } from "./result-files.ts";
|
|
67
|
-
import { appendTurnBudgetSystemPrompt, initialTurnBudgetState } from "../shared/turn-budget.ts";
|
|
68
68
|
import { validateToolBudgetConfig } from "../shared/tool-budget.ts";
|
|
69
69
|
import { usageBudgetState } from "../shared/usage-budget.ts";
|
|
70
70
|
import type { ImportedAsyncRoot } from "./chain-root-attachment.ts";
|
|
@@ -77,6 +77,7 @@ import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling,
|
|
|
77
77
|
import { agentDefinitionDigest, launchBindingDigest } from "../../shared/launch-contract.ts";
|
|
78
78
|
import { resolvePermissionRules, type PermissionConfig } from "../shared/permissions.ts";
|
|
79
79
|
import { normalizeExtensionBindings, omitExtensionBindingsEnv, type ExtensionBindings } from "../shared/extension-bindings.ts";
|
|
80
|
+
import { assertWorkflowLaneKey, normalizeWorkflowLaneMetadata } from "../shared/lane-metadata.ts";
|
|
80
81
|
|
|
81
82
|
const require = createRequire(import.meta.url);
|
|
82
83
|
const piPackageRoot = resolvePiPackageRoot();
|
|
@@ -172,6 +173,7 @@ interface AsyncChainParams {
|
|
|
172
173
|
dynamicFanoutMaxItems?: number;
|
|
173
174
|
maxSubagentDepth: number;
|
|
174
175
|
waitToolEnabled?: boolean;
|
|
176
|
+
waitToolDefaultTimeoutMs?: number;
|
|
175
177
|
worktreeSetupHook?: string;
|
|
176
178
|
worktreeSetupHookTimeoutMs?: number;
|
|
177
179
|
worktreeBaseDir?: string;
|
|
@@ -182,7 +184,6 @@ interface AsyncChainParams {
|
|
|
182
184
|
acceptance?: AcceptanceInput;
|
|
183
185
|
fast?: boolean;
|
|
184
186
|
timeoutMs?: number;
|
|
185
|
-
turnBudget?: ResolvedTurnBudget;
|
|
186
187
|
toolBudget?: ResolvedToolBudget;
|
|
187
188
|
usageBudget?: UsageBudgetConfig;
|
|
188
189
|
configToolBudget?: ResolvedToolBudget;
|
|
@@ -199,6 +200,7 @@ interface AsyncChainParams {
|
|
|
199
200
|
runFanoutBudget?: RunFanoutBudgetDescriptor;
|
|
200
201
|
parentWorkflowRunId?: string;
|
|
201
202
|
workflowKey?: string;
|
|
203
|
+
lane?: WorkflowLaneMetadata;
|
|
202
204
|
activeAsyncCapacity?: ActiveAsyncCapacityHandle;
|
|
203
205
|
}
|
|
204
206
|
|
|
@@ -212,6 +214,7 @@ interface AsyncSingleParams {
|
|
|
212
214
|
recoveryAgentConfig?: AgentConfig;
|
|
213
215
|
ctx: AsyncExecutionContext;
|
|
214
216
|
cwd?: string;
|
|
217
|
+
requestedCwd?: string;
|
|
215
218
|
maxOutput?: MaxOutputConfig;
|
|
216
219
|
artifactsDir?: string;
|
|
217
220
|
artifactConfig: ArtifactConfig;
|
|
@@ -226,6 +229,7 @@ interface AsyncSingleParams {
|
|
|
226
229
|
reads?: string[] | false;
|
|
227
230
|
outputMode?: "inline" | "file-only";
|
|
228
231
|
outputBaseDir?: string;
|
|
232
|
+
outputClaimPath?: string;
|
|
229
233
|
agentContract?: AgentContract;
|
|
230
234
|
structuredOutputSchema?: JsonSchemaObject;
|
|
231
235
|
modelOverride?: string;
|
|
@@ -235,6 +239,7 @@ interface AsyncSingleParams {
|
|
|
235
239
|
availableModels?: AvailableModelInfo[];
|
|
236
240
|
maxSubagentDepth: number;
|
|
237
241
|
waitToolEnabled?: boolean;
|
|
242
|
+
waitToolDefaultTimeoutMs?: number;
|
|
238
243
|
worktreeSetupHook?: string;
|
|
239
244
|
worktreeSetupHookTimeoutMs?: number;
|
|
240
245
|
worktreeBaseDir?: string;
|
|
@@ -249,7 +254,6 @@ interface AsyncSingleParams {
|
|
|
249
254
|
absoluteDeadlineAt?: number;
|
|
250
255
|
/** Optional per-call hard toolTimeoutMs override (highest precedence). */
|
|
251
256
|
toolTimeoutMs?: number;
|
|
252
|
-
turnBudget?: { maxTurns: number; graceTurns?: number };
|
|
253
257
|
toolBudget?: ResolvedToolBudget | ToolBudgetConfig;
|
|
254
258
|
usageBudget?: UsageBudgetConfig;
|
|
255
259
|
configToolBudget?: ResolvedToolBudget;
|
|
@@ -263,6 +267,7 @@ interface AsyncSingleParams {
|
|
|
263
267
|
runFanoutBudget?: RunFanoutBudgetDescriptor;
|
|
264
268
|
parentWorkflowRunId?: string;
|
|
265
269
|
workflowKey?: string;
|
|
270
|
+
lane?: WorkflowLaneMetadata;
|
|
266
271
|
workflowAwaitAsync?: boolean;
|
|
267
272
|
activeAsyncCapacity?: ActiveAsyncCapacityHandle;
|
|
268
273
|
externalJobFollowUp?: {
|
|
@@ -301,6 +306,7 @@ export interface AsyncRunnerStepBuildParams {
|
|
|
301
306
|
dynamicFanoutMaxItems?: number;
|
|
302
307
|
maxSubagentDepth: number;
|
|
303
308
|
waitToolEnabled?: boolean;
|
|
309
|
+
waitToolDefaultTimeoutMs?: number;
|
|
304
310
|
worktreeBaseDir?: string;
|
|
305
311
|
asyncDir: string;
|
|
306
312
|
outputBaseDir?: string;
|
|
@@ -512,20 +518,14 @@ export function emitProcessTerminalEvent(ctx: AsyncExecutionContext, proof: unkn
|
|
|
512
518
|
}
|
|
513
519
|
}
|
|
514
520
|
|
|
515
|
-
function spawnRunner(cfg: object, suffix: string, cwd: string, initialStatus: Omit<AsyncStatus, "pid" | "processTerminal">, initialStatusPath: string, onProcessTerminal?: (proof: unknown) => void): SpawnRunnerResult {
|
|
521
|
+
function spawnRunner(cfg: object, suffix: string, cwd: string, initialStatus: Omit<AsyncStatus, "pid" | "processTerminal">, initialStatusPath: string, onProcessTerminal?: (proof: unknown) => void, requestedCwd = cwd): SpawnRunnerResult {
|
|
522
|
+
const cwdError = preflightLaunchCwd(requestedCwd, cwd);
|
|
523
|
+
if (cwdError) return { error: cwdError };
|
|
524
|
+
|
|
516
525
|
if (!jitiCliPath) {
|
|
517
526
|
return { error: "upstream jiti for TypeScript execution could not be found; ensure package dependencies are installed" };
|
|
518
527
|
}
|
|
519
528
|
|
|
520
|
-
try {
|
|
521
|
-
const cwdStats = fs.statSync(cwd);
|
|
522
|
-
if (!cwdStats.isDirectory()) {
|
|
523
|
-
return { error: `cwd is not a directory: ${cwd}` };
|
|
524
|
-
}
|
|
525
|
-
} catch {
|
|
526
|
-
return { error: `cwd does not exist: ${cwd}` };
|
|
527
|
-
}
|
|
528
|
-
|
|
529
529
|
fs.mkdirSync(TEMP_ROOT_DIR, { recursive: true });
|
|
530
530
|
const cfgPath = getAsyncConfigPath(suffix);
|
|
531
531
|
const runnerProcessInstanceId = randomUUID();
|
|
@@ -808,19 +808,21 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
808
808
|
envValue: params.toolTimeoutMsEnv ?? toolTimeoutFromEnv(),
|
|
809
809
|
});
|
|
810
810
|
if (resolvedToolTimeout.error) throw new AsyncStartValidationError(resolvedToolTimeout.error);
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
811
|
+
const launchPlan = planChildLaunch({
|
|
812
|
+
agentConfig: a,
|
|
813
|
+
stepOverrides: buildStepOverrides(s),
|
|
814
|
+
task: s.task,
|
|
815
|
+
originalTask,
|
|
816
|
+
runnerCwd,
|
|
817
|
+
runtimeCwd: ctx.cwd,
|
|
818
|
+
stepCwdInput: s.cwd,
|
|
819
|
+
behaviorCwd,
|
|
820
|
+
chainSkills,
|
|
821
|
+
outputBaseDir,
|
|
822
|
+
parallelOutputNamespace,
|
|
823
|
+
resolvedBehavior,
|
|
824
|
+
});
|
|
825
|
+
const { stepCwd, instructionCwd, readExistenceCwd, behavior, namespaceOutputPath, outputPath, skillNames } = launchPlan;
|
|
824
826
|
const { resolved: resolvedSkills, missing: missingSkills } = resolveSkillsWithFallback(
|
|
825
827
|
skillNames,
|
|
826
828
|
stepCwd,
|
|
@@ -845,7 +847,6 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
845
847
|
const isFirstProgressAgent = behavior.progress && !progressPrecreated && !progressInstructionCreated;
|
|
846
848
|
if (behavior.progress) progressInstructionCreated = true;
|
|
847
849
|
const progressInstructions = buildChainInstructions({ ...behavior, output: false, reads: false }, progressDir, isFirstProgressAgent);
|
|
848
|
-
const outputPath = resolveSingleOutputPath(behavior.output, ctx.cwd, instructionCwd, outputBaseDir);
|
|
849
850
|
if (!namespaceOutputPath) systemPrompt = injectOutputPathSystemPrompt(systemPrompt, outputPath, a);
|
|
850
851
|
const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Async step (${s.agent})`);
|
|
851
852
|
if (validationError) throw new AsyncStartValidationError(validationError);
|
|
@@ -868,6 +869,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
868
869
|
const thinkingOverride = flatIndex === undefined ? undefined : thinkingOverridesByFlatIndex?.[flatIndex];
|
|
869
870
|
const effectiveThinking = externalRunner ? undefined : thinkingOverride ?? a.thinking;
|
|
870
871
|
const model = externalRunner ? undefined : applyThinkingSuffix(primaryModel, effectiveThinking, thinkingOverride !== undefined);
|
|
872
|
+
const contextLimit = model ? findModelInfo(model, availableModels, a.modelProvider ?? ctx.currentModelProvider)?.contextWindow : undefined;
|
|
871
873
|
const thinkingCeiling = externalRunner ? undefined : intersectThinkingCeilings(
|
|
872
874
|
params.thinkingCeiling,
|
|
873
875
|
a.maxThinking,
|
|
@@ -899,6 +901,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
899
901
|
const fast = s.fast ?? params.fast ?? a.fast;
|
|
900
902
|
const toolPlan = resolvePiLaunchToolPlan({
|
|
901
903
|
tools: a.tools,
|
|
904
|
+
allowNestedSubagents: a.allowNestedSubagents,
|
|
902
905
|
extensions: a.extensions,
|
|
903
906
|
subagentOnlyExtensions: a.subagentOnlyExtensions,
|
|
904
907
|
mcpDirectTools: a.mcpDirectTools,
|
|
@@ -912,6 +915,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
912
915
|
inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
|
|
913
916
|
agentName: a.name,
|
|
914
917
|
permissionRules,
|
|
918
|
+
runtimeSnapshotHost: ctx.pi,
|
|
915
919
|
});
|
|
916
920
|
const launchResolvedExtensions = externalRunner ? undefined : projectLaunchResolvedChildExtensions(toolPlan);
|
|
917
921
|
if (externalRunner && permissionRules) {
|
|
@@ -946,22 +950,29 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
946
950
|
outputName: s.as,
|
|
947
951
|
structured: Boolean(s.outputSchema),
|
|
948
952
|
cwd: stepCwd,
|
|
953
|
+
requestedCwd: s.cwd ?? stepCwd,
|
|
949
954
|
model,
|
|
955
|
+
...(contextLimit !== undefined ? { contextLimit } : {}),
|
|
950
956
|
...(fast !== undefined ? { fast } : {}),
|
|
951
957
|
thinking: resolveEffectiveThinking(model, effectiveThinking),
|
|
952
958
|
...(thinkingCeiling ? { thinkingCeiling } : {}),
|
|
953
959
|
launchResolvedExtensions,
|
|
960
|
+
...(toolPlan.mcpConfig ? { mcpConfig: toolPlan.mcpConfig } : {}),
|
|
961
|
+
...(toolPlan.runtimeServerNames ? { runtimeServerNames: toolPlan.runtimeServerNames } : {}),
|
|
954
962
|
modelCandidates: externalRunner ? undefined : modelCandidates,
|
|
955
963
|
...(primaryModelFromParent ? { skipPrimaryModelVerification: true } : {}),
|
|
956
964
|
...(availableModels && availableModels.length > 0 ? { modelVerificationRegistry: availableModels } : {}),
|
|
957
965
|
tools: a.tools,
|
|
966
|
+
allowNestedSubagents: a.allowNestedSubagents,
|
|
958
967
|
extensions: a.extensions,
|
|
959
968
|
subagentOnlyExtensions: a.subagentOnlyExtensions,
|
|
960
969
|
mcpDirectTools: a.mcpDirectTools,
|
|
970
|
+
mutationTools: a.mutationTools,
|
|
961
971
|
completionGuard: a.completionGuard,
|
|
962
972
|
systemPrompt,
|
|
963
973
|
systemPromptMode: a.systemPromptMode,
|
|
964
974
|
inheritProjectContext: a.inheritProjectContext,
|
|
975
|
+
inheritGlobalContext: a.inheritGlobalContext,
|
|
965
976
|
inheritSkills: a.inheritSkills,
|
|
966
977
|
skills: resolvedSkills.map((r) => r.name),
|
|
967
978
|
outputPath,
|
|
@@ -972,6 +983,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
972
983
|
timeoutMs: a.defaultTimeoutMs ?? DEFAULT_ASYNC_TIMEOUT_MS,
|
|
973
984
|
toolTimeoutMs: resolvedToolTimeout.toolTimeoutMs,
|
|
974
985
|
waitToolEnabled: params.waitToolEnabled,
|
|
986
|
+
waitToolDefaultTimeoutMs: params.waitToolDefaultTimeoutMs,
|
|
975
987
|
effectiveAcceptance: resolveEffectiveAcceptance({
|
|
976
988
|
explicit: s.acceptance,
|
|
977
989
|
agentName: s.agent,
|
|
@@ -1098,6 +1110,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
|
|
|
1098
1110
|
index: params.attachRoot.index,
|
|
1099
1111
|
},
|
|
1100
1112
|
inheritProjectContext: false,
|
|
1113
|
+
inheritGlobalContext: false,
|
|
1101
1114
|
inheritSkills: false,
|
|
1102
1115
|
}, ...builtSteps]
|
|
1103
1116
|
: builtSteps;
|
|
@@ -1198,6 +1211,7 @@ export function executeAsyncChain(
|
|
|
1198
1211
|
dynamicFanoutMaxItems: params.dynamicFanoutMaxItems,
|
|
1199
1212
|
maxSubagentDepth,
|
|
1200
1213
|
waitToolEnabled: params.waitToolEnabled,
|
|
1214
|
+
waitToolDefaultTimeoutMs: params.waitToolDefaultTimeoutMs,
|
|
1201
1215
|
worktreeBaseDir,
|
|
1202
1216
|
asyncDir,
|
|
1203
1217
|
fast: params.fast,
|
|
@@ -1219,7 +1233,6 @@ export function executeAsyncChain(
|
|
|
1219
1233
|
}
|
|
1220
1234
|
const { steps, runnerCwd, workflowGraph, eventChain } = built;
|
|
1221
1235
|
const deadlineAt = params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined;
|
|
1222
|
-
const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
|
|
1223
1236
|
const initialUsageBudget = usageBudgetState(params.usageBudget, undefined);
|
|
1224
1237
|
let childTargetIndex = 0;
|
|
1225
1238
|
const childIntercomTargets = childIntercomTarget ? steps.flatMap((step) => {
|
|
@@ -1276,7 +1289,6 @@ export function executeAsyncChain(
|
|
|
1276
1289
|
worktreeSetupHookTimeoutMs,
|
|
1277
1290
|
worktreeBaseDir,
|
|
1278
1291
|
controlConfig,
|
|
1279
|
-
turnBudget: params.turnBudget,
|
|
1280
1292
|
toolBudget: params.toolBudget,
|
|
1281
1293
|
usageBudget: params.usageBudget,
|
|
1282
1294
|
controlIntercomTarget,
|
|
@@ -1395,7 +1407,6 @@ export function executeAsyncChain(
|
|
|
1395
1407
|
chainStepCount: eventChain.length,
|
|
1396
1408
|
parallelGroups,
|
|
1397
1409
|
...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}),
|
|
1398
|
-
...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
|
|
1399
1410
|
startedAt: now,
|
|
1400
1411
|
lastUpdate: now,
|
|
1401
1412
|
...(capabilityCeiling ? { capabilityCeiling } : {}),
|
|
@@ -1426,7 +1437,6 @@ export function executeAsyncChain(
|
|
|
1426
1437
|
asyncDir,
|
|
1427
1438
|
...(sessionRoot ? { sessionRoot } : {}),
|
|
1428
1439
|
...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}),
|
|
1429
|
-
...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
|
|
1430
1440
|
...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}),
|
|
1431
1441
|
...(capabilityCeiling ? { capabilityCeiling } : {}),
|
|
1432
1442
|
...(params.parentWorkflowRunId ? { parentWorkflowRunId: params.parentWorkflowRunId } : {}),
|
|
@@ -1443,7 +1453,7 @@ export function executeAsyncChain(
|
|
|
1443
1453
|
|
|
1444
1454
|
return {
|
|
1445
1455
|
content: [{ type: "text", text: formatAsyncStartedMessage(`Async ${resultMode}: ${chainDesc} [${id}]`, ctx.interactive === true) }],
|
|
1446
|
-
details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.parentWorkflowRunId ? { parentWorkflowRunId: params.parentWorkflowRunId } : {}), ...(params.workflowKey ? { workflowKey: params.workflowKey } : {}), ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}), ...(params.
|
|
1456
|
+
details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.parentWorkflowRunId ? { parentWorkflowRunId: params.parentWorkflowRunId } : {}), ...(params.workflowKey ? { workflowKey: params.workflowKey } : {}), ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}), ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}) },
|
|
1447
1457
|
};
|
|
1448
1458
|
}
|
|
1449
1459
|
|
|
@@ -1478,6 +1488,13 @@ export function executeAsyncSingle(
|
|
|
1478
1488
|
childIntercomTarget,
|
|
1479
1489
|
nestedRoute,
|
|
1480
1490
|
} = params;
|
|
1491
|
+
let lane: WorkflowLaneMetadata | undefined;
|
|
1492
|
+
try {
|
|
1493
|
+
lane = normalizeWorkflowLaneMetadata(params.lane, "lane");
|
|
1494
|
+
assertWorkflowLaneKey(lane, params.workflowKey, "lane");
|
|
1495
|
+
} catch (error) {
|
|
1496
|
+
return formatAsyncStartError("single", error instanceof Error ? error.message : String(error));
|
|
1497
|
+
}
|
|
1481
1498
|
const task = params.task ?? "";
|
|
1482
1499
|
let extensionBindings: ExtensionBindings | undefined;
|
|
1483
1500
|
try {
|
|
@@ -1582,6 +1599,7 @@ export function executeAsyncSingle(
|
|
|
1582
1599
|
);
|
|
1583
1600
|
const effectiveThinking = externalRunner ? undefined : params.thinkingOverride ?? agentConfig.thinking;
|
|
1584
1601
|
const model = externalRunner ? undefined : applyThinkingSuffix(primaryModel, effectiveThinking, params.thinkingOverride !== undefined);
|
|
1602
|
+
const contextLimit = model ? findModelInfo(model, availableModels, agentConfig.modelProvider ?? ctx.currentModelProvider)?.contextWindow : undefined;
|
|
1585
1603
|
const thinkingCeiling = externalRunner ? undefined : intersectThinkingCeilings(
|
|
1586
1604
|
params.thinkingCeiling,
|
|
1587
1605
|
agentConfig.maxThinking,
|
|
@@ -1610,7 +1628,6 @@ export function executeAsyncSingle(
|
|
|
1610
1628
|
});
|
|
1611
1629
|
if (resolvedToolTimeout.error) return formatAsyncStartError("single", resolvedToolTimeout.error);
|
|
1612
1630
|
const toolTimeoutMs = resolvedToolTimeout.toolTimeoutMs;
|
|
1613
|
-
const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
|
|
1614
1631
|
const initialUsageBudget = usageBudgetState(params.usageBudget, undefined);
|
|
1615
1632
|
const resolvedSessionDir = params.sessionDir ?? (sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined);
|
|
1616
1633
|
const structuredOutput = params.structuredOutputSchema
|
|
@@ -1633,9 +1650,9 @@ export function executeAsyncSingle(
|
|
|
1633
1650
|
return formatAsyncStartError("single", error instanceof Error ? error.message : String(error));
|
|
1634
1651
|
}
|
|
1635
1652
|
}
|
|
1636
|
-
const effectiveSystemPrompt = appendTurnBudgetSystemPrompt(systemPrompt, params.turnBudget);
|
|
1637
1653
|
const toolPlan = resolvePiLaunchToolPlan({
|
|
1638
1654
|
tools: agentConfig.tools,
|
|
1655
|
+
allowNestedSubagents: agentConfig.allowNestedSubagents,
|
|
1639
1656
|
extensions: agentConfig.extensions,
|
|
1640
1657
|
subagentOnlyExtensions: agentConfig.subagentOnlyExtensions,
|
|
1641
1658
|
mcpDirectTools: agentConfig.mcpDirectTools,
|
|
@@ -1649,6 +1666,7 @@ export function executeAsyncSingle(
|
|
|
1649
1666
|
inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
|
|
1650
1667
|
agentName: agentConfig.name,
|
|
1651
1668
|
permissionRules: resolvePermissionRules(ctx.permissions, agentConfig.permissions),
|
|
1669
|
+
runtimeSnapshotHost: ctx.pi,
|
|
1652
1670
|
});
|
|
1653
1671
|
const launchResolvedExtensions = externalRunner ? undefined : projectLaunchResolvedChildExtensions(toolPlan);
|
|
1654
1672
|
if (!externalRunner) {
|
|
@@ -1673,9 +1691,10 @@ export function executeAsyncSingle(
|
|
|
1673
1691
|
...((params.fast ?? agentConfig.fast) !== undefined ? { fast: params.fast ?? agentConfig.fast } : {}),
|
|
1674
1692
|
...(resolveEffectiveThinking(model, effectiveThinking) ? { thinking: resolveEffectiveThinking(model, effectiveThinking) } : {}),
|
|
1675
1693
|
...(thinkingCeiling ? { thinkingCeiling } : {}),
|
|
1676
|
-
systemPrompt
|
|
1694
|
+
systemPrompt,
|
|
1677
1695
|
systemPromptMode: agentConfig.systemPromptMode,
|
|
1678
1696
|
inheritProjectContext: agentConfig.inheritProjectContext,
|
|
1697
|
+
inheritGlobalContext: agentConfig.inheritGlobalContext,
|
|
1679
1698
|
inheritSkills: agentConfig.inheritSkills,
|
|
1680
1699
|
skills: resolvedSkills.map((skill) => skill.name),
|
|
1681
1700
|
tools: toolPlan.effectiveToolAllowlist,
|
|
@@ -1698,6 +1717,7 @@ export function executeAsyncSingle(
|
|
|
1698
1717
|
const recoveryAgentConfig = params.recoveryAgentConfig ?? agentConfig;
|
|
1699
1718
|
const recoveryDescriptor: SteeringRecoveryDescriptor = {
|
|
1700
1719
|
version: 1,
|
|
1720
|
+
...(lane ? { lane } : {}),
|
|
1701
1721
|
launchContractDigest,
|
|
1702
1722
|
...(extensionBindings ? { extensionBindings } : {}),
|
|
1703
1723
|
runFanoutBudget,
|
|
@@ -1715,12 +1735,15 @@ export function executeAsyncSingle(
|
|
|
1715
1735
|
...(effectiveThinking ? { thinking: resolveEffectiveThinking(model, effectiveThinking) } : {}),
|
|
1716
1736
|
...(thinkingCeiling ? { thinkingCeiling } : {}),
|
|
1717
1737
|
...(recoveryAgentConfig.tools ? { tools: [...recoveryAgentConfig.tools] } : {}),
|
|
1738
|
+
...(recoveryAgentConfig.allowNestedSubagents !== undefined ? { allowNestedSubagents: recoveryAgentConfig.allowNestedSubagents } : {}),
|
|
1718
1739
|
...(recoveryAgentConfig.extensions ? { extensions: [...recoveryAgentConfig.extensions] } : {}),
|
|
1719
1740
|
...(recoveryAgentConfig.subagentOnlyExtensions ? { subagentOnlyExtensions: [...recoveryAgentConfig.subagentOnlyExtensions] } : {}),
|
|
1720
1741
|
...(recoveryAgentConfig.mcpDirectTools ? { mcpDirectTools: [...recoveryAgentConfig.mcpDirectTools] } : {}),
|
|
1742
|
+
...(recoveryAgentConfig.mutationTools ? { mutationTools: [...recoveryAgentConfig.mutationTools] } : {}),
|
|
1721
1743
|
...(recoveryAgentConfig.systemPrompt ? { systemPrompt: recoveryAgentConfig.systemPrompt } : {}),
|
|
1722
1744
|
systemPromptMode: recoveryAgentConfig.systemPromptMode,
|
|
1723
1745
|
inheritProjectContext: recoveryAgentConfig.inheritProjectContext,
|
|
1746
|
+
inheritGlobalContext: recoveryAgentConfig.inheritGlobalContext,
|
|
1724
1747
|
inheritSkills: recoveryAgentConfig.inheritSkills,
|
|
1725
1748
|
...(resolvedSkills.length ? { skills: resolvedSkills.map((skill) => skill.name) } : {}),
|
|
1726
1749
|
...(recoveryAgentConfig.skillPath ? { skillPath: [...recoveryAgentConfig.skillPath] } : {}),
|
|
@@ -1735,7 +1758,6 @@ export function executeAsyncSingle(
|
|
|
1735
1758
|
...(params.context ? { context: params.context } : {}),
|
|
1736
1759
|
...(params.intercomBridge !== undefined ? { intercomBridge: params.intercomBridge } : {}),
|
|
1737
1760
|
...(deadlineAt !== undefined ? { absoluteDeadlineAt: deadlineAt } : {}),
|
|
1738
|
-
...(initialTurnBudget ? { initialTurnBudget: { maxTurns: initialTurnBudget.maxTurns, graceTurns: initialTurnBudget.graceTurns } } : {}),
|
|
1739
1761
|
...(resolvedToolBudget.budget ? { initialToolBudget: resolvedToolBudget.budget } : {}),
|
|
1740
1762
|
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, recoveryAgentConfig.maxSubagentDepth),
|
|
1741
1763
|
...(maxOutput ? { maxOutput } : {}),
|
|
@@ -1770,7 +1792,9 @@ export function executeAsyncSingle(
|
|
|
1770
1792
|
...(params.externalJobFollowUp ? { externalJobFollowUp: params.externalJobFollowUp } : {}),
|
|
1771
1793
|
...(params.context ? { context: params.context } : {}),
|
|
1772
1794
|
cwd: runnerCwd,
|
|
1795
|
+
requestedCwd: params.requestedCwd ?? runnerCwd,
|
|
1773
1796
|
model,
|
|
1797
|
+
...(contextLimit !== undefined ? { contextLimit } : {}),
|
|
1774
1798
|
...(params.fast ?? agentConfig.fast ? { fast: params.fast ?? agentConfig.fast } : {}),
|
|
1775
1799
|
thinking: resolveEffectiveThinking(model, effectiveThinking),
|
|
1776
1800
|
...(thinkingCeiling ? { thinkingCeiling } : {}),
|
|
@@ -1778,20 +1802,27 @@ export function executeAsyncSingle(
|
|
|
1778
1802
|
...(params.modelOverrideFromParent ? { skipPrimaryModelVerification: true } : {}),
|
|
1779
1803
|
...(availableModels && availableModels.length > 0 ? { modelVerificationRegistry: availableModels } : {}),
|
|
1780
1804
|
tools: agentConfig.tools,
|
|
1805
|
+
allowNestedSubagents: agentConfig.allowNestedSubagents,
|
|
1781
1806
|
extensions: agentConfig.extensions,
|
|
1782
1807
|
subagentOnlyExtensions: agentConfig.subagentOnlyExtensions,
|
|
1783
1808
|
mcpDirectTools: agentConfig.mcpDirectTools,
|
|
1809
|
+
...(toolPlan.mcpConfig ? { mcpConfig: toolPlan.mcpConfig } : {}),
|
|
1810
|
+
...(toolPlan.runtimeServerNames ? { runtimeServerNames: toolPlan.runtimeServerNames } : {}),
|
|
1811
|
+
mutationTools: agentConfig.mutationTools,
|
|
1784
1812
|
completionGuard: agentConfig.completionGuard,
|
|
1785
1813
|
systemPrompt,
|
|
1786
1814
|
systemPromptMode: agentConfig.systemPromptMode,
|
|
1787
1815
|
inheritProjectContext: agentConfig.inheritProjectContext,
|
|
1816
|
+
inheritGlobalContext: agentConfig.inheritGlobalContext,
|
|
1788
1817
|
inheritSkills: agentConfig.inheritSkills,
|
|
1789
1818
|
skills: resolvedSkills.map((r) => r.name),
|
|
1790
1819
|
outputPath,
|
|
1820
|
+
...(params.outputClaimPath ? { outputClaimPath: params.outputClaimPath } : {}),
|
|
1791
1821
|
outputMode,
|
|
1792
1822
|
...(!externalRunner && sessionFile ? { sessionFile } : {}),
|
|
1793
1823
|
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, agentConfig.maxSubagentDepth),
|
|
1794
1824
|
waitToolEnabled: params.waitToolEnabled,
|
|
1825
|
+
waitToolDefaultTimeoutMs: params.waitToolDefaultTimeoutMs,
|
|
1795
1826
|
...(params.agentContract ? { agentContract: params.agentContract } : {}),
|
|
1796
1827
|
definitionDigest: agentDefinitionDigest(agentConfig),
|
|
1797
1828
|
launchBindingTask: task,
|
|
@@ -1803,6 +1834,7 @@ export function executeAsyncSingle(
|
|
|
1803
1834
|
...(params.structuredOutputSchema ? { structuredOutputSchema: params.structuredOutputSchema } : {}),
|
|
1804
1835
|
...(resolvedToolBudget.budget ? { toolBudget: resolvedToolBudget.budget } : {}),
|
|
1805
1836
|
...(params.worktree === true ? { worktree: true } : {}),
|
|
1837
|
+
...(lane ? { lane } : {}),
|
|
1806
1838
|
},
|
|
1807
1839
|
],
|
|
1808
1840
|
resultPath: params.parentWorkflowRunId !== undefined && (params.revivalLease !== undefined || params.workflowAwaitAsync === true)
|
|
@@ -1828,7 +1860,6 @@ export function executeAsyncSingle(
|
|
|
1828
1860
|
timeoutMs,
|
|
1829
1861
|
deadlineAt,
|
|
1830
1862
|
toolTimeoutMs,
|
|
1831
|
-
turnBudget: params.turnBudget,
|
|
1832
1863
|
toolBudget: params.toolBudget,
|
|
1833
1864
|
usageBudget: params.usageBudget,
|
|
1834
1865
|
controlIntercomTarget,
|
|
@@ -1839,6 +1870,7 @@ export function executeAsyncSingle(
|
|
|
1839
1870
|
runFanoutBudget,
|
|
1840
1871
|
...(params.parentWorkflowRunId ? { parentWorkflowRunId: params.parentWorkflowRunId } : {}),
|
|
1841
1872
|
...(params.workflowKey ? { workflowKey: params.workflowKey } : {}),
|
|
1873
|
+
...(lane ? { lane } : {}),
|
|
1842
1874
|
...(params.revivalLease ? { revivalLease: params.revivalLease } : {}),
|
|
1843
1875
|
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
1844
1876
|
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
@@ -1861,10 +1893,12 @@ export function executeAsyncSingle(
|
|
|
1861
1893
|
lastUpdate: initialStatusAt,
|
|
1862
1894
|
currentStep: 0,
|
|
1863
1895
|
chainStepCount: 1,
|
|
1864
|
-
|
|
1896
|
+
...(lane ? { lane } : {}),
|
|
1897
|
+
steps: [{ agent, status: "pending", ...(lane ? { lane } : {}), ...(model ? { model } : {}), ...(contextLimit !== undefined ? { contextLimit } : {}) }],
|
|
1865
1898
|
},
|
|
1866
1899
|
path.join(asyncDir, "status.json"),
|
|
1867
1900
|
(proof) => emitProcessTerminalEvent(ctx, proof),
|
|
1901
|
+
params.requestedCwd ?? runnerCwd,
|
|
1868
1902
|
);
|
|
1869
1903
|
} catch (error) {
|
|
1870
1904
|
params.activeAsyncCapacity?.rollback();
|
|
@@ -1910,7 +1944,6 @@ export function executeAsyncSingle(
|
|
|
1910
1944
|
agents: [agent],
|
|
1911
1945
|
chainStepCount: 1,
|
|
1912
1946
|
...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}),
|
|
1913
|
-
...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
|
|
1914
1947
|
startedAt: now,
|
|
1915
1948
|
lastUpdate: now,
|
|
1916
1949
|
...(capabilityCeiling ? { capabilityCeiling } : {}),
|
|
@@ -1938,7 +1971,6 @@ export function executeAsyncSingle(
|
|
|
1938
1971
|
...(params.parentWorkflowRunId ? { parentWorkflowRunId: params.parentWorkflowRunId } : {}),
|
|
1939
1972
|
...(params.workflowKey ? { workflowKey: params.workflowKey } : {}),
|
|
1940
1973
|
...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}),
|
|
1941
|
-
...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
|
|
1942
1974
|
...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}),
|
|
1943
1975
|
...(capabilityCeiling ? { capabilityCeiling } : {}),
|
|
1944
1976
|
nestedRoute,
|
|
@@ -1947,6 +1979,6 @@ export function executeAsyncSingle(
|
|
|
1947
1979
|
|
|
1948
1980
|
return {
|
|
1949
1981
|
content: [{ type: "text", text: formatAsyncStartedMessage(`Async: ${agent} [${id}]`, ctx.interactive === true) }],
|
|
1950
|
-
details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, launchContractDigest, launchResolvedExtensions, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.context ? { context: params.context } : {}), ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}), ...(params.
|
|
1982
|
+
details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, launchContractDigest, launchResolvedExtensions, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.context ? { context: params.context } : {}), ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}), ...(params.toolBudget ? { toolBudget: resolvedToolBudget.budget ?? params.toolBudget } : {}), ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}) } as Details,
|
|
1951
1983
|
};
|
|
1952
1984
|
}
|
|
@@ -25,6 +25,8 @@ import { listAsyncRuns, type AsyncRunSummary } from "./async-status.ts";
|
|
|
25
25
|
import { EXTERNAL_JOB_BRIDGE_REQUEST_DIR, serviceExternalJobBridgeRequests } from "../shared/external-job-bridge.ts";
|
|
26
26
|
import { shouldUseNativeFsWatch } from "../../shared/watch-strategy.ts";
|
|
27
27
|
import { parseWorkflowChildSummary } from "../../workflows/workflow-child-summary.ts";
|
|
28
|
+
import { validHostStepNodes } from "../shared/host-step-status.ts";
|
|
29
|
+
import { withCachedUiContext } from "../../shared/extension-context.ts";
|
|
28
30
|
|
|
29
31
|
interface AsyncJobTrackerOptions {
|
|
30
32
|
completionRetentionMs?: number;
|
|
@@ -78,23 +80,19 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
78
80
|
const watch = options.watch ?? fs.watch;
|
|
79
81
|
const useNativeWatcher = () => shouldUseNativeFsWatch("async-job-tracker", options.platform);
|
|
80
82
|
const terminalStatus = (status: string) => status === "complete" || status === "failed" || status === "paused" || status === "stopped";
|
|
83
|
+
const withLastUiContext = <T>(run: (ctx: ExtensionContext) => T): T | undefined => {
|
|
84
|
+
const cached = state.lastUiContext;
|
|
85
|
+
return withCachedUiContext(cached, () => {
|
|
86
|
+
if (state.lastUiContext === cached) state.lastUiContext = null;
|
|
87
|
+
}, run);
|
|
88
|
+
};
|
|
81
89
|
const rerenderWidget = (ctx: ExtensionContext, jobs = Array.from(state.asyncJobs.values())) => {
|
|
82
90
|
if (state.widgetsSuspended) return;
|
|
83
91
|
renderWidget(ctx, options.widgetEnabled === false ? [] : jobs);
|
|
84
92
|
(ctx.ui as { requestRender?: () => void }).requestRender?.();
|
|
85
93
|
};
|
|
86
94
|
const rerenderLastWidget = (jobs = Array.from(state.asyncJobs.values())) => {
|
|
87
|
-
|
|
88
|
-
if (!ctx) return;
|
|
89
|
-
try {
|
|
90
|
-
if (ctx.hasUI) rerenderWidget(ctx, jobs);
|
|
91
|
-
} catch (error) {
|
|
92
|
-
if (error instanceof Error && error.message.includes("extension ctx is stale")) {
|
|
93
|
-
state.lastUiContext = null;
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
throw error;
|
|
97
|
-
}
|
|
95
|
+
withLastUiContext((ctx) => rerenderWidget(ctx, jobs));
|
|
98
96
|
};
|
|
99
97
|
const requestLastWidgetRender = () => {
|
|
100
98
|
if (options.widgetEnabled === false) return;
|
|
@@ -147,6 +145,8 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
147
145
|
currentStep: run.currentStep,
|
|
148
146
|
chainStepCount: run.chainStepCount,
|
|
149
147
|
parallelGroups: groups,
|
|
148
|
+
hostSteps: run.hostSteps,
|
|
149
|
+
preflight: run.preflight,
|
|
150
150
|
steps: visibleSteps,
|
|
151
151
|
stepsTotal: visibleSteps.length,
|
|
152
152
|
runningSteps: visibleSteps.filter((step) => step.status === "running").length,
|
|
@@ -342,7 +342,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
342
342
|
};
|
|
343
343
|
|
|
344
344
|
const refreshJob = (job: AsyncJobState): boolean => {
|
|
345
|
-
const widgetExpanded =
|
|
345
|
+
const widgetExpanded = withLastUiContext((ctx) => ctx.ui.getToolsExpanded?.() ?? false) ?? false;
|
|
346
346
|
const widgetStateBefore = widgetRenderKey(job, widgetExpanded);
|
|
347
347
|
let nestedRefreshFailed = false;
|
|
348
348
|
const refreshNestedProjection = () => {
|
|
@@ -399,7 +399,9 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
|
|
|
399
399
|
job.mode = status.mode;
|
|
400
400
|
job.parentWorkflowRunId = status.parentWorkflowRunId ?? job.parentWorkflowRunId;
|
|
401
401
|
job.workflowKey = status.workflowKey ?? job.workflowKey;
|
|
402
|
+
job.lane = status.lane ?? job.lane;
|
|
402
403
|
job.workflow = status.workflow ?? job.workflow;
|
|
404
|
+
job.hostSteps = validHostStepNodes(status.workflowGraph);
|
|
403
405
|
const workflowChildren = parseWorkflowChildSummary(status.workflowChildren);
|
|
404
406
|
if (workflowChildren && workflowChildren.workflowRunId !== status.runId) throw new Error("workflowChildren.workflowRunId does not match async status runId.");
|
|
405
407
|
job.workflowChildren = workflowChildren ?? job.workflowChildren;
|