pi-subagents 0.81.0 → 0.82.1
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 +55 -0
- package/README.md +1 -1
- package/bundle/agents.js +3 -3
- package/bundle/child-tool-plan.js +2 -2
- package/bundle/{chunk-L5ZHE4L4.js → chunk-3JCDWF4V.js} +4 -4
- package/bundle/{chunk-LSRUTHT7.js → chunk-43SCHIMD.js} +1 -1
- package/bundle/{chunk-VJHOELQP.js → chunk-46XKCPJR.js} +193 -81
- package/bundle/{chunk-G5DKFLLI.js → chunk-4SDU2BZX.js} +15 -10
- package/bundle/{chunk-2ZSNH26H.js → chunk-4Y2ROR7L.js} +7 -7
- package/bundle/{chunk-V2JWDB5U.js → chunk-52UBALJL.js} +2 -2
- package/bundle/{chunk-3DC5KBVP.js → chunk-5TYMSZX3.js} +1 -1
- package/bundle/{chunk-NNLASTQE.js → chunk-6XJB7PIX.js} +20 -6
- package/bundle/{chunk-ZBC44JJ3.js → chunk-CIZQXJ5Q.js} +22 -9
- package/bundle/{chunk-KSWQVGDW.js → chunk-FXUXCX2K.js} +225 -18
- package/bundle/{chunk-563BHAZ5.js → chunk-G4GZD3OJ.js} +35 -26
- package/bundle/{chunk-ARRKBB2B.js → chunk-GJECHSAR.js} +2 -2
- package/bundle/{chunk-V3BIUPLU.js → chunk-IVAE5Z6Q.js} +256 -52
- package/bundle/{chunk-V6MR5TOQ.js → chunk-JYUKW2SY.js} +25 -19
- package/bundle/{chunk-BJN5LUQY.js → chunk-OYF6AFDY.js} +1 -1
- package/bundle/{chunk-CEKS3TFO.js → chunk-PBK2I7WY.js} +6 -6
- package/bundle/{chunk-TUWLXTAM.js → chunk-PDZWJCHD.js} +681 -320
- package/bundle/{chunk-EYNJ6VL6.js → chunk-PLCCBLPY.js} +2 -2
- package/bundle/{chunk-XMFLCKMQ.js → chunk-QE4AGIMG.js} +339 -132
- package/bundle/{chunk-74RT5YQE.js → chunk-RMQFMMAT.js} +123 -33
- package/bundle/{chunk-WSBNENFS.js → chunk-UCPP4GNU.js} +14 -4
- package/bundle/{chunk-2XYWN7QJ.js → chunk-UTT254JE.js} +2 -2
- package/bundle/{chunk-BPS2AGBZ.js → chunk-VSUSLDNW.js} +93 -52
- package/bundle/{chunk-ZP3HODFH.js → chunk-XSWOTIA3.js} +1 -1
- package/bundle/{chunk-3IF2PGW7.js → chunk-YKEWIB4M.js} +1 -1
- package/bundle/{chunk-26C3WLYQ.js → chunk-ZIV4J4HG.js} +498 -274
- package/bundle/control-channel.js +2 -2
- package/bundle/index.js +1 -1
- package/bundle/intercom-bridge.js +2 -2
- package/bundle/preflight.js +8 -8
- package/bundle/project-panes.js +3 -3
- package/docs/agents.md +37 -7
- package/docs/configuration.md +9 -1
- package/docs/tool-reference.md +3 -1
- package/docs/workflows.md +16 -0
- package/package.json +2 -2
- package/skills/council-mode/SKILL.md +1 -4
- package/skills/pi-subagents/SKILL.md +130 -107
- package/skills/pi-subagents/references/orchestration.md +124 -0
- package/skills/pi-subagents/references/prompting-and-roles.md +96 -295
- package/src/agents/agent-management.js +3 -3
- package/src/agents/agent-memory.js +3 -1
- package/src/agents/agents.js +6 -6
- package/src/agents/frontmatter.d.ts +2 -0
- package/src/agents/frontmatter.js +15 -1
- package/src/agents/skills.js +2 -1
- package/src/extension/config.js +3 -0
- package/src/extension/herdr-pi-bridge.js +17 -10
- package/src/extension/index.js +82 -2
- package/src/extension/reply-workflow-script.js +5 -2
- package/src/extension/schemas.js +3 -3
- package/src/extension/subagent-guide.js +1 -2
- package/src/intercom/native-supervisor-channel.js +20 -0
- package/src/missions/lifecycle.js +7 -1
- package/src/runs/background/active-async-capacity.d.ts +1 -0
- package/src/runs/background/active-async-capacity.js +9 -3
- package/src/runs/background/async-execution.js +20 -10
- package/src/runs/background/async-job-tracker.d.ts +6 -1
- package/src/runs/background/async-job-tracker.js +9 -4
- package/src/runs/background/async-status.d.ts +4 -0
- package/src/runs/background/async-status.js +22 -3
- package/src/runs/background/await-async-run.js +3 -7
- package/src/runs/background/boot-id.d.ts +12 -0
- package/src/runs/background/boot-id.js +47 -0
- package/src/runs/background/interrupted-elsewhere.d.ts +22 -0
- package/src/runs/background/interrupted-elsewhere.js +68 -0
- package/src/runs/background/notify.d.ts +2 -0
- package/src/runs/background/notify.js +13 -0
- package/src/runs/background/result-delivery-ownership.d.ts +6 -0
- package/src/runs/background/result-delivery-ownership.js +19 -1
- package/src/runs/background/result-watcher.d.ts +3 -1
- package/src/runs/background/result-watcher.js +24 -8
- package/src/runs/background/run-child-session.d.ts +1 -6
- package/src/runs/background/run-child-session.js +1 -1
- package/src/runs/background/run-status.js +2 -1
- package/src/runs/background/stale-run-reconciler.d.ts +25 -0
- package/src/runs/background/stale-run-reconciler.js +52 -13
- package/src/runs/background/subagent-runner-bootstrap.js +3 -0
- package/src/runs/background/subagent-runner.d.ts +4 -0
- package/src/runs/background/subagent-runner.js +13 -5
- package/src/runs/background/subagent-wait.d.ts +1 -1
- package/src/runs/background/subagent-wait.js +6 -1
- package/src/runs/background/terminal-run-index.d.ts +2 -0
- package/src/runs/background/terminal-run-index.js +44 -3
- package/src/runs/foreground/async-stop-action.js +3 -1
- package/src/runs/foreground/execution.js +6 -3
- package/src/runs/foreground/foreground-history.d.ts +16 -2
- package/src/runs/foreground/foreground-history.js +133 -31
- package/src/runs/foreground/subagent-executor.d.ts +11 -0
- package/src/runs/foreground/subagent-executor.js +277 -74
- package/src/runs/shared/child-launch.d.ts +2 -2
- package/src/runs/shared/child-session.d.ts +3 -2
- package/src/runs/shared/child-session.js +51 -8
- package/src/runs/shared/child-tool-plan.d.ts +7 -0
- package/src/runs/shared/child-tool-plan.js +21 -6
- package/src/runs/shared/herdr-connection.d.ts +17 -8
- package/src/runs/shared/herdr-connection.js +19 -7
- package/src/runs/shared/herdr-external-adapters.d.ts +3 -2
- package/src/runs/shared/herdr-external-adapters.js +1 -1
- package/src/runs/shared/herdr-machine.d.ts +12 -2
- package/src/runs/shared/herdr-machine.js +55 -9
- package/src/runs/shared/herdr-pane-host.d.ts +88 -0
- package/src/runs/shared/herdr-pane-host.js +155 -0
- package/src/runs/shared/herdr-placed-run.d.ts +27 -150
- package/src/runs/shared/herdr-placed-run.js +48 -395
- package/src/runs/shared/local-machine-access.d.ts +5 -0
- package/src/runs/shared/local-machine-access.js +28 -0
- package/src/runs/shared/orca-progress-tabs.d.ts +0 -1
- package/src/runs/shared/orca-progress-tabs.js +1 -24
- package/src/runs/shared/parallel-utils.d.ts +1 -1
- package/src/runs/shared/placed-run-owner.d.ts +49 -0
- package/src/runs/shared/placed-run-owner.js +93 -0
- package/src/runs/shared/placement-host.d.ts +99 -0
- package/src/runs/shared/placement-host.js +157 -0
- package/src/runs/shared/rex-machine.d.ts +25 -0
- package/src/runs/shared/rex-machine.js +83 -0
- package/src/runs/shared/rex-pane-host.d.ts +62 -0
- package/src/runs/shared/rex-pane-host.js +327 -0
- package/src/shared/completion-owner.d.ts +5 -0
- package/src/shared/completion-owner.js +5 -0
- package/src/shared/session-identity.d.ts +2 -0
- package/src/shared/session-identity.js +26 -0
- package/src/shared/types.d.ts +45 -6
- package/src/tui/fleet.d.ts +1 -0
- package/src/tui/fleet.js +25 -15
- package/src/tui/render.d.ts +6 -0
- package/src/tui/render.js +3 -3
- package/src/tui/subagent-messages.js +1 -0
- package/src/workflows/scripted-workflow.d.ts +1 -1
- package/src/workflows/workflow-auto-resume.d.ts +32 -0
- package/src/workflows/workflow-auto-resume.js +102 -0
- package/src/workflows/workflow-launch-record.d.ts +27 -0
- package/src/workflows/workflow-launch-record.js +48 -0
- package/src/workflows/workflow-resume-claim.d.ts +82 -0
- package/src/workflows/workflow-resume-claim.js +210 -0
- package/src/workflows/workflow-resume.d.ts +56 -0
- package/src/workflows/workflow-resume.js +106 -0
- package/src/workflows/workflow-reuse.d.ts +15 -9
- package/src/workflows/workflow-reuse.js +77 -14
- package/src/workflows/workflow-revival.d.ts +2 -0
- package/src/workflows/workflow-revival.js +2 -1
- package/src/workflows/workflow-stop-cause.d.ts +6 -0
- package/src/workflows/workflow-stop-cause.js +8 -0
- package/skills/pi-subagents/references/constraints-and-recipes.md +0 -74
- package/skills/pi-subagents/references/execution-controls.md +0 -563
- package/skills/pi-subagents/references/management-authoring-rpc.md +0 -165
- package/skills/pi-subagents/references/multi-lane-orchestration.md +0 -61
- package/skills/pi-subagents/references/review-and-validation.md +0 -73
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
projectRuntimeAcknowledgedExtensions,
|
|
4
4
|
registerSubagentPromptBoundary,
|
|
5
5
|
registerSubagentPromptRuntime
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3JCDWF4V.js";
|
|
7
7
|
import {
|
|
8
8
|
INSPECTOR_ACTIONS,
|
|
9
9
|
canQueueRetainedAsyncFollowUp,
|
|
@@ -25,15 +25,19 @@ import {
|
|
|
25
25
|
updateSteeringTarget,
|
|
26
26
|
waitForSteeringAction,
|
|
27
27
|
workflowAsyncChildSteeringGuidance
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import
|
|
28
|
+
} from "./chunk-PBK2I7WY.js";
|
|
29
|
+
import {
|
|
30
|
+
REX_LOCAL_MACHINE,
|
|
31
|
+
isRexLocalMachine,
|
|
32
|
+
resolveRexLocalPlacement
|
|
33
|
+
} from "./chunk-RMQFMMAT.js";
|
|
30
34
|
import {
|
|
31
35
|
COMPLETION_ACTION,
|
|
32
36
|
DEFAULT_CONTROL_CONFIG,
|
|
33
37
|
HERDR_FOREGROUND_CONTROL_CHANGED_EVENT,
|
|
34
38
|
JITI_ALIAS_ENV,
|
|
35
|
-
MAX_REMEMBERED_FOREGROUND_RUNS,
|
|
36
39
|
STATUS_ACTION,
|
|
40
|
+
WORKFLOW_RUNTIME_REPLACED_STOP_NOTICE,
|
|
37
41
|
appendWorkflowChildJournal,
|
|
38
42
|
attachNestedChildrenToResultChildren,
|
|
39
43
|
buildControlEvent,
|
|
@@ -45,6 +49,8 @@ import {
|
|
|
45
49
|
childSessionFactoryModule,
|
|
46
50
|
childSessionHasQueuedMessages,
|
|
47
51
|
claimControlNotification,
|
|
52
|
+
claimWorkflowResume,
|
|
53
|
+
claimedWorkflowRunRefusal,
|
|
48
54
|
clearProviderRetry,
|
|
49
55
|
controlChildCommand,
|
|
50
56
|
createChildExternalJobBridgeSweeper,
|
|
@@ -72,11 +78,12 @@ import {
|
|
|
72
78
|
isScheduledRunAction,
|
|
73
79
|
isWorkflowScriptPath,
|
|
74
80
|
listRetainedChildren,
|
|
81
|
+
manualWorkflowResumeRefusalText,
|
|
75
82
|
matchWorkflowReuse,
|
|
76
83
|
normalizePublicSubagentExecution,
|
|
77
84
|
observeProviderDiagnostics,
|
|
78
85
|
parseWatchdogThinkingInput,
|
|
79
|
-
|
|
86
|
+
prepareWorkflowResume,
|
|
80
87
|
projectChildSessionEventForJson,
|
|
81
88
|
projectWorkflowKeyRevival,
|
|
82
89
|
readNamedWorkflowReuseSource,
|
|
@@ -84,13 +91,16 @@ import {
|
|
|
84
91
|
readWorkflowReceipt,
|
|
85
92
|
recommendStrongWatchdogModel,
|
|
86
93
|
recommendWatchdogModel,
|
|
94
|
+
recordWorkflowResumeRefusal,
|
|
87
95
|
recordWorkflowRevival,
|
|
96
|
+
releaseWorkflowResumeClaim,
|
|
88
97
|
resolveControlConfig,
|
|
89
98
|
resolveHostPeerAliases,
|
|
90
99
|
resolveSubagentResultStatus,
|
|
91
100
|
resolveToolTimeoutMs,
|
|
92
101
|
resolveWatchdogModelInput,
|
|
93
102
|
resolveWorkflowReceiptResumeEntry,
|
|
103
|
+
resumedRunStarted,
|
|
94
104
|
retainLiveForegroundNestedRoute,
|
|
95
105
|
retainsChildCommand,
|
|
96
106
|
shouldEmitOpenToolAttention,
|
|
@@ -103,11 +113,13 @@ import {
|
|
|
103
113
|
withWorkflowRevivals,
|
|
104
114
|
workflowChildFingerprint,
|
|
105
115
|
workflowReceiptPath,
|
|
106
|
-
|
|
116
|
+
workflowResumeRefusal,
|
|
117
|
+
workflowResumeTargetId,
|
|
107
118
|
workflowScriptDigest,
|
|
108
119
|
workflowStopCause,
|
|
120
|
+
writeWorkflowLaunchRecord,
|
|
109
121
|
writeWorkflowReceipt
|
|
110
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-ZIV4J4HG.js";
|
|
111
123
|
import {
|
|
112
124
|
NATIVE_SUPERVISOR_TOOL_NAME,
|
|
113
125
|
SUBAGENT_PARENT_SESSION_ENV,
|
|
@@ -117,22 +129,26 @@ import {
|
|
|
117
129
|
finalizeToolResult,
|
|
118
130
|
registerPinnedTool,
|
|
119
131
|
resolveCurrentSessionId,
|
|
132
|
+
resolvePiSessionId,
|
|
120
133
|
resolveSupervisorChannelDir,
|
|
121
134
|
resolveWaitToolConfig,
|
|
122
135
|
resolveWatchdogConfig,
|
|
123
136
|
sendRuleViolationWarning,
|
|
124
137
|
writeWatchdogModelSettings
|
|
125
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-VSUSLDNW.js";
|
|
126
139
|
import {
|
|
127
|
-
|
|
140
|
+
MAX_REMEMBERED_FOREGROUND_RUNS,
|
|
141
|
+
discardRunningForegroundRun,
|
|
142
|
+
foregroundChildStateLabel,
|
|
128
143
|
formatAsyncResultTranscript,
|
|
129
144
|
formatAsyncRunTranscript,
|
|
130
145
|
formatNestedRunTranscript,
|
|
131
146
|
inspectSubagentFleet,
|
|
147
|
+
persistForegroundRun,
|
|
132
148
|
resolveSubagentRunId,
|
|
133
149
|
resolveWorkflowChatProgress,
|
|
134
150
|
stopAsyncRun
|
|
135
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-FXUXCX2K.js";
|
|
136
152
|
import {
|
|
137
153
|
MODEL_ONLY_TOOL,
|
|
138
154
|
RunFanoutLimitError,
|
|
@@ -194,7 +210,7 @@ import {
|
|
|
194
210
|
writeParallelHandoffGroup,
|
|
195
211
|
writeRunFanoutBudgetDescriptor,
|
|
196
212
|
writeWorktreeSetupHandoff
|
|
197
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-6XJB7PIX.js";
|
|
198
214
|
import {
|
|
199
215
|
authorizeWorkflowResourceHost,
|
|
200
216
|
claimWorkflowChildPermit,
|
|
@@ -211,10 +227,10 @@ import {
|
|
|
211
227
|
canPreferFork,
|
|
212
228
|
createForkContextResolver,
|
|
213
229
|
resolveSubagentLaunchContext
|
|
214
|
-
} from "./chunk-
|
|
230
|
+
} from "./chunk-GJECHSAR.js";
|
|
215
231
|
import {
|
|
216
232
|
handleRefinementAction
|
|
217
|
-
} from "./chunk-
|
|
233
|
+
} from "./chunk-PLCCBLPY.js";
|
|
218
234
|
import {
|
|
219
235
|
ActiveAsyncCapacityError,
|
|
220
236
|
acquireActiveAsyncCapacity,
|
|
@@ -228,7 +244,7 @@ import {
|
|
|
228
244
|
resolveDisabledFeatureSurface,
|
|
229
245
|
resolveMaxActiveAsyncRunsPerSession,
|
|
230
246
|
transferActiveAsyncCapacity
|
|
231
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-UCPP4GNU.js";
|
|
232
248
|
import {
|
|
233
249
|
DEFAULT_STALE_TERMINAL_ACTIVE_MARKER_MS,
|
|
234
250
|
MACHINE_DIFF_OPTIONS,
|
|
@@ -239,12 +255,15 @@ import {
|
|
|
239
255
|
activeRunMarkerAgeMs,
|
|
240
256
|
attachMissionToLaunchResult,
|
|
241
257
|
attachRootChildrenToSteps,
|
|
242
|
-
|
|
258
|
+
checkRecordedPidLiveness,
|
|
243
259
|
cleanupWorktrees,
|
|
244
260
|
createMissionWorkflowState,
|
|
245
261
|
createNestedRoute,
|
|
246
262
|
createWorktrees,
|
|
263
|
+
currentBootId,
|
|
264
|
+
currentCompletionOwnerId,
|
|
247
265
|
currentPidNamespaceScope,
|
|
266
|
+
currentRecordedPid,
|
|
248
267
|
diffWorktrees,
|
|
249
268
|
encodeIndexSegment,
|
|
250
269
|
executeWorkflowHostCommand,
|
|
@@ -304,7 +323,7 @@ import {
|
|
|
304
323
|
writeNestedControlRequest,
|
|
305
324
|
writeNestedControlResult,
|
|
306
325
|
writeNestedEvent
|
|
307
|
-
} from "./chunk-
|
|
326
|
+
} from "./chunk-46XKCPJR.js";
|
|
308
327
|
import {
|
|
309
328
|
closeSteerInbox,
|
|
310
329
|
consumeSteerRequests,
|
|
@@ -312,7 +331,7 @@ import {
|
|
|
312
331
|
readRevivalBriefs,
|
|
313
332
|
requestAsyncSteer,
|
|
314
333
|
watchAsyncControlInbox
|
|
315
|
-
} from "./chunk-
|
|
334
|
+
} from "./chunk-OYF6AFDY.js";
|
|
316
335
|
import "./chunk-NIXWDZZV.js";
|
|
317
336
|
import {
|
|
318
337
|
INTERCOM_BRIDGE_MARKER,
|
|
@@ -321,7 +340,7 @@ import {
|
|
|
321
340
|
resolveIntercomBridge,
|
|
322
341
|
resolveIntercomSessionTarget,
|
|
323
342
|
resolveSubagentIntercomTarget
|
|
324
|
-
} from "./chunk-
|
|
343
|
+
} from "./chunk-XSWOTIA3.js";
|
|
325
344
|
import {
|
|
326
345
|
resolveLaunchBinding,
|
|
327
346
|
stableJsonDigest
|
|
@@ -335,7 +354,7 @@ import {
|
|
|
335
354
|
resolvePiLaunchToolPlan,
|
|
336
355
|
resolveRuntimeModulePath,
|
|
337
356
|
supervisorChannelDir
|
|
338
|
-
} from "./chunk-
|
|
357
|
+
} from "./chunk-4SDU2BZX.js";
|
|
339
358
|
import {
|
|
340
359
|
assertRequiredChildExtensionsAdmitted,
|
|
341
360
|
hasMandatoryRequiredChildExtensions,
|
|
@@ -346,7 +365,7 @@ import {
|
|
|
346
365
|
import {
|
|
347
366
|
HERDR_PROJECT_PANE_ACTIONS,
|
|
348
367
|
handleHerdrProjectPaneAction
|
|
349
|
-
} from "./chunk-
|
|
368
|
+
} from "./chunk-52UBALJL.js";
|
|
350
369
|
import "./chunk-7J4ZXMY7.js";
|
|
351
370
|
import {
|
|
352
371
|
PROJECT_SUBAGENTS_RELATIVE_DIR,
|
|
@@ -359,12 +378,12 @@ import {
|
|
|
359
378
|
getProjectSubagentsDir,
|
|
360
379
|
writeArtifact,
|
|
361
380
|
writeMetadata
|
|
362
|
-
} from "./chunk-
|
|
381
|
+
} from "./chunk-5TYMSZX3.js";
|
|
363
382
|
import "./chunk-N2BN7BF5.js";
|
|
364
383
|
import {
|
|
365
384
|
getExternalJobProvider
|
|
366
385
|
} from "./chunk-YYREO77V.js";
|
|
367
|
-
import "./chunk-
|
|
386
|
+
import "./chunk-YKEWIB4M.js";
|
|
368
387
|
import {
|
|
369
388
|
CODE_OWNED_EXTERNAL_CLI_ADAPTER_IDS,
|
|
370
389
|
ChainOutputValidationError,
|
|
@@ -512,7 +531,7 @@ import {
|
|
|
512
531
|
writeAtomicJson,
|
|
513
532
|
writeInitialProgressFile,
|
|
514
533
|
writePrivateAtomicJson
|
|
515
|
-
} from "./chunk-
|
|
534
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
516
535
|
import {
|
|
517
536
|
CHAIN_RUNS_DIR,
|
|
518
537
|
DEFAULT_ARTIFACT_CONFIG,
|
|
@@ -884,6 +903,11 @@ function machineSettingsFrom(settings, keys, filePath) {
|
|
|
884
903
|
throw new Error(`Subagent settings in '${filePath}' set 'machines.${key}.env'. Saved-machine runs use the remote Herdr/Pi environment; configure credentials and environment on '${key}' and remove the local env map.`);
|
|
885
904
|
}
|
|
886
905
|
}
|
|
906
|
+
if (record2.rex !== void 0) {
|
|
907
|
+
const rex = record2.rex, ssh = rex && typeof rex === "object" && !Array.isArray(rex) && Object.keys(rex).every((field) => field === "ssh") ? rex.ssh : void 0;
|
|
908
|
+
if (typeof ssh !== "string") throw new Error(`Subagent settings in '${filePath}' have invalid 'machines.${key}.rex'; expected { "ssh": "<ssh target>" }.`);
|
|
909
|
+
entry.rex = { ssh: validateTarget(ssh, key) };
|
|
910
|
+
}
|
|
887
911
|
return entry;
|
|
888
912
|
}
|
|
889
913
|
function readMachineSettings(cwd, keys) {
|
|
@@ -891,9 +915,14 @@ function readMachineSettings(cwd, keys) {
|
|
|
891
915
|
const projectPath = path.join(getProjectConfigDir(findProjectRootForSettings(cwd)), "settings.json");
|
|
892
916
|
const user = machineSettingsFrom(readJsonObject(userPath), keys, userPath);
|
|
893
917
|
const project = projectPath === userPath ? void 0 : machineSettingsFrom(readJsonObject(projectPath), keys, projectPath);
|
|
918
|
+
if (project?.rex) throw new Error(`Project settings '${projectPath}' set a Rex SSH host in 'machines'. Move the rex entry to your user settings '${userPath}'; only user settings choose which host a task runs on.`);
|
|
894
919
|
if (!user && !project) return void 0;
|
|
895
920
|
return { ...user, ...project };
|
|
896
921
|
}
|
|
922
|
+
function userRexMachine(machine) {
|
|
923
|
+
const userPath = path.join(getAgentDir(), "settings.json");
|
|
924
|
+
return machineSettingsFrom(readJsonObject(userPath), [machine], userPath)?.rex !== void 0;
|
|
925
|
+
}
|
|
897
926
|
function findProjectRootForSettings(cwd) {
|
|
898
927
|
let current = path.resolve(cwd);
|
|
899
928
|
while (true) {
|
|
@@ -903,6 +932,12 @@ function findProjectRootForSettings(cwd) {
|
|
|
903
932
|
current = parent;
|
|
904
933
|
}
|
|
905
934
|
}
|
|
935
|
+
function remoteMachineCwd(stepCwd, root, name) {
|
|
936
|
+
const step = stepCwd?.trim();
|
|
937
|
+
if (step && isRemoteAbsolute(step)) return step;
|
|
938
|
+
if (!root) throw new Error(`No root for ${name} in this repo. Set subagents.machines.${name}.cwd in .pi/settings.json or pass an absolute cwd on that machine.`);
|
|
939
|
+
return step ? path.posix.join(root, step) : root;
|
|
940
|
+
}
|
|
906
941
|
function resolveHerdrMachinePlacement(input) {
|
|
907
942
|
const requested = validateMachineName(input.machine);
|
|
908
943
|
const catalog = input.catalogJson !== void 0 ? parseMachineCatalog(input.catalogJson) : readHerdrMachineCatalog(input.env ?? process.env, input.herdrBin ?? process.env.HERDR_BIN ?? "herdr");
|
|
@@ -913,11 +948,7 @@ function resolveHerdrMachinePlacement(input) {
|
|
|
913
948
|
if (settings?.env && Object.keys(settings.env).length > 0) {
|
|
914
949
|
throw new Error(`Saved-machine environment for '${name}' must be configured remotely. Remove machines.${name}.env and configure the remote Herdr/Pi session instead.`);
|
|
915
950
|
}
|
|
916
|
-
const
|
|
917
|
-
let cwd;
|
|
918
|
-
if (stepCwd && isRemoteAbsolute(stepCwd)) cwd = stepCwd;
|
|
919
|
-
else if (settings?.cwd) cwd = stepCwd ? path.posix.join(settings.cwd, stepCwd) : settings.cwd;
|
|
920
|
-
else throw new Error(`No root for ${name} in this repo. Set subagents.machines.${name}.cwd in .pi/settings.json or pass an absolute cwd on that machine.`);
|
|
951
|
+
const cwd = remoteMachineCwd(input.stepCwd, settings?.cwd, name);
|
|
921
952
|
return {
|
|
922
953
|
machine: {
|
|
923
954
|
provider: "herdr",
|
|
@@ -930,8 +961,31 @@ function resolveHerdrMachinePlacement(input) {
|
|
|
930
961
|
...settings?.env ? { env: settings.env } : {}
|
|
931
962
|
};
|
|
932
963
|
}
|
|
964
|
+
function resolveMachinePlacement(input) {
|
|
965
|
+
const requested = validateMachineName(input.machine);
|
|
966
|
+
const settings = input.settings ?? readMachineSettings(input.cwd, [requested]);
|
|
967
|
+
if (requested === REX_LOCAL_MACHINE) {
|
|
968
|
+
if (settings?.rex) throw new Error("Machine 'local' is reserved for a Rex pane on this machine; give the Rex SSH host in subagents.machines.local.rex another name.");
|
|
969
|
+
return { machine: resolveRexLocalPlacement({ cwd: input.cwd, stepCwd: input.stepCwd, env: input.env }) };
|
|
970
|
+
}
|
|
971
|
+
if (settings?.rex) return { machine: { provider: "rex", id: requested, target: settings.rex.ssh, cwd: validateRemoteCwd(remoteMachineCwd(input.stepCwd, settings.cwd, requested), requested) } };
|
|
972
|
+
return resolveHerdrMachinePlacement(input);
|
|
973
|
+
}
|
|
933
974
|
function formatHerdrMachineRunnerUnsupported(input) {
|
|
934
975
|
if (input.machine === void 0) return void 0;
|
|
976
|
+
const name = input.machine.trim();
|
|
977
|
+
let rex;
|
|
978
|
+
try {
|
|
979
|
+
rex = name === REX_LOCAL_MACHINE || userRexMachine(name);
|
|
980
|
+
} catch (error) {
|
|
981
|
+
return error instanceof Error ? error.message : String(error);
|
|
982
|
+
}
|
|
983
|
+
if (rex) {
|
|
984
|
+
if (input.runnerType !== void 0 && input.runnerType !== "pi") return `Agent '${input.agentName}' requested machine '${name}', but Rex supports native Pi children only. Remove the machine or use a native Pi agent.`;
|
|
985
|
+
if (input.worktree === true) return `Agent '${input.agentName}' requested machine '${name}', but managed worktrees cannot be combined with machine placement.`;
|
|
986
|
+
if (process.platform === "win32") return `Machine '${name}' runs the child in a Rex pane, which is not supported on Windows.`;
|
|
987
|
+
return void 0;
|
|
988
|
+
}
|
|
935
989
|
if (input.runnerType !== void 0 && input.runnerType !== "pi" && input.runnerType !== "external-cli") {
|
|
936
990
|
return `Agent '${input.agentName}' requested machine '${input.machine}', but this runner cannot use pane-native Herdr placement. Use native Pi or a built-in Claude, Codex, or Cursor profile.`;
|
|
937
991
|
}
|
|
@@ -2044,7 +2098,9 @@ function spawnRunner(cfg, suffix, cwd, initialStatus, initialStatusPath, launchP
|
|
|
2044
2098
|
const runnerProcessInstanceId = randomUUID2();
|
|
2045
2099
|
const hasRevivalLease = typeof cfg.revivalLease === "object";
|
|
2046
2100
|
const launchBarrierToken = hasRevivalLease ? void 0 : runnerProcessInstanceId;
|
|
2047
|
-
const
|
|
2101
|
+
const launcher = cfg.launcher;
|
|
2102
|
+
const bootId = launcher ? void 0 : currentBootId();
|
|
2103
|
+
const launchConfig = { ...cfg, runnerProcessInstanceId, ...launchBarrierToken ? { launchBarrierToken } : {}, ...bootId ? { bootId } : {} };
|
|
2048
2104
|
writePrivateAtomicJson(cfgPath, launchConfig);
|
|
2049
2105
|
const command = binaryHost ?? nodeExecutable;
|
|
2050
2106
|
const launchForStartup = launchConfig;
|
|
@@ -2060,7 +2116,6 @@ function spawnRunner(cfg, suffix, cwd, initialStatus, initialStatusPath, launchP
|
|
|
2060
2116
|
if (startupAckPath) fs7.rmSync(startupAckPath, { force: true });
|
|
2061
2117
|
if (startupConfirmPath) fs7.rmSync(startupConfirmPath, { force: true });
|
|
2062
2118
|
if (startupProceedPath) fs7.rmSync(startupProceedPath, { force: true });
|
|
2063
|
-
const launcher = launchConfig.launcher;
|
|
2064
2119
|
const identityPath = launcher && launchBarrierToken && launchAsyncDir ? path6.join(launchAsyncDir, "runner-startup.json") : void 0;
|
|
2065
2120
|
if (identityPath) fs7.rmSync(identityPath, { force: true });
|
|
2066
2121
|
let runnerIdentity;
|
|
@@ -2132,7 +2187,7 @@ function spawnRunner(cfg, suffix, cwd, initialStatus, initialStatusPath, launchP
|
|
|
2132
2187
|
writePrivateAtomicJson(path6.join(asyncDir, "launcher-close.json"), { version: 1, runId, runnerProcessInstanceId, closeObservedAt: Date.now(), exitCode, signal, ...runnerIdentity ? { runnerPid: runnerIdentity.pid } : {} });
|
|
2133
2188
|
} catch {
|
|
2134
2189
|
}
|
|
2135
|
-
if (!runnerIdentity || runnerIdentity.pidNamespaceScope !== currentPidNamespaceScope() ||
|
|
2190
|
+
if (!runnerIdentity || runnerIdentity.pidNamespaceScope !== currentPidNamespaceScope() || checkRecordedPidLiveness(runnerIdentity) !== "dead") return;
|
|
2136
2191
|
}
|
|
2137
2192
|
finalizeProcessTerminal(asyncDir, runId, {
|
|
2138
2193
|
processInstanceId: runnerProcessInstanceId,
|
|
@@ -2188,7 +2243,7 @@ function spawnRunner(cfg, suffix, cwd, initialStatus, initialStatusPath, launchP
|
|
|
2188
2243
|
try {
|
|
2189
2244
|
writePrivateAtomicJson(initialStatusPath, {
|
|
2190
2245
|
...initialStatus,
|
|
2191
|
-
...launcher ? {} : { pid: proc.pid, pidNamespaceScope: currentPidNamespaceScope() },
|
|
2246
|
+
...launcher ? {} : { pid: proc.pid, pidNamespaceScope: currentPidNamespaceScope(), ...bootId ? { bootId } : {} },
|
|
2192
2247
|
processTerminal: { version: 1, state: "pending", runId: initialStatus.runId, runnerProcessInstanceId }
|
|
2193
2248
|
});
|
|
2194
2249
|
updateActiveRunIndex(path6.dirname(initialStatusPath), initialStatus.state, initialStatus.toolCallId);
|
|
@@ -2375,7 +2430,7 @@ function buildAsyncRunnerSteps(id, params) {
|
|
|
2375
2430
|
let machineEnv;
|
|
2376
2431
|
if (requestedMachine) {
|
|
2377
2432
|
try {
|
|
2378
|
-
const placement =
|
|
2433
|
+
const placement = resolveMachinePlacement({ machine: requestedMachine, cwd: runnerCwd, stepCwd: s.cwd ?? params.machineCwd });
|
|
2379
2434
|
machine = placement.machine;
|
|
2380
2435
|
machineEnv = placement.env;
|
|
2381
2436
|
} catch (error) {
|
|
@@ -2867,6 +2922,7 @@ function executeAsyncChain(id, params) {
|
|
|
2867
2922
|
}
|
|
2868
2923
|
const initialStatusAt = Date.now();
|
|
2869
2924
|
const initialCompletionOwnerId = ctx.completionOwnerId ?? currentCompletionOwnerId();
|
|
2925
|
+
const completionOwnerProcess = currentRecordedPid();
|
|
2870
2926
|
const launchParentSessionId = ctx.parentSessionId ?? ctx.currentSessionId;
|
|
2871
2927
|
try {
|
|
2872
2928
|
writeRetainedRequiredChildExtensions(asyncDir, params.requiredExtensions ?? ctx.childRuntime?.requiredExtensions ?? resolveRequiredChildExtensions(launchParentSessionId ?? void 0));
|
|
@@ -2891,6 +2947,7 @@ function executeAsyncChain(id, params) {
|
|
|
2891
2947
|
asyncDir,
|
|
2892
2948
|
sessionId: ctx.currentSessionId,
|
|
2893
2949
|
completionOwnerId: ctx.completionOwnerId ?? currentCompletionOwnerId(),
|
|
2950
|
+
completionOwnerProcess,
|
|
2894
2951
|
...capabilityCeiling ? { capabilityCeiling } : {},
|
|
2895
2952
|
piPackageRoot,
|
|
2896
2953
|
childSessionFactoryModule: childSessionFactoryModule(),
|
|
@@ -2932,6 +2989,7 @@ function executeAsyncChain(id, params) {
|
|
|
2932
2989
|
runId: id,
|
|
2933
2990
|
...ctx.currentSessionId ? { sessionId: ctx.currentSessionId } : {},
|
|
2934
2991
|
...initialCompletionOwnerId ? { completionOwnerId: initialCompletionOwnerId } : {},
|
|
2992
|
+
completionOwnerProcess,
|
|
2935
2993
|
mode: resultMode,
|
|
2936
2994
|
state: "running",
|
|
2937
2995
|
startedAt: initialStatusAt,
|
|
@@ -3148,7 +3206,7 @@ function executeAsyncSingle(id, params) {
|
|
|
3148
3206
|
let machineEnv;
|
|
3149
3207
|
if (requestedMachine) {
|
|
3150
3208
|
try {
|
|
3151
|
-
const placement =
|
|
3209
|
+
const placement = resolveMachinePlacement({ machine: requestedMachine, cwd: runnerCwd, stepCwd: params.machineCwd });
|
|
3152
3210
|
machine = placement.machine;
|
|
3153
3211
|
machineEnv = placement.env;
|
|
3154
3212
|
} catch (error) {
|
|
@@ -3404,6 +3462,7 @@ function executeAsyncSingle(id, params) {
|
|
|
3404
3462
|
let spawnResultOrPromise = {};
|
|
3405
3463
|
const initialStatusAt = Date.now();
|
|
3406
3464
|
const initialCompletionOwnerId = ctx.completionOwnerId ?? currentCompletionOwnerId();
|
|
3465
|
+
const completionOwnerProcess = currentRecordedPid();
|
|
3407
3466
|
const launchParentSessionId = ctx.parentSessionId ?? ctx.currentSessionId;
|
|
3408
3467
|
try {
|
|
3409
3468
|
spawnResultOrPromise = spawnRunner(
|
|
@@ -3485,6 +3544,7 @@ function executeAsyncSingle(id, params) {
|
|
|
3485
3544
|
asyncDir,
|
|
3486
3545
|
sessionId: ctx.currentSessionId,
|
|
3487
3546
|
completionOwnerId: ctx.completionOwnerId ?? currentCompletionOwnerId(),
|
|
3547
|
+
completionOwnerProcess,
|
|
3488
3548
|
...capabilityCeiling ? { capabilityCeiling } : {},
|
|
3489
3549
|
piPackageRoot,
|
|
3490
3550
|
childSessionFactoryModule: childSessionFactoryModule(),
|
|
@@ -3529,6 +3589,7 @@ function executeAsyncSingle(id, params) {
|
|
|
3529
3589
|
runId: id,
|
|
3530
3590
|
...ctx.currentSessionId ? { sessionId: ctx.currentSessionId } : {},
|
|
3531
3591
|
...initialCompletionOwnerId ? { completionOwnerId: initialCompletionOwnerId } : {},
|
|
3592
|
+
completionOwnerProcess,
|
|
3532
3593
|
mode: "single",
|
|
3533
3594
|
...params.toolCallId ? { toolCallId: params.toolCallId } : {},
|
|
3534
3595
|
state: "running",
|
|
@@ -3926,7 +3987,8 @@ var WORKFLOW_FENCE = /^```(?:js|javascript) workflow[ \t]*$/;
|
|
|
3926
3987
|
var PLAIN_JS_FENCE = /^```(?:js|javascript)[ \t]*$/;
|
|
3927
3988
|
var OPEN_FENCE = /^(`{3,}|~{3,})/;
|
|
3928
3989
|
var CLOSE_FENCE = /^(`{3,}|~{3,})[ \t]*$/;
|
|
3929
|
-
var
|
|
3990
|
+
var SUMMARY_NOTE = 'On some models, text written after a tool call in the same turn reaches the session only as a summary without code blocks, so for the rest of this turn write the script to a file and pass its path, such as workflow: "./script.js".';
|
|
3991
|
+
var FILE_FALLBACK = `If the block is in your reply: ${SUMMARY_NOTE}`;
|
|
3930
3992
|
function readReplyWorkflowScript(sessionManager, toolCallId) {
|
|
3931
3993
|
const branch = sessionManager.getBranch();
|
|
3932
3994
|
for (let index = branch.length - 1; index >= 0; index--) {
|
|
@@ -3942,7 +4004,7 @@ function readReplyWorkflowScript(sessionManager, toolCallId) {
|
|
|
3942
4004
|
function scriptFromReply(content) {
|
|
3943
4005
|
const replyCalls = content.filter((block) => block.type === "toolCall" && block.name === "subagent" && (block.arguments?.workflow === true || block.arguments?.workflow === "true")).length;
|
|
3944
4006
|
if (replyCalls > 1) return { error: `This reply has ${replyCalls} subagent calls with workflow: true; a reply can carry only one. Pass other scripts as workflow file paths.` };
|
|
3945
|
-
if (!content.some((block) => block.type === "text")) return { error:
|
|
4007
|
+
if (!content.some((block) => block.type === "text")) return { error: `The assistant message that issued this call has no text in the session, so the reply's visible text, including any \`\`\`js workflow block, never reached it. ${SUMMARY_NOTE}` };
|
|
3946
4008
|
const text = content.flatMap((block) => block.type === "text" && typeof block.text === "string" ? [block.text] : []).join("\n");
|
|
3947
4009
|
const { tagged, plain, unclosed } = workflowBlocks(text);
|
|
3948
4010
|
if (unclosed) return { error: "The script's fenced block in this reply is not closed." };
|
|
@@ -4535,25 +4597,6 @@ ${createDone}
|
|
|
4535
4597
|
}
|
|
4536
4598
|
});
|
|
4537
4599
|
}
|
|
4538
|
-
function resolvePiSessionId(sessionFile) {
|
|
4539
|
-
if (!sessionFile) return void 0;
|
|
4540
|
-
try {
|
|
4541
|
-
const fd = fs12.openSync(sessionFile, "r");
|
|
4542
|
-
try {
|
|
4543
|
-
const buffer = Buffer.alloc(16 * 1024);
|
|
4544
|
-
const bytes = fs12.readSync(fd, buffer, 0, buffer.length, 0);
|
|
4545
|
-
const line = buffer.toString("utf-8", 0, bytes).split("\n", 1)[0];
|
|
4546
|
-
if (!line) return void 0;
|
|
4547
|
-
const header = JSON.parse(line);
|
|
4548
|
-
if (header.type === "session" && typeof header.id === "string" && /^[A-Za-z0-9-]{8,}$/.test(header.id)) return header.id;
|
|
4549
|
-
return void 0;
|
|
4550
|
-
} finally {
|
|
4551
|
-
fs12.closeSync(fd);
|
|
4552
|
-
}
|
|
4553
|
-
} catch {
|
|
4554
|
-
return void 0;
|
|
4555
|
-
}
|
|
4556
|
-
}
|
|
4557
4600
|
function scheduleCleanup(nodeExecutable, paths) {
|
|
4558
4601
|
try {
|
|
4559
4602
|
const watchdog = spawn2(nodeExecutable, ["-e", ORCA_CLEANUP_WATCHDOG_SCRIPT, String(CLEANUP_DELAY_MS), ...paths], {
|
|
@@ -5576,7 +5619,8 @@ ${shared.acceptancePrompt}` : shared.systemPrompt,
|
|
|
5576
5619
|
};
|
|
5577
5620
|
return result2;
|
|
5578
5621
|
}
|
|
5579
|
-
const
|
|
5622
|
+
const mutationCwd = isRexLocalMachine(options.machine) ? options.machine.cwd : options.cwd ?? runtimeCwd;
|
|
5623
|
+
const mutationSnapshot = options.machine && !isRexLocalMachine(options.machine) ? { source: "tracked-files", trackedOnly: true, cwd: mutationCwd, dirtyFiles: [], fingerprints: {}, unavailable: "Local Git evidence is not authoritative for a pane-native remote run." } : snapshotTrackedMutations(mutationCwd);
|
|
5580
5624
|
let structuredOutputToolInvoked = false;
|
|
5581
5625
|
let structuredOutputMessageStartIndex;
|
|
5582
5626
|
let toolAvailabilityError;
|
|
@@ -6293,7 +6337,7 @@ ${shared.acceptancePrompt}` : shared.systemPrompt,
|
|
|
6293
6337
|
const toolDiagnosticError = diagnostic ? formatChildToolDiagnostic(diagnostic, { host: "parent" }) : void 0;
|
|
6294
6338
|
toolAvailabilityError = toolDiagnosticError;
|
|
6295
6339
|
result2.runtimeAcknowledgedExtensions = capture.runtimeAcknowledgedExtensions();
|
|
6296
|
-
if (session?.machineEvidence) result2.nativeMachine = { provider:
|
|
6340
|
+
if (session?.machineEvidence) result2.nativeMachine = { provider: session.machineEvidence.provider, machineId: session.machineEvidence.machineId, ...session.machineEvidence.initial ? { initialGit: session.machineEvidence.initial } : {}, ...session.machineEvidence.final ? { finalGit: session.machineEvidence.final } : {} };
|
|
6297
6341
|
let closeError = result2.error ?? toolDiagnosticError ?? assistantError;
|
|
6298
6342
|
const promptErrorMessage = promptError === void 0 ? void 0 : promptError instanceof Error ? promptError.message : String(promptError);
|
|
6299
6343
|
if (promptError !== void 0) childPromptFailed = true;
|
|
@@ -6500,7 +6544,7 @@ ${formatInheritedProviderDiagnostic({ agent: agent.name, model: launch.session.m
|
|
|
6500
6544
|
durationMs: progress.durationMs
|
|
6501
6545
|
};
|
|
6502
6546
|
const remoteGitChanged = result2.nativeMachine?.initialGit && result2.nativeMachine.finalGit ? result2.nativeMachine.initialGit.head !== result2.nativeMachine.finalGit.head || result2.nativeMachine.initialGit.dirty !== result2.nativeMachine.finalGit.dirty : void 0;
|
|
6503
|
-
const mutationEvidence = result2.nativeMachine ? { source: "tracked-files", trackedOnly: true, changedFiles: [], attemptedMutation: remoteGitChanged === true, ...remoteGitChanged === void 0 ? { unavailable: "Remote Git before/after evidence was incomplete." } : {} } : collectTrackedMutationEvidence(mutationSnapshot,
|
|
6547
|
+
const mutationEvidence = result2.nativeMachine && !isRexLocalMachine(options.machine) ? { source: "tracked-files", trackedOnly: true, changedFiles: [], attemptedMutation: remoteGitChanged === true, ...remoteGitChanged === void 0 ? { unavailable: "Remote Git before/after evidence was incomplete." } : {} } : collectTrackedMutationEvidence(mutationSnapshot, mutationCwd);
|
|
6504
6548
|
const acceptanceOutput = getFinalOutput(result2.messages ?? []);
|
|
6505
6549
|
const structuredText = result2.structuredOutput === void 0 ? void 0 : JSON.stringify(result2.structuredOutput, null, 2);
|
|
6506
6550
|
let fullOutput = stripAcceptanceReport(acceptanceOutput);
|
|
@@ -8350,10 +8394,7 @@ function errorMessage2(error) {
|
|
|
8350
8394
|
function runnerExitedWithoutResult(asyncDir, runId, resultPath) {
|
|
8351
8395
|
const status = readStatus(asyncDir);
|
|
8352
8396
|
if (!status || status.state !== "running" && status.state !== "queued" || typeof status.pid !== "number") return false;
|
|
8353
|
-
|
|
8354
|
-
if (status.pidNamespaceScope !== void 0 && status.pidNamespaceScope !== observedScope) return false;
|
|
8355
|
-
const pidScopeVerified = status.pidNamespaceScope !== void 0 && status.pidNamespaceScope === observedScope;
|
|
8356
|
-
if (checkPidLiveness(status.pid, void 0, pidScopeVerified) !== "dead") return false;
|
|
8397
|
+
if (checkRecordedPidLiveness({ pid: status.pid, pidNamespaceScope: status.pidNamespaceScope, bootId: status.bootId }) !== "dead") return false;
|
|
8357
8398
|
return !fs17.existsSync(resultPath) && !(status.sessionId && resultPayloadPathForSessionRun(asyncDir, status.sessionId, runId));
|
|
8358
8399
|
}
|
|
8359
8400
|
async function awaitExistingAsyncRun(asyncDir, runId, signal) {
|
|
@@ -8543,7 +8584,7 @@ function formatRememberedForegroundStatus(run) {
|
|
|
8543
8584
|
for (const child of run.children) {
|
|
8544
8585
|
const output = rememberedForegroundChildOutput(child).trim().split(/\r?\n/).find((line) => line.trim());
|
|
8545
8586
|
const parts = [
|
|
8546
|
-
`${child.index + 1}. ${child.sessionName?.trim() || child.agent} ${child
|
|
8587
|
+
`${child.index + 1}. ${child.sessionName?.trim() || child.agent} ${foregroundChildStateLabel(run, child)}`,
|
|
8547
8588
|
child.exitCode !== void 0 ? `exit ${child.exitCode}` : void 0,
|
|
8548
8589
|
child.detachedReason ? `detached: ${child.detachedReason}` : void 0,
|
|
8549
8590
|
child.acceptance ? `acceptance: ${child.acceptance.status}` : void 0,
|
|
@@ -10159,9 +10200,11 @@ function trimRememberedForegroundRuns(state) {
|
|
|
10159
10200
|
state.foregroundRuns.delete(oldestTerminal.runId);
|
|
10160
10201
|
}
|
|
10161
10202
|
}
|
|
10162
|
-
function
|
|
10203
|
+
function persistRememberedForegroundRun(state, runId) {
|
|
10204
|
+
const run = state.foregroundRuns?.get(runId);
|
|
10205
|
+
if (!run) return;
|
|
10163
10206
|
try {
|
|
10164
|
-
|
|
10207
|
+
persistForegroundRun(run);
|
|
10165
10208
|
} catch (error) {
|
|
10166
10209
|
console.error("Failed to persist foreground run history:", error);
|
|
10167
10210
|
}
|
|
@@ -10180,6 +10223,49 @@ function foregroundChildActivityFromProgress(progress) {
|
|
|
10180
10223
|
...progress?.toolCount !== void 0 ? { toolCount: progress.toolCount } : {}
|
|
10181
10224
|
};
|
|
10182
10225
|
}
|
|
10226
|
+
function rememberedForegroundChild(input, result2, index, status, updatedAt) {
|
|
10227
|
+
const resumeContract = omitUndefinedProperties({
|
|
10228
|
+
modelResponseAliases: input.modelResponseAliases,
|
|
10229
|
+
outputSchema: input.params.outputSchema,
|
|
10230
|
+
agentContract: input.params.agentContract,
|
|
10231
|
+
acceptance: input.params.acceptance,
|
|
10232
|
+
output: input.effectiveOutput,
|
|
10233
|
+
outputMode: input.effectiveOutputMode
|
|
10234
|
+
});
|
|
10235
|
+
return {
|
|
10236
|
+
agent: result2.agent,
|
|
10237
|
+
index,
|
|
10238
|
+
...result2.sessionName ? { sessionName: result2.sessionName } : {},
|
|
10239
|
+
...result2.context ? { context: result2.context } : {},
|
|
10240
|
+
status,
|
|
10241
|
+
...foregroundChildActivityFromProgress(result2.progress),
|
|
10242
|
+
updatedAt,
|
|
10243
|
+
...result2.exitCode !== void 0 ? { exitCode: result2.exitCode } : {},
|
|
10244
|
+
...result2.error ? { error: result2.error } : {},
|
|
10245
|
+
...result2.finalOutput ? { finalOutput: result2.finalOutput } : {},
|
|
10246
|
+
...result2.outputState ? { outputState: result2.outputState } : {},
|
|
10247
|
+
...result2.outputPartial ? { outputPartial: true } : {},
|
|
10248
|
+
...result2.outputMode ? { outputMode: result2.outputMode } : {},
|
|
10249
|
+
...result2.savedOutputPath ? { savedOutputPath: result2.savedOutputPath } : {},
|
|
10250
|
+
...result2.outputSaveError ? { outputSaveError: result2.outputSaveError } : {},
|
|
10251
|
+
...result2.sessionFile ? { sessionFile: result2.sessionFile } : {},
|
|
10252
|
+
...result2.model ? { model: result2.model } : {},
|
|
10253
|
+
...result2.thinking ? { thinking: result2.thinking } : {},
|
|
10254
|
+
...result2.artifactPaths ? { artifactPaths: result2.artifactPaths } : {},
|
|
10255
|
+
...result2.transcriptPath ? { transcriptPath: result2.transcriptPath } : {},
|
|
10256
|
+
...result2.transcriptError ? { transcriptError: result2.transcriptError } : {},
|
|
10257
|
+
...result2.detachedReason ? { detachedReason: result2.detachedReason } : {},
|
|
10258
|
+
...result2.acceptance ? { acceptance: result2.acceptance } : {},
|
|
10259
|
+
...Object.keys(resumeContract).length ? { resumeContract } : {},
|
|
10260
|
+
...result2.launchContractDigest ? { launchContractDigest: result2.launchContractDigest } : {},
|
|
10261
|
+
...input.extensionBindings ? { extensionBindings: input.extensionBindings } : {},
|
|
10262
|
+
...input.requiredExtensions?.length ? { requiredExtensions: input.requiredExtensions } : {},
|
|
10263
|
+
...result2.launchResolvedExtensions ? { launchResolvedExtensions: result2.launchResolvedExtensions } : {},
|
|
10264
|
+
...result2.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: result2.runtimeAcknowledgedExtensions } : {},
|
|
10265
|
+
...result2.capabilityCeiling ? { capabilityCeiling: result2.capabilityCeiling } : {},
|
|
10266
|
+
...result2.capabilityAudit ? { capabilityAudit: result2.capabilityAudit } : {}
|
|
10267
|
+
};
|
|
10268
|
+
}
|
|
10183
10269
|
function rememberForegroundRun(state, input) {
|
|
10184
10270
|
state.foregroundRuns ??= /* @__PURE__ */ new Map();
|
|
10185
10271
|
const previous = state.foregroundRuns.get(input.runId);
|
|
@@ -10191,61 +10277,38 @@ function rememberForegroundRun(state, input) {
|
|
|
10191
10277
|
...input.sessionId ? { sessionId: input.sessionId } : {},
|
|
10192
10278
|
updatedAt,
|
|
10193
10279
|
children: input.results.map((result2, index) => {
|
|
10194
|
-
const
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
agent: result2.agent,
|
|
10204
|
-
index,
|
|
10205
|
-
...result2.sessionName ? { sessionName: result2.sessionName } : {},
|
|
10206
|
-
...result2.context ? { context: result2.context } : {},
|
|
10207
|
-
status: resolveSubagentResultStatus(omitUndefinedProperties({
|
|
10208
|
-
exitCode: result2.exitCode,
|
|
10209
|
-
interrupted: result2.interrupted,
|
|
10210
|
-
detached: result2.detached,
|
|
10211
|
-
processSignal: result2.processSignal,
|
|
10212
|
-
timedOut: result2.timedOut,
|
|
10213
|
-
stopped: result2.stopped,
|
|
10214
|
-
turnBudgetExceeded: result2.turnBudgetExceeded
|
|
10215
|
-
})),
|
|
10216
|
-
...foregroundChildActivityFromProgress(result2.progress),
|
|
10217
|
-
updatedAt,
|
|
10218
|
-
...result2.exitCode !== void 0 ? { exitCode: result2.exitCode } : {},
|
|
10219
|
-
...result2.error ? { error: result2.error } : {},
|
|
10220
|
-
...result2.finalOutput ? { finalOutput: result2.finalOutput } : {},
|
|
10221
|
-
...result2.outputState ? { outputState: result2.outputState } : {},
|
|
10222
|
-
...result2.outputPartial ? { outputPartial: true } : {},
|
|
10223
|
-
...result2.outputMode ? { outputMode: result2.outputMode } : {},
|
|
10224
|
-
...result2.savedOutputPath ? { savedOutputPath: result2.savedOutputPath } : {},
|
|
10225
|
-
...result2.outputSaveError ? { outputSaveError: result2.outputSaveError } : {},
|
|
10226
|
-
...result2.sessionFile ? { sessionFile: result2.sessionFile } : {},
|
|
10227
|
-
...result2.model ? { model: result2.model } : {},
|
|
10228
|
-
...result2.thinking ? { thinking: result2.thinking } : {},
|
|
10229
|
-
...result2.artifactPaths ? { artifactPaths: result2.artifactPaths } : {},
|
|
10230
|
-
...result2.transcriptPath ? { transcriptPath: result2.transcriptPath } : {},
|
|
10231
|
-
...result2.transcriptError ? { transcriptError: result2.transcriptError } : {},
|
|
10232
|
-
...result2.detachedReason ? { detachedReason: result2.detachedReason } : {},
|
|
10233
|
-
...result2.acceptance ? { acceptance: result2.acceptance } : {},
|
|
10234
|
-
...Object.keys(resumeContract).length ? { resumeContract } : {},
|
|
10235
|
-
...result2.launchContractDigest ? { launchContractDigest: result2.launchContractDigest } : {},
|
|
10236
|
-
...input.extensionBindings ? { extensionBindings: input.extensionBindings } : {},
|
|
10237
|
-
...input.requiredExtensions?.length ? { requiredExtensions: input.requiredExtensions } : {},
|
|
10238
|
-
...result2.launchResolvedExtensions ? { launchResolvedExtensions: result2.launchResolvedExtensions } : {},
|
|
10239
|
-
...result2.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: result2.runtimeAcknowledgedExtensions } : {},
|
|
10240
|
-
...result2.capabilityCeiling ? { capabilityCeiling: result2.capabilityCeiling } : {},
|
|
10241
|
-
...result2.capabilityAudit ? { capabilityAudit: result2.capabilityAudit } : {}
|
|
10242
|
-
};
|
|
10280
|
+
const child = rememberedForegroundChild(input, result2, index, resolveSubagentResultStatus(omitUndefinedProperties({
|
|
10281
|
+
exitCode: result2.exitCode,
|
|
10282
|
+
interrupted: result2.interrupted,
|
|
10283
|
+
detached: result2.detached,
|
|
10284
|
+
processSignal: result2.processSignal,
|
|
10285
|
+
timedOut: result2.timedOut,
|
|
10286
|
+
stopped: result2.stopped,
|
|
10287
|
+
turnBudgetExceeded: result2.turnBudgetExceeded
|
|
10288
|
+
})), updatedAt);
|
|
10243
10289
|
const recovered = previous?.children[index];
|
|
10244
10290
|
return child.status === "detached" && recovered && recovered.status !== "detached" ? recovered : child;
|
|
10245
10291
|
})
|
|
10246
10292
|
});
|
|
10247
10293
|
trimRememberedForegroundRuns(state);
|
|
10248
|
-
|
|
10294
|
+
persistRememberedForegroundRun(state, input.runId);
|
|
10295
|
+
}
|
|
10296
|
+
function rememberRunningForegroundRun(input) {
|
|
10297
|
+
const updatedAt = Date.now();
|
|
10298
|
+
try {
|
|
10299
|
+
persistForegroundRun({
|
|
10300
|
+
runId: input.runId,
|
|
10301
|
+
mode: "single",
|
|
10302
|
+
cwd: input.cwd,
|
|
10303
|
+
...input.sessionId ? { sessionId: input.sessionId } : {},
|
|
10304
|
+
updatedAt,
|
|
10305
|
+
children: [rememberedForegroundChild(input, input.child, 0, "running", updatedAt)],
|
|
10306
|
+
owner: currentRecordedPid(),
|
|
10307
|
+
...input.parentWorkflowRunId ? { parentWorkflowRunId: input.parentWorkflowRunId } : {}
|
|
10308
|
+
});
|
|
10309
|
+
} catch (error) {
|
|
10310
|
+
console.error("Failed to persist running foreground run:", error);
|
|
10311
|
+
}
|
|
10249
10312
|
}
|
|
10250
10313
|
function applyControlEventToRememberedForegroundRun(state, event) {
|
|
10251
10314
|
const run = state.foregroundRuns?.get(event.runId);
|
|
@@ -10320,7 +10383,7 @@ function updateRememberedForegroundChild(state, input) {
|
|
|
10320
10383
|
...input.result.capabilityAudit ? { capabilityAudit: input.result.capabilityAudit } : {}
|
|
10321
10384
|
});
|
|
10322
10385
|
trimRememberedForegroundRuns(state);
|
|
10323
|
-
|
|
10386
|
+
persistRememberedForegroundRun(state, input.runId);
|
|
10324
10387
|
const output = getSingleResultOutput(input.result).trim();
|
|
10325
10388
|
const success = terminalStatus === "completed";
|
|
10326
10389
|
const summary = !success && input.result.error ? `${input.result.error}${output ? `
|
|
@@ -12501,9 +12564,9 @@ function importWorkflowAwaitedChildResult(completed, options) {
|
|
|
12501
12564
|
}
|
|
12502
12565
|
};
|
|
12503
12566
|
}
|
|
12504
|
-
function stopAwaitedAsyncChildOnAbort(signal, state, runId, asyncDir, kill,
|
|
12567
|
+
function stopAwaitedAsyncChildOnAbort(signal, state, runId, asyncDir, kill, reattached = false) {
|
|
12505
12568
|
const stopOnAbort = () => {
|
|
12506
|
-
if (!workflowStopCause(signal?.reason)) stopAsyncRun(state, runId, kill, { asyncDir, resolvedId: runId, ...
|
|
12569
|
+
if (!workflowStopCause(signal?.reason)) stopAsyncRun(state, runId, kill, { asyncDir, resolvedId: runId, ...reattached ? { reattachedRunId: runId } : {} });
|
|
12507
12570
|
};
|
|
12508
12571
|
if (signal?.aborted) stopOnAbort();
|
|
12509
12572
|
else signal?.addEventListener("abort", stopOnAbort, { once: true });
|
|
@@ -13016,7 +13079,7 @@ async function runSinglePath(data, deps) {
|
|
|
13016
13079
|
if (requestedMachine) {
|
|
13017
13080
|
try {
|
|
13018
13081
|
assertRequiredChildExtensionsAdmitted([requiredExtensions], { agent: agentConfig.name, runnerType: agentConfig.runner?.type, machine: requestedMachine });
|
|
13019
|
-
foregroundMachine =
|
|
13082
|
+
foregroundMachine = resolveMachinePlacement({ machine: requestedMachine, cwd: ctx.cwd, stepCwd: params.machineCwd }).machine;
|
|
13020
13083
|
} catch (error) {
|
|
13021
13084
|
return toExecutionErrorResult(params, error instanceof Error ? error : new Error(String(error)), data.contextPolicy.contextSummary);
|
|
13022
13085
|
}
|
|
@@ -13209,6 +13272,13 @@ async function runSinglePath(data, deps) {
|
|
|
13209
13272
|
onUpdate(update);
|
|
13210
13273
|
} : void 0;
|
|
13211
13274
|
const deadlineAt = data.deadlineAt ?? (data.timeoutMs !== void 0 ? Date.now() + data.timeoutMs : void 0);
|
|
13275
|
+
const discardRunningRecord = () => {
|
|
13276
|
+
try {
|
|
13277
|
+
discardRunningForegroundRun(runId);
|
|
13278
|
+
} catch (discardError) {
|
|
13279
|
+
console.error("Failed to discard running foreground run:", discardError);
|
|
13280
|
+
}
|
|
13281
|
+
};
|
|
13212
13282
|
let r;
|
|
13213
13283
|
let resolveDetachedWorkflowChild;
|
|
13214
13284
|
const detachedWorkflowChild = params.workflowAwaitDetached === true ? new Promise((resolve10) => {
|
|
@@ -13216,6 +13286,27 @@ async function runSinglePath(data, deps) {
|
|
|
13216
13286
|
}) : void 0;
|
|
13217
13287
|
try {
|
|
13218
13288
|
const childSessionFile = sessionFileForTask(params.agent, 0, modelOverride, modelOverrideFromParent, modelOrigin);
|
|
13289
|
+
rememberRunningForegroundRun({
|
|
13290
|
+
modelResponseAliases,
|
|
13291
|
+
runId,
|
|
13292
|
+
mode: "single",
|
|
13293
|
+
cwd: singleCwd,
|
|
13294
|
+
sessionId: data.parentSessionId,
|
|
13295
|
+
params,
|
|
13296
|
+
effectiveOutput,
|
|
13297
|
+
effectiveOutputMode,
|
|
13298
|
+
extensionBindings: params.extensionBindings,
|
|
13299
|
+
requiredExtensions,
|
|
13300
|
+
child: omitUndefinedProperties({
|
|
13301
|
+
agent: params.agent,
|
|
13302
|
+
context: shouldForkAgent(contextPolicy, params.agent) ? "fork" : "fresh",
|
|
13303
|
+
sessionFile: childSessionFile,
|
|
13304
|
+
model: modelOverride,
|
|
13305
|
+
thinking: resolveEffectiveThinking(modelOverride, thinkingOverrideForTask()),
|
|
13306
|
+
capabilityCeiling: data.capabilityCeiling
|
|
13307
|
+
}),
|
|
13308
|
+
parentWorkflowRunId: params.workflowParentRunId ?? foregroundControl?.parentWorkflowRunId
|
|
13309
|
+
});
|
|
13219
13310
|
const launched = await runSync(ctx.cwd, agents, params.agent, task, compactOptional({
|
|
13220
13311
|
machine: foregroundMachine,
|
|
13221
13312
|
parentProviderRegistry: ctx.modelRegistry,
|
|
@@ -13291,7 +13382,12 @@ async function runSinglePath(data, deps) {
|
|
|
13291
13382
|
}
|
|
13292
13383
|
try {
|
|
13293
13384
|
if (worktreeSetup) {
|
|
13294
|
-
|
|
13385
|
+
try {
|
|
13386
|
+
await finalizeSingleWorktreeHandoff({ worktreeSetup, artifactsDir, runId, cwd: sourceCwd, agent: params.agent, result: result2, workflowKey: params.workflowKey, lane });
|
|
13387
|
+
} catch (error) {
|
|
13388
|
+
discardRunningRecord();
|
|
13389
|
+
throw error;
|
|
13390
|
+
}
|
|
13295
13391
|
}
|
|
13296
13392
|
try {
|
|
13297
13393
|
updateRememberedForegroundChild(deps.state, { runId, mode: "single", cwd: singleCwd, sessionId: data.parentSessionId, index: 0, result: result2, events: deps.pi.events, notify: true });
|
|
@@ -13340,6 +13436,7 @@ async function runSinglePath(data, deps) {
|
|
|
13340
13436
|
}
|
|
13341
13437
|
r = launched.detached && detachedWorkflowChild ? await detachedWorkflowChild : launched;
|
|
13342
13438
|
} catch (error) {
|
|
13439
|
+
discardRunningRecord();
|
|
13343
13440
|
await cleanupSingleWorktree();
|
|
13344
13441
|
throw error;
|
|
13345
13442
|
} finally {
|
|
@@ -13350,7 +13447,12 @@ async function runSinglePath(data, deps) {
|
|
|
13350
13447
|
}
|
|
13351
13448
|
let worktreeHandoff;
|
|
13352
13449
|
if (worktreeSetup) {
|
|
13353
|
-
|
|
13450
|
+
try {
|
|
13451
|
+
worktreeHandoff = r.detached ? { suffix: pendingHandoff ? formatParallelHandoffReference(pendingHandoff) : "", reference: pendingHandoff } : await finalizeSingleWorktreeHandoff({ worktreeSetup, artifactsDir, runId, cwd: sourceCwd, agent: params.agent, result: r, workflowKey: params.workflowKey, lane });
|
|
13452
|
+
} catch (error) {
|
|
13453
|
+
discardRunningRecord();
|
|
13454
|
+
throw error;
|
|
13455
|
+
}
|
|
13354
13456
|
}
|
|
13355
13457
|
if (r.progress) allProgress.push(r.progress);
|
|
13356
13458
|
if (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);
|
|
@@ -14029,6 +14131,14 @@ function createScheduledOwnerState(source, ownerSessionId, ctx) {
|
|
|
14029
14131
|
workflowChildStops: /* @__PURE__ */ new Map()
|
|
14030
14132
|
};
|
|
14031
14133
|
}
|
|
14134
|
+
function savedWorkflowLaunchParams(params) {
|
|
14135
|
+
const { reuseFrom: _reuseFrom, scheduleOrigin: _scheduleOrigin, resumeOrigin: _resumeOrigin, ...saved } = params;
|
|
14136
|
+
return saved;
|
|
14137
|
+
}
|
|
14138
|
+
function workflowLaunchRecord(launch, cwd, scriptDigest) {
|
|
14139
|
+
if (launch.source === "structured") return { version: 1, source: "structured", scriptDigest };
|
|
14140
|
+
return { version: 1, source: launch.source, params: { ...launch.params, cwd }, scriptDigest };
|
|
14141
|
+
}
|
|
14032
14142
|
function createSubagentExecutor(deps) {
|
|
14033
14143
|
const executorDeps = deps;
|
|
14034
14144
|
const delegatedThinkingOverrides = /* @__PURE__ */ new WeakMap();
|
|
@@ -14036,6 +14146,8 @@ function createSubagentExecutor(deps) {
|
|
|
14036
14146
|
const delegatedExecutions = /* @__PURE__ */ new WeakSet();
|
|
14037
14147
|
const publicExecutions = /* @__PURE__ */ new WeakSet();
|
|
14038
14148
|
const workflowResourcePermits = /* @__PURE__ */ new WeakMap();
|
|
14149
|
+
const publicWorkflowLaunches = /* @__PURE__ */ new WeakMap();
|
|
14150
|
+
const workflowResumeLaunches = /* @__PURE__ */ new WeakMap();
|
|
14039
14151
|
const workflowPermitContexts = /* @__PURE__ */ new WeakMap();
|
|
14040
14152
|
const warnedArtifactPackageDirs = /* @__PURE__ */ new Set();
|
|
14041
14153
|
const scheduledOwnerExecutors = /* @__PURE__ */ new Map();
|
|
@@ -14051,7 +14163,13 @@ function createSubagentExecutor(deps) {
|
|
|
14051
14163
|
if (error) throw new Error(error);
|
|
14052
14164
|
}
|
|
14053
14165
|
};
|
|
14054
|
-
const
|
|
14166
|
+
const pendingReuseClaimReleases = /* @__PURE__ */ new WeakMap();
|
|
14167
|
+
const execute = (...args) => executeRequest(...args).finally(() => {
|
|
14168
|
+
const releaseReuseClaim = pendingReuseClaimReleases.get(args[1]);
|
|
14169
|
+
pendingReuseClaimReleases.delete(args[1]);
|
|
14170
|
+
releaseReuseClaim?.();
|
|
14171
|
+
});
|
|
14172
|
+
const executeRequest = async (_id, params, signal, onUpdate, ctx, preserveActiveSession = false, parentModelOverride) => {
|
|
14055
14173
|
const projectScopeError = projectScopeTrustError(params, ctx);
|
|
14056
14174
|
if (projectScopeError) return projectScopeError;
|
|
14057
14175
|
const deps2 = withSessionProjectTrust(executorDeps, ctx);
|
|
@@ -14063,6 +14181,8 @@ function createSubagentExecutor(deps) {
|
|
|
14063
14181
|
const delegatedExecution = delegatedExecutions.has(params);
|
|
14064
14182
|
const publicExecution = publicExecutions.has(params);
|
|
14065
14183
|
const workflowResourcePermit = workflowResourcePermits.get(params);
|
|
14184
|
+
const workflowResumeLaunch = workflowResumeLaunches.get(params);
|
|
14185
|
+
const publicWorkflowLaunch = publicWorkflowLaunches.get(params);
|
|
14066
14186
|
const workflowPermitContext = workflowPermitContexts.get(params);
|
|
14067
14187
|
const delegatedWorkflowPermit = workflowPermitContext && "root" in workflowPermitContext ? workflowPermitContext.root : void 0;
|
|
14068
14188
|
const workflowChildPermitLaunch = workflowPermitContext && "child" in workflowPermitContext ? workflowPermitContext.child : void 0;
|
|
@@ -14180,13 +14300,14 @@ function createSubagentExecutor(deps) {
|
|
|
14180
14300
|
const workflowDepth = checkSubagentDepth(deps2.config.maxSubagentDepth, deps2.childRuntime).depth;
|
|
14181
14301
|
const asyncWorkflow = requestParams.async !== false;
|
|
14182
14302
|
const topLevelAsyncWorkflow = asyncWorkflow && workflowDepth === 0 && !inheritedNestedRoute(deps2) && !requestParams.workflowParentRunId;
|
|
14183
|
-
const workflowRunId = asyncWorkflow ? randomUUID5() : void 0;
|
|
14303
|
+
const workflowRunId = asyncWorkflow ? workflowResumeLaunch?.presetRunId ?? randomUUID5() : void 0;
|
|
14184
14304
|
if (requestParams.reuseFrom !== void 0 && !topLevelAsyncWorkflow) {
|
|
14185
14305
|
return { content: [{ type: "text", text: "options.reuseFrom requires an async top-level workflow." }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14186
14306
|
}
|
|
14187
|
-
let
|
|
14307
|
+
let workflowReuseSource;
|
|
14188
14308
|
try {
|
|
14189
|
-
if (requestParams.reuseFrom !== void 0)
|
|
14309
|
+
if (requestParams.reuseFrom !== void 0) workflowReuseSource = readNamedWorkflowReuseSource(DIRS.async, requestParams.reuseFrom, workflowScriptDigest(requestParams.workflowScript), workflowCwd, workflowResumeLaunch?.presetRunId);
|
|
14310
|
+
else if (workflowRunId) workflowReuseSource = findWorkflowReuseSource(DIRS.async, resolveCurrentSessionId(ctx.sessionManager), workflowScriptDigest(requestParams.workflowScript), workflowArgsDigest);
|
|
14190
14311
|
} catch (error) {
|
|
14191
14312
|
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14192
14313
|
}
|
|
@@ -14256,17 +14377,37 @@ function createSubagentExecutor(deps) {
|
|
|
14256
14377
|
const completionOwnerId = deps2.state.completionOwnerId ?? currentCompletionOwnerId();
|
|
14257
14378
|
deps2.state.completionOwnerId = completionOwnerId;
|
|
14258
14379
|
const workflowScriptSourceDigest = workflowScriptDigest(requestParams.workflowScript);
|
|
14259
|
-
const workflowReuseSource = namedWorkflowReuseSource ?? findWorkflowReuseSource(DIRS.async, currentSessionId, workflowScriptSourceDigest, workflowArgsDigest);
|
|
14260
14380
|
const workflowRunEvidence = { ...workflowArgsEvidence, scriptDigest: workflowScriptSourceDigest };
|
|
14261
14381
|
if (workflowReuseSource) workflowRunEvidence.reusedFrom = workflowReuseSource.runId;
|
|
14382
|
+
if (workflowResumeLaunch) workflowRunEvidence.resumeOrigin = workflowResumeLaunch.resumeOrigin;
|
|
14262
14383
|
const workflowJournalFingerprints = /* @__PURE__ */ new Map();
|
|
14384
|
+
const storageFailure = (error) => {
|
|
14385
|
+
workflowCapacity?.rollback();
|
|
14386
|
+
return { content: [{ type: "text", text: `Failed to create async workflow storage: ${error instanceof Error ? error.message : String(error)}` }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14387
|
+
};
|
|
14388
|
+
if (workflowReuseSource) {
|
|
14389
|
+
const reuseSourceDir = path19.join(DIRS.async, workflowReuseSource.runId);
|
|
14390
|
+
let claim;
|
|
14391
|
+
try {
|
|
14392
|
+
claim = claimWorkflowResume(reuseSourceDir, { newRunId: workflowRunId, trigger: "reuse" });
|
|
14393
|
+
} catch (error) {
|
|
14394
|
+
return storageFailure(error);
|
|
14395
|
+
}
|
|
14396
|
+
if (claim.kind !== "owner") {
|
|
14397
|
+
workflowCapacity?.rollback();
|
|
14398
|
+
return { content: [{ type: "text", text: claimedWorkflowRunRefusal(workflowReuseSource.runId, claim, requestParams.reuseFrom !== void 0) }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14399
|
+
}
|
|
14400
|
+
pendingReuseClaimReleases.set(params, () => {
|
|
14401
|
+
if (!fs21.existsSync(statusPath)) releaseWorkflowResumeClaim(reuseSourceDir, workflowRunId);
|
|
14402
|
+
});
|
|
14403
|
+
}
|
|
14263
14404
|
try {
|
|
14264
14405
|
fs21.mkdirSync(asyncDir, { recursive: true });
|
|
14265
14406
|
writeRunFanoutBudgetDescriptor(asyncDir, workflowFanoutBudget);
|
|
14407
|
+
if (topLevelAsyncWorkflow && publicWorkflowLaunch) writeWorkflowLaunchRecord(asyncDir, workflowLaunchRecord(publicWorkflowLaunch, workflowCwd, workflowScriptSourceDigest));
|
|
14266
14408
|
fs21.mkdirSync(DIRS.results, { recursive: true });
|
|
14267
14409
|
} catch (error) {
|
|
14268
|
-
|
|
14269
|
-
return { content: [{ type: "text", text: `Failed to create async workflow storage: ${error instanceof Error ? error.message : String(error)}` }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14410
|
+
return storageFailure(error);
|
|
14270
14411
|
}
|
|
14271
14412
|
const controller = new AbortController();
|
|
14272
14413
|
deps2.state.workflowControllers ??= /* @__PURE__ */ new Map();
|
|
@@ -14287,7 +14428,7 @@ function createSubagentExecutor(deps) {
|
|
|
14287
14428
|
cwd: workflowCwd,
|
|
14288
14429
|
...workflowSessionRoot ? { sessionRoot: workflowSessionRoot } : {},
|
|
14289
14430
|
...requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {},
|
|
14290
|
-
|
|
14431
|
+
...currentRecordedPid(),
|
|
14291
14432
|
...workflowCapabilityCeiling2 ? { admissionCapabilityCeiling: workflowCapabilityCeiling2 } : {},
|
|
14292
14433
|
steps: [],
|
|
14293
14434
|
...workflowPreflight ? { preflight: workflowPreflight } : {},
|
|
@@ -14876,7 +15017,7 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
14876
15017
|
const priorAsyncDir = path19.join(DIRS.async, priorRunId);
|
|
14877
15018
|
appendWorkflowChildJournal(asyncDir, { type: "start", key, fingerprint: journalFingerprint, runId: priorRunId });
|
|
14878
15019
|
recordReusedWorkflowChild(key, priorRunId);
|
|
14879
|
-
const stopListener = stopAwaitedAsyncChildOnAbort(workflowSignal, deps2.state, priorRunId, priorAsyncDir, deps2.kill,
|
|
15020
|
+
const stopListener = stopAwaitedAsyncChildOnAbort(workflowSignal, deps2.state, priorRunId, priorAsyncDir, deps2.kill, true);
|
|
14880
15021
|
const reattached = await awaitExistingAsyncRun(priorAsyncDir, priorRunId, workflowSignal).finally(stopListener.remove);
|
|
14881
15022
|
const claimedPath = reattached.status === "settled" ? claimWorkflowAwaitedResult(priorAsyncDir, workflowRunId, { ...reattached.result.importedPublication, runId: priorRunId }) : void 0;
|
|
14882
15023
|
if (reattached.status === "settled" && claimedPath) {
|
|
@@ -15052,7 +15193,7 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
15052
15193
|
if (promoted) status = promoted;
|
|
15053
15194
|
}
|
|
15054
15195
|
const errorPreview = status.error && status.error.length > 1e3 ? `${status.error.slice(0, 1e3)}\u2026 (truncated; full error: ${statusPath} (error))` : status.error;
|
|
15055
|
-
const terminalSummary = `${status.state === "complete" ? "Workflow completed after detached child finished." : errorPreview ?? (pauseForDetached ? "Workflow paused." : "Workflow failed.")}${stopCause ? ` ${
|
|
15196
|
+
const terminalSummary = `${status.state === "complete" ? "Workflow completed after detached child finished." : errorPreview ?? (pauseForDetached ? "Workflow paused." : "Workflow failed.")}${stopCause ? ` ${WORKFLOW_RUNTIME_REPLACED_STOP_NOTICE}` : ""}${workflowOutputPathMappingSummary2(partial.children)}${finalPreflightWarnings.length ? ` ${finalPreflightWarnings.join(" ")}` : ""}`;
|
|
15056
15197
|
const outputWarning = writeWorkflowAggregateOutput(workflowAggregateOutputPath2, terminalSummary, producedChildOutputPaths2);
|
|
15057
15198
|
const resultSummary = appendWorkflowOutputWarning(terminalSummary, outputWarning);
|
|
15058
15199
|
const receiptState = status.state === "complete" ? "complete" : status.state === "paused" ? "paused" : status.state === "stopped" ? "stopped" : "failed";
|
|
@@ -15115,6 +15256,7 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
15115
15256
|
let liveWorkflow = { trace: [], emits: [], console: [], ...workflowResource ? { resource: workflowResource.provenance } : {} };
|
|
15116
15257
|
const childProgress = /* @__PURE__ */ new Map();
|
|
15117
15258
|
const childLaunches = /* @__PURE__ */ new Map();
|
|
15259
|
+
const blockingWorkflowChildren = /* @__PURE__ */ new Set();
|
|
15118
15260
|
let activityTimer;
|
|
15119
15261
|
let lastProgressAt = 0;
|
|
15120
15262
|
let workflowProgressClosed = false;
|
|
@@ -15202,6 +15344,10 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
15202
15344
|
workflowPermitContexts.set(childRequest, { child: { permit: delegatedWorkflowPermit, workflowRunId: foregroundWorkflowRunId, childKey: key } });
|
|
15203
15345
|
}
|
|
15204
15346
|
workflowLaunchObservers.set(childRequest, (launch) => {
|
|
15347
|
+
if (launch.async && launch.runId && (childRequest.workflowAwaitAsync === true || childRequest.action === "resume")) {
|
|
15348
|
+
(deps2.state.blockingWorkflowChildren ??= /* @__PURE__ */ new Set()).add(launch.runId);
|
|
15349
|
+
blockingWorkflowChildren.add(launch.runId);
|
|
15350
|
+
}
|
|
15205
15351
|
childLaunches.set(key, { agent: launch.agent, ...launch.runId ? { runId: launch.runId } : {} });
|
|
15206
15352
|
try {
|
|
15207
15353
|
sendWorkflowProgress();
|
|
@@ -15323,6 +15469,7 @@ ${partial.console.map((entry) => `[${entry.level}] ${entry.text}`).join("\n")}`]
|
|
|
15323
15469
|
}, workflowFanoutBudget));
|
|
15324
15470
|
} finally {
|
|
15325
15471
|
workflowProgressClosed = true;
|
|
15472
|
+
for (const runId2 of blockingWorkflowChildren) deps2.state.blockingWorkflowChildren?.delete(runId2);
|
|
15326
15473
|
if (activityTimer) clearTimeout(activityTimer);
|
|
15327
15474
|
childProgress.clear();
|
|
15328
15475
|
}
|
|
@@ -15745,6 +15892,8 @@ ${item.text}` } : item)
|
|
|
15745
15892
|
return withBudget(inspectSubagentStatus(paramsWithResolvedCwd, omitUndefinedProperties({ state: deps2.state, nested: nestedScope, sessionRoots, abandonedSlotReleaseAfterMs: resolveAbandonedSlotReleaseAfterMs(deps2.config.capacity?.abandonedSlotReleaseAfterMs) })));
|
|
15746
15893
|
}
|
|
15747
15894
|
if (action === "resume") {
|
|
15895
|
+
const workflowResumeSourceId = workflowResumeTargetId(DIRS.async, paramsWithResolvedCwd);
|
|
15896
|
+
if (workflowResumeSourceId) return resumeWorkflowById(_id, workflowResumeSourceId, signal, ctx);
|
|
15748
15897
|
return resumeAsyncRun(omitUndefinedProperties({
|
|
15749
15898
|
params: paramsWithResolvedCwd,
|
|
15750
15899
|
requestCwd,
|
|
@@ -16570,6 +16719,8 @@ ${item.text}` } : item)
|
|
|
16570
16719
|
const workflow = publicParams.workflow;
|
|
16571
16720
|
const errorResult = (text) => Promise.resolve({ content: [{ type: "text", text }], isError: true, details: { mode: publicParams.action ? "management" : "workflow", results: [] } });
|
|
16572
16721
|
const scriptTextHint = " A workflow string is a named workflow resource or a script file path. To run script text, write it in one ```js workflow block in the same reply and call subagent({ workflow: true }).";
|
|
16722
|
+
let workflowLaunch;
|
|
16723
|
+
const workflowResumeLaunch = workflowResumeLaunches.get(params);
|
|
16573
16724
|
if (publicParams.tasks !== void 0 || publicParams.chain !== void 0) {
|
|
16574
16725
|
const kind = publicParams.tasks !== void 0 ? "tasks" : "chain";
|
|
16575
16726
|
const resolved = resolveStructuredWorkflowResource({ kind, steps: publicParams[kind], task: publicParams.task });
|
|
@@ -16577,10 +16728,20 @@ ${item.text}` } : item)
|
|
|
16577
16728
|
const { tasks: _tasks, chain: _chain, task: _task, ...withoutStructuredInput } = publicParams;
|
|
16578
16729
|
publicParams = { ...withoutStructuredInput, workflowScript: resolved.resource.script };
|
|
16579
16730
|
workflowResourcePermits.set(publicParams, resolved.resource.permit);
|
|
16731
|
+
workflowLaunch = { source: "structured" };
|
|
16580
16732
|
} else if (typeof workflow === "string" && !isWorkflowScriptPath(workflow)) {
|
|
16581
16733
|
const resolved = resolveWorkflowResource(workflow, publicParams.args, ctx.sessionManager.getSessionId() ?? void 0);
|
|
16734
|
+
if (workflowResumeLaunch && !resolved.ok) {
|
|
16735
|
+
workflowResumeLaunch.refusal = { code: "authority", reason: `workflow resource '${workflow}' can no longer be resolved: ${resolved.error}` };
|
|
16736
|
+
return errorResult(workflowResumeLaunch.refusal.reason);
|
|
16737
|
+
}
|
|
16738
|
+
if (workflowResumeLaunch && resolved.ok && workflowScriptDigest(resolved.resource.script) !== workflowResumeLaunch.expectedScriptDigest) {
|
|
16739
|
+
workflowResumeLaunch.refusal = { code: "digest", reason: `workflow resource '${workflow}' changed since the run started` };
|
|
16740
|
+
return errorResult(workflowResumeLaunch.refusal.reason);
|
|
16741
|
+
}
|
|
16582
16742
|
if (!resolved.ok) return Promise.resolve({ content: [{ type: "text", text: resolved.error + scriptTextHint }], isError: true, details: { mode: "workflow", results: [] } });
|
|
16583
16743
|
const { workflow: _workflow, args: _args, ...withoutResourceInput } = publicParams;
|
|
16744
|
+
workflowLaunch = { source: "resource", params: savedWorkflowLaunchParams(publicParams) };
|
|
16584
16745
|
publicParams = { ...withoutResourceInput, workflowScript: resolved.resource.script };
|
|
16585
16746
|
workflowResourcePermits.set(publicParams, resolved.resource.permit);
|
|
16586
16747
|
} else if (workflow !== void 0 || publicParams.workflowScript !== void 0) {
|
|
@@ -16595,10 +16756,56 @@ ${item.text}` } : item)
|
|
|
16595
16756
|
}
|
|
16596
16757
|
const { workflow: _workflow, ...withoutWorkflowSource } = publicParams;
|
|
16597
16758
|
publicParams = { ...withoutWorkflowSource, workflowScript, args: "error" in normalizedArgs ? publicParams.args : deepFreezeWorkflowArgs(normalizedArgs.args) };
|
|
16759
|
+
workflowLaunch = { source: "script", params: savedWorkflowLaunchParams(publicParams) };
|
|
16598
16760
|
}
|
|
16761
|
+
if (workflowLaunch && publicParams.action === void 0) publicWorkflowLaunches.set(publicParams, workflowLaunch);
|
|
16762
|
+
if (workflowResumeLaunch) workflowResumeLaunches.set(publicParams, workflowResumeLaunch);
|
|
16599
16763
|
publicExecutions.add(publicParams);
|
|
16600
16764
|
return executeWithSingleDispatchGuard(id, publicParams, signal, onUpdate, ctx);
|
|
16601
16765
|
};
|
|
16766
|
+
const executeWorkflowResume = async (id, prepared, signal, ctx) => {
|
|
16767
|
+
const params = { ...prepared.params };
|
|
16768
|
+
const launch = { presetRunId: prepared.newRunId, resumeOrigin: prepared.resumeOrigin, expectedScriptDigest: prepared.expectedScriptDigest };
|
|
16769
|
+
workflowResumeLaunches.set(params, launch);
|
|
16770
|
+
let result2;
|
|
16771
|
+
try {
|
|
16772
|
+
result2 = await executePublic(id, params, signal, void 0, ctx);
|
|
16773
|
+
} catch (error) {
|
|
16774
|
+
result2 = { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "workflow", results: [] } };
|
|
16775
|
+
}
|
|
16776
|
+
if (resumedRunStarted(prepared.sourceAsyncDir, prepared.newRunId)) return { result: result2, launched: true };
|
|
16777
|
+
const firstText = result2.content.find((block) => block.type === "text")?.text ?? "no result";
|
|
16778
|
+
const refusal = launch.refusal ? workflowResumeRefusal(launch.refusal.code, launch.refusal.reason, prepared.sourceRunId) : result2.details?.activeAsyncCapacity ? workflowResumeRefusal("capacity", `capacity refused: ${firstText}`, prepared.sourceRunId) : workflowResumeRefusal("launch-failed", `launch failed: ${firstText}`, prepared.sourceRunId);
|
|
16779
|
+
releaseWorkflowResumeClaim(prepared.sourceAsyncDir, prepared.newRunId);
|
|
16780
|
+
if (prepared.trigger === "auto") {
|
|
16781
|
+
try {
|
|
16782
|
+
recordWorkflowResumeRefusal(prepared.sourceAsyncDir, { reason: refusal.reason, byHand: refusal.byHand, newRunId: prepared.newRunId });
|
|
16783
|
+
} catch (error) {
|
|
16784
|
+
console.error(`Failed to record why workflow ${prepared.sourceRunId} was not resumed:`, error);
|
|
16785
|
+
}
|
|
16786
|
+
}
|
|
16787
|
+
return { result: result2, launched: false, refusal };
|
|
16788
|
+
};
|
|
16789
|
+
const resumeWorkflowById = async (id, sourceRunId, signal, ctx) => {
|
|
16790
|
+
const refused = (text) => ({ content: [{ type: "text", text }], isError: true, details: { mode: "management", results: [] } });
|
|
16791
|
+
let preparation;
|
|
16792
|
+
try {
|
|
16793
|
+
preparation = prepareWorkflowResume({ asyncDirRoot: DIRS.async, sourceRunId, trigger: "manual", now: Date.now(), currentSessionId: resolveCurrentSessionId(ctx.sessionManager) });
|
|
16794
|
+
} catch (error) {
|
|
16795
|
+
return refused(`Cannot resume workflow '${sourceRunId}': ${error instanceof Error ? error.message : String(error)}`);
|
|
16796
|
+
}
|
|
16797
|
+
if (!preparation.ok) return refused(manualWorkflowResumeRefusalText(sourceRunId, preparation));
|
|
16798
|
+
const outcome = await executeWorkflowResume(id, preparation.prepared, signal, ctx);
|
|
16799
|
+
if (!outcome.launched) return refused(manualWorkflowResumeRefusalText(sourceRunId, outcome.refusal));
|
|
16800
|
+
const resumedLine = `Resumed workflow '${sourceRunId}' as ${preparation.prepared.newRunId}.`;
|
|
16801
|
+
const textIndex = outcome.result.content.findIndex((block) => block.type === "text");
|
|
16802
|
+
const content = [...outcome.result.content];
|
|
16803
|
+
const first = content[textIndex];
|
|
16804
|
+
if (first?.type === "text") content[textIndex] = { ...first, text: `${resumedLine}
|
|
16805
|
+
${first.text}` };
|
|
16806
|
+
else content.unshift({ type: "text", text: resumedLine });
|
|
16807
|
+
return { ...outcome.result, content };
|
|
16808
|
+
};
|
|
16602
16809
|
const executeDelegated = async (id, params, signal, onUpdate, ctx) => {
|
|
16603
16810
|
const disabledFeatureError = disabledFeatureResult(params);
|
|
16604
16811
|
if (disabledFeatureError) return disabledFeatureError;
|
|
@@ -16637,7 +16844,7 @@ ${item.text}` } : item)
|
|
|
16637
16844
|
if (!ownerId) return;
|
|
16638
16845
|
for (const owner of scheduledOwnerExecutors.get(ownerId)?.values() ?? []) yield owner.state;
|
|
16639
16846
|
}
|
|
16640
|
-
return { execute: executeWithSingleDispatchGuard, executePublic, executeDelegated, executeScheduled, getCurrentSupervisorOwnerStates };
|
|
16847
|
+
return { execute: executeWithSingleDispatchGuard, executePublic, executeDelegated, executeScheduled, executeWorkflowResume, getCurrentSupervisorOwnerStates };
|
|
16641
16848
|
}
|
|
16642
16849
|
export {
|
|
16643
16850
|
DEFAULT_ASYNC_TIMEOUT_MS,
|