pi-subagents 0.81.0 → 0.82.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 +38 -0
- package/bundle/agents.js +3 -3
- package/bundle/child-tool-plan.js +2 -2
- package/bundle/{chunk-LSRUTHT7.js → chunk-43SCHIMD.js} +1 -1
- package/bundle/{chunk-G5DKFLLI.js → chunk-4SDU2BZX.js} +15 -10
- package/bundle/{chunk-V2JWDB5U.js → chunk-52UBALJL.js} +2 -2
- package/bundle/{chunk-3DC5KBVP.js → chunk-5TYMSZX3.js} +1 -1
- package/bundle/{chunk-CEKS3TFO.js → chunk-7IVSUMQQ.js} +6 -6
- package/bundle/{chunk-KSWQVGDW.js → chunk-7PCKZHR5.js} +225 -18
- package/bundle/{chunk-563BHAZ5.js → chunk-7YMXOYEU.js} +33 -25
- package/bundle/{chunk-XMFLCKMQ.js → chunk-B5EKXDHE.js} +336 -130
- package/bundle/{chunk-ZBC44JJ3.js → chunk-CIZQXJ5Q.js} +22 -9
- package/bundle/{chunk-L5ZHE4L4.js → chunk-GC4DSPMH.js} +4 -4
- package/bundle/{chunk-ARRKBB2B.js → chunk-GJECHSAR.js} +2 -2
- package/bundle/{chunk-2ZSNH26H.js → chunk-M2CTFYT3.js} +7 -7
- package/bundle/{chunk-TUWLXTAM.js → chunk-MHZ4G23A.js} +681 -320
- package/bundle/{chunk-WSBNENFS.js → chunk-NGGAFDL6.js} +14 -4
- package/bundle/{chunk-VJHOELQP.js → chunk-NRQ75MGH.js} +160 -78
- package/bundle/{chunk-BJN5LUQY.js → chunk-OYF6AFDY.js} +1 -1
- package/bundle/{chunk-EYNJ6VL6.js → chunk-PLCCBLPY.js} +2 -2
- package/bundle/{chunk-74RT5YQE.js → chunk-RMQFMMAT.js} +123 -33
- package/bundle/{chunk-V6MR5TOQ.js → chunk-SIJ4S3EN.js} +25 -19
- package/bundle/{chunk-NNLASTQE.js → chunk-VH5OAWVG.js} +19 -5
- package/bundle/{chunk-BPS2AGBZ.js → chunk-W2SZ22EM.js} +93 -52
- package/bundle/{chunk-V3BIUPLU.js → chunk-WVD4UEL4.js} +256 -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-ZLINIYTP.js} +497 -272
- package/bundle/{chunk-2XYWN7QJ.js → chunk-ZQGSDHL6.js} +2 -2
- 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 +31 -0
- 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/pi-subagents/references/execution-controls.md +5 -4
- 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/schemas.js +3 -3
- 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 +2 -0
- package/src/runs/background/async-status.js +21 -2
- 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 +1 -0
- package/src/runs/background/terminal-run-index.js +4 -2
- 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 +24 -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
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
projectRuntimeAcknowledgedExtensions,
|
|
4
4
|
registerSubagentPromptBoundary,
|
|
5
5
|
registerSubagentPromptRuntime
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GC4DSPMH.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-7IVSUMQQ.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-ZLINIYTP.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-W2SZ22EM.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-7PCKZHR5.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-VH5OAWVG.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-NGGAFDL6.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-NRQ75MGH.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",
|
|
@@ -4535,25 +4596,6 @@ ${createDone}
|
|
|
4535
4596
|
}
|
|
4536
4597
|
});
|
|
4537
4598
|
}
|
|
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
4599
|
function scheduleCleanup(nodeExecutable, paths) {
|
|
4558
4600
|
try {
|
|
4559
4601
|
const watchdog = spawn2(nodeExecutable, ["-e", ORCA_CLEANUP_WATCHDOG_SCRIPT, String(CLEANUP_DELAY_MS), ...paths], {
|
|
@@ -5576,7 +5618,8 @@ ${shared.acceptancePrompt}` : shared.systemPrompt,
|
|
|
5576
5618
|
};
|
|
5577
5619
|
return result2;
|
|
5578
5620
|
}
|
|
5579
|
-
const
|
|
5621
|
+
const mutationCwd = isRexLocalMachine(options.machine) ? options.machine.cwd : options.cwd ?? runtimeCwd;
|
|
5622
|
+
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
5623
|
let structuredOutputToolInvoked = false;
|
|
5581
5624
|
let structuredOutputMessageStartIndex;
|
|
5582
5625
|
let toolAvailabilityError;
|
|
@@ -6293,7 +6336,7 @@ ${shared.acceptancePrompt}` : shared.systemPrompt,
|
|
|
6293
6336
|
const toolDiagnosticError = diagnostic ? formatChildToolDiagnostic(diagnostic, { host: "parent" }) : void 0;
|
|
6294
6337
|
toolAvailabilityError = toolDiagnosticError;
|
|
6295
6338
|
result2.runtimeAcknowledgedExtensions = capture.runtimeAcknowledgedExtensions();
|
|
6296
|
-
if (session?.machineEvidence) result2.nativeMachine = { provider:
|
|
6339
|
+
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
6340
|
let closeError = result2.error ?? toolDiagnosticError ?? assistantError;
|
|
6298
6341
|
const promptErrorMessage = promptError === void 0 ? void 0 : promptError instanceof Error ? promptError.message : String(promptError);
|
|
6299
6342
|
if (promptError !== void 0) childPromptFailed = true;
|
|
@@ -6500,7 +6543,7 @@ ${formatInheritedProviderDiagnostic({ agent: agent.name, model: launch.session.m
|
|
|
6500
6543
|
durationMs: progress.durationMs
|
|
6501
6544
|
};
|
|
6502
6545
|
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,
|
|
6546
|
+
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
6547
|
const acceptanceOutput = getFinalOutput(result2.messages ?? []);
|
|
6505
6548
|
const structuredText = result2.structuredOutput === void 0 ? void 0 : JSON.stringify(result2.structuredOutput, null, 2);
|
|
6506
6549
|
let fullOutput = stripAcceptanceReport(acceptanceOutput);
|
|
@@ -8350,10 +8393,7 @@ function errorMessage2(error) {
|
|
|
8350
8393
|
function runnerExitedWithoutResult(asyncDir, runId, resultPath) {
|
|
8351
8394
|
const status = readStatus(asyncDir);
|
|
8352
8395
|
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;
|
|
8396
|
+
if (checkRecordedPidLiveness({ pid: status.pid, pidNamespaceScope: status.pidNamespaceScope, bootId: status.bootId }) !== "dead") return false;
|
|
8357
8397
|
return !fs17.existsSync(resultPath) && !(status.sessionId && resultPayloadPathForSessionRun(asyncDir, status.sessionId, runId));
|
|
8358
8398
|
}
|
|
8359
8399
|
async function awaitExistingAsyncRun(asyncDir, runId, signal) {
|
|
@@ -8543,7 +8583,7 @@ function formatRememberedForegroundStatus(run) {
|
|
|
8543
8583
|
for (const child of run.children) {
|
|
8544
8584
|
const output = rememberedForegroundChildOutput(child).trim().split(/\r?\n/).find((line) => line.trim());
|
|
8545
8585
|
const parts = [
|
|
8546
|
-
`${child.index + 1}. ${child.sessionName?.trim() || child.agent} ${child
|
|
8586
|
+
`${child.index + 1}. ${child.sessionName?.trim() || child.agent} ${foregroundChildStateLabel(run, child)}`,
|
|
8547
8587
|
child.exitCode !== void 0 ? `exit ${child.exitCode}` : void 0,
|
|
8548
8588
|
child.detachedReason ? `detached: ${child.detachedReason}` : void 0,
|
|
8549
8589
|
child.acceptance ? `acceptance: ${child.acceptance.status}` : void 0,
|
|
@@ -10159,9 +10199,11 @@ function trimRememberedForegroundRuns(state) {
|
|
|
10159
10199
|
state.foregroundRuns.delete(oldestTerminal.runId);
|
|
10160
10200
|
}
|
|
10161
10201
|
}
|
|
10162
|
-
function
|
|
10202
|
+
function persistRememberedForegroundRun(state, runId) {
|
|
10203
|
+
const run = state.foregroundRuns?.get(runId);
|
|
10204
|
+
if (!run) return;
|
|
10163
10205
|
try {
|
|
10164
|
-
|
|
10206
|
+
persistForegroundRun(run);
|
|
10165
10207
|
} catch (error) {
|
|
10166
10208
|
console.error("Failed to persist foreground run history:", error);
|
|
10167
10209
|
}
|
|
@@ -10180,6 +10222,49 @@ function foregroundChildActivityFromProgress(progress) {
|
|
|
10180
10222
|
...progress?.toolCount !== void 0 ? { toolCount: progress.toolCount } : {}
|
|
10181
10223
|
};
|
|
10182
10224
|
}
|
|
10225
|
+
function rememberedForegroundChild(input, result2, index, status, updatedAt) {
|
|
10226
|
+
const resumeContract = omitUndefinedProperties({
|
|
10227
|
+
modelResponseAliases: input.modelResponseAliases,
|
|
10228
|
+
outputSchema: input.params.outputSchema,
|
|
10229
|
+
agentContract: input.params.agentContract,
|
|
10230
|
+
acceptance: input.params.acceptance,
|
|
10231
|
+
output: input.effectiveOutput,
|
|
10232
|
+
outputMode: input.effectiveOutputMode
|
|
10233
|
+
});
|
|
10234
|
+
return {
|
|
10235
|
+
agent: result2.agent,
|
|
10236
|
+
index,
|
|
10237
|
+
...result2.sessionName ? { sessionName: result2.sessionName } : {},
|
|
10238
|
+
...result2.context ? { context: result2.context } : {},
|
|
10239
|
+
status,
|
|
10240
|
+
...foregroundChildActivityFromProgress(result2.progress),
|
|
10241
|
+
updatedAt,
|
|
10242
|
+
...result2.exitCode !== void 0 ? { exitCode: result2.exitCode } : {},
|
|
10243
|
+
...result2.error ? { error: result2.error } : {},
|
|
10244
|
+
...result2.finalOutput ? { finalOutput: result2.finalOutput } : {},
|
|
10245
|
+
...result2.outputState ? { outputState: result2.outputState } : {},
|
|
10246
|
+
...result2.outputPartial ? { outputPartial: true } : {},
|
|
10247
|
+
...result2.outputMode ? { outputMode: result2.outputMode } : {},
|
|
10248
|
+
...result2.savedOutputPath ? { savedOutputPath: result2.savedOutputPath } : {},
|
|
10249
|
+
...result2.outputSaveError ? { outputSaveError: result2.outputSaveError } : {},
|
|
10250
|
+
...result2.sessionFile ? { sessionFile: result2.sessionFile } : {},
|
|
10251
|
+
...result2.model ? { model: result2.model } : {},
|
|
10252
|
+
...result2.thinking ? { thinking: result2.thinking } : {},
|
|
10253
|
+
...result2.artifactPaths ? { artifactPaths: result2.artifactPaths } : {},
|
|
10254
|
+
...result2.transcriptPath ? { transcriptPath: result2.transcriptPath } : {},
|
|
10255
|
+
...result2.transcriptError ? { transcriptError: result2.transcriptError } : {},
|
|
10256
|
+
...result2.detachedReason ? { detachedReason: result2.detachedReason } : {},
|
|
10257
|
+
...result2.acceptance ? { acceptance: result2.acceptance } : {},
|
|
10258
|
+
...Object.keys(resumeContract).length ? { resumeContract } : {},
|
|
10259
|
+
...result2.launchContractDigest ? { launchContractDigest: result2.launchContractDigest } : {},
|
|
10260
|
+
...input.extensionBindings ? { extensionBindings: input.extensionBindings } : {},
|
|
10261
|
+
...input.requiredExtensions?.length ? { requiredExtensions: input.requiredExtensions } : {},
|
|
10262
|
+
...result2.launchResolvedExtensions ? { launchResolvedExtensions: result2.launchResolvedExtensions } : {},
|
|
10263
|
+
...result2.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: result2.runtimeAcknowledgedExtensions } : {},
|
|
10264
|
+
...result2.capabilityCeiling ? { capabilityCeiling: result2.capabilityCeiling } : {},
|
|
10265
|
+
...result2.capabilityAudit ? { capabilityAudit: result2.capabilityAudit } : {}
|
|
10266
|
+
};
|
|
10267
|
+
}
|
|
10183
10268
|
function rememberForegroundRun(state, input) {
|
|
10184
10269
|
state.foregroundRuns ??= /* @__PURE__ */ new Map();
|
|
10185
10270
|
const previous = state.foregroundRuns.get(input.runId);
|
|
@@ -10191,61 +10276,38 @@ function rememberForegroundRun(state, input) {
|
|
|
10191
10276
|
...input.sessionId ? { sessionId: input.sessionId } : {},
|
|
10192
10277
|
updatedAt,
|
|
10193
10278
|
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
|
-
};
|
|
10279
|
+
const child = rememberedForegroundChild(input, result2, index, resolveSubagentResultStatus(omitUndefinedProperties({
|
|
10280
|
+
exitCode: result2.exitCode,
|
|
10281
|
+
interrupted: result2.interrupted,
|
|
10282
|
+
detached: result2.detached,
|
|
10283
|
+
processSignal: result2.processSignal,
|
|
10284
|
+
timedOut: result2.timedOut,
|
|
10285
|
+
stopped: result2.stopped,
|
|
10286
|
+
turnBudgetExceeded: result2.turnBudgetExceeded
|
|
10287
|
+
})), updatedAt);
|
|
10243
10288
|
const recovered = previous?.children[index];
|
|
10244
10289
|
return child.status === "detached" && recovered && recovered.status !== "detached" ? recovered : child;
|
|
10245
10290
|
})
|
|
10246
10291
|
});
|
|
10247
10292
|
trimRememberedForegroundRuns(state);
|
|
10248
|
-
|
|
10293
|
+
persistRememberedForegroundRun(state, input.runId);
|
|
10294
|
+
}
|
|
10295
|
+
function rememberRunningForegroundRun(input) {
|
|
10296
|
+
const updatedAt = Date.now();
|
|
10297
|
+
try {
|
|
10298
|
+
persistForegroundRun({
|
|
10299
|
+
runId: input.runId,
|
|
10300
|
+
mode: "single",
|
|
10301
|
+
cwd: input.cwd,
|
|
10302
|
+
...input.sessionId ? { sessionId: input.sessionId } : {},
|
|
10303
|
+
updatedAt,
|
|
10304
|
+
children: [rememberedForegroundChild(input, input.child, 0, "running", updatedAt)],
|
|
10305
|
+
owner: currentRecordedPid(),
|
|
10306
|
+
...input.parentWorkflowRunId ? { parentWorkflowRunId: input.parentWorkflowRunId } : {}
|
|
10307
|
+
});
|
|
10308
|
+
} catch (error) {
|
|
10309
|
+
console.error("Failed to persist running foreground run:", error);
|
|
10310
|
+
}
|
|
10249
10311
|
}
|
|
10250
10312
|
function applyControlEventToRememberedForegroundRun(state, event) {
|
|
10251
10313
|
const run = state.foregroundRuns?.get(event.runId);
|
|
@@ -10320,7 +10382,7 @@ function updateRememberedForegroundChild(state, input) {
|
|
|
10320
10382
|
...input.result.capabilityAudit ? { capabilityAudit: input.result.capabilityAudit } : {}
|
|
10321
10383
|
});
|
|
10322
10384
|
trimRememberedForegroundRuns(state);
|
|
10323
|
-
|
|
10385
|
+
persistRememberedForegroundRun(state, input.runId);
|
|
10324
10386
|
const output = getSingleResultOutput(input.result).trim();
|
|
10325
10387
|
const success = terminalStatus === "completed";
|
|
10326
10388
|
const summary = !success && input.result.error ? `${input.result.error}${output ? `
|
|
@@ -12501,9 +12563,9 @@ function importWorkflowAwaitedChildResult(completed, options) {
|
|
|
12501
12563
|
}
|
|
12502
12564
|
};
|
|
12503
12565
|
}
|
|
12504
|
-
function stopAwaitedAsyncChildOnAbort(signal, state, runId, asyncDir, kill,
|
|
12566
|
+
function stopAwaitedAsyncChildOnAbort(signal, state, runId, asyncDir, kill, reattached = false) {
|
|
12505
12567
|
const stopOnAbort = () => {
|
|
12506
|
-
if (!workflowStopCause(signal?.reason)) stopAsyncRun(state, runId, kill, { asyncDir, resolvedId: runId, ...
|
|
12568
|
+
if (!workflowStopCause(signal?.reason)) stopAsyncRun(state, runId, kill, { asyncDir, resolvedId: runId, ...reattached ? { reattachedRunId: runId } : {} });
|
|
12507
12569
|
};
|
|
12508
12570
|
if (signal?.aborted) stopOnAbort();
|
|
12509
12571
|
else signal?.addEventListener("abort", stopOnAbort, { once: true });
|
|
@@ -13016,7 +13078,7 @@ async function runSinglePath(data, deps) {
|
|
|
13016
13078
|
if (requestedMachine) {
|
|
13017
13079
|
try {
|
|
13018
13080
|
assertRequiredChildExtensionsAdmitted([requiredExtensions], { agent: agentConfig.name, runnerType: agentConfig.runner?.type, machine: requestedMachine });
|
|
13019
|
-
foregroundMachine =
|
|
13081
|
+
foregroundMachine = resolveMachinePlacement({ machine: requestedMachine, cwd: ctx.cwd, stepCwd: params.machineCwd }).machine;
|
|
13020
13082
|
} catch (error) {
|
|
13021
13083
|
return toExecutionErrorResult(params, error instanceof Error ? error : new Error(String(error)), data.contextPolicy.contextSummary);
|
|
13022
13084
|
}
|
|
@@ -13209,6 +13271,13 @@ async function runSinglePath(data, deps) {
|
|
|
13209
13271
|
onUpdate(update);
|
|
13210
13272
|
} : void 0;
|
|
13211
13273
|
const deadlineAt = data.deadlineAt ?? (data.timeoutMs !== void 0 ? Date.now() + data.timeoutMs : void 0);
|
|
13274
|
+
const discardRunningRecord = () => {
|
|
13275
|
+
try {
|
|
13276
|
+
discardRunningForegroundRun(runId);
|
|
13277
|
+
} catch (discardError) {
|
|
13278
|
+
console.error("Failed to discard running foreground run:", discardError);
|
|
13279
|
+
}
|
|
13280
|
+
};
|
|
13212
13281
|
let r;
|
|
13213
13282
|
let resolveDetachedWorkflowChild;
|
|
13214
13283
|
const detachedWorkflowChild = params.workflowAwaitDetached === true ? new Promise((resolve10) => {
|
|
@@ -13216,6 +13285,27 @@ async function runSinglePath(data, deps) {
|
|
|
13216
13285
|
}) : void 0;
|
|
13217
13286
|
try {
|
|
13218
13287
|
const childSessionFile = sessionFileForTask(params.agent, 0, modelOverride, modelOverrideFromParent, modelOrigin);
|
|
13288
|
+
rememberRunningForegroundRun({
|
|
13289
|
+
modelResponseAliases,
|
|
13290
|
+
runId,
|
|
13291
|
+
mode: "single",
|
|
13292
|
+
cwd: singleCwd,
|
|
13293
|
+
sessionId: data.parentSessionId,
|
|
13294
|
+
params,
|
|
13295
|
+
effectiveOutput,
|
|
13296
|
+
effectiveOutputMode,
|
|
13297
|
+
extensionBindings: params.extensionBindings,
|
|
13298
|
+
requiredExtensions,
|
|
13299
|
+
child: omitUndefinedProperties({
|
|
13300
|
+
agent: params.agent,
|
|
13301
|
+
context: shouldForkAgent(contextPolicy, params.agent) ? "fork" : "fresh",
|
|
13302
|
+
sessionFile: childSessionFile,
|
|
13303
|
+
model: modelOverride,
|
|
13304
|
+
thinking: resolveEffectiveThinking(modelOverride, thinkingOverrideForTask()),
|
|
13305
|
+
capabilityCeiling: data.capabilityCeiling
|
|
13306
|
+
}),
|
|
13307
|
+
parentWorkflowRunId: params.workflowParentRunId ?? foregroundControl?.parentWorkflowRunId
|
|
13308
|
+
});
|
|
13219
13309
|
const launched = await runSync(ctx.cwd, agents, params.agent, task, compactOptional({
|
|
13220
13310
|
machine: foregroundMachine,
|
|
13221
13311
|
parentProviderRegistry: ctx.modelRegistry,
|
|
@@ -13291,7 +13381,12 @@ async function runSinglePath(data, deps) {
|
|
|
13291
13381
|
}
|
|
13292
13382
|
try {
|
|
13293
13383
|
if (worktreeSetup) {
|
|
13294
|
-
|
|
13384
|
+
try {
|
|
13385
|
+
await finalizeSingleWorktreeHandoff({ worktreeSetup, artifactsDir, runId, cwd: sourceCwd, agent: params.agent, result: result2, workflowKey: params.workflowKey, lane });
|
|
13386
|
+
} catch (error) {
|
|
13387
|
+
discardRunningRecord();
|
|
13388
|
+
throw error;
|
|
13389
|
+
}
|
|
13295
13390
|
}
|
|
13296
13391
|
try {
|
|
13297
13392
|
updateRememberedForegroundChild(deps.state, { runId, mode: "single", cwd: singleCwd, sessionId: data.parentSessionId, index: 0, result: result2, events: deps.pi.events, notify: true });
|
|
@@ -13340,6 +13435,7 @@ async function runSinglePath(data, deps) {
|
|
|
13340
13435
|
}
|
|
13341
13436
|
r = launched.detached && detachedWorkflowChild ? await detachedWorkflowChild : launched;
|
|
13342
13437
|
} catch (error) {
|
|
13438
|
+
discardRunningRecord();
|
|
13343
13439
|
await cleanupSingleWorktree();
|
|
13344
13440
|
throw error;
|
|
13345
13441
|
} finally {
|
|
@@ -13350,7 +13446,12 @@ async function runSinglePath(data, deps) {
|
|
|
13350
13446
|
}
|
|
13351
13447
|
let worktreeHandoff;
|
|
13352
13448
|
if (worktreeSetup) {
|
|
13353
|
-
|
|
13449
|
+
try {
|
|
13450
|
+
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 });
|
|
13451
|
+
} catch (error) {
|
|
13452
|
+
discardRunningRecord();
|
|
13453
|
+
throw error;
|
|
13454
|
+
}
|
|
13354
13455
|
}
|
|
13355
13456
|
if (r.progress) allProgress.push(r.progress);
|
|
13356
13457
|
if (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);
|
|
@@ -14029,6 +14130,14 @@ function createScheduledOwnerState(source, ownerSessionId, ctx) {
|
|
|
14029
14130
|
workflowChildStops: /* @__PURE__ */ new Map()
|
|
14030
14131
|
};
|
|
14031
14132
|
}
|
|
14133
|
+
function savedWorkflowLaunchParams(params) {
|
|
14134
|
+
const { reuseFrom: _reuseFrom, scheduleOrigin: _scheduleOrigin, resumeOrigin: _resumeOrigin, ...saved } = params;
|
|
14135
|
+
return saved;
|
|
14136
|
+
}
|
|
14137
|
+
function workflowLaunchRecord(launch, cwd, scriptDigest) {
|
|
14138
|
+
if (launch.source === "structured") return { version: 1, source: "structured", scriptDigest };
|
|
14139
|
+
return { version: 1, source: launch.source, params: { ...launch.params, cwd }, scriptDigest };
|
|
14140
|
+
}
|
|
14032
14141
|
function createSubagentExecutor(deps) {
|
|
14033
14142
|
const executorDeps = deps;
|
|
14034
14143
|
const delegatedThinkingOverrides = /* @__PURE__ */ new WeakMap();
|
|
@@ -14036,6 +14145,8 @@ function createSubagentExecutor(deps) {
|
|
|
14036
14145
|
const delegatedExecutions = /* @__PURE__ */ new WeakSet();
|
|
14037
14146
|
const publicExecutions = /* @__PURE__ */ new WeakSet();
|
|
14038
14147
|
const workflowResourcePermits = /* @__PURE__ */ new WeakMap();
|
|
14148
|
+
const publicWorkflowLaunches = /* @__PURE__ */ new WeakMap();
|
|
14149
|
+
const workflowResumeLaunches = /* @__PURE__ */ new WeakMap();
|
|
14039
14150
|
const workflowPermitContexts = /* @__PURE__ */ new WeakMap();
|
|
14040
14151
|
const warnedArtifactPackageDirs = /* @__PURE__ */ new Set();
|
|
14041
14152
|
const scheduledOwnerExecutors = /* @__PURE__ */ new Map();
|
|
@@ -14051,7 +14162,13 @@ function createSubagentExecutor(deps) {
|
|
|
14051
14162
|
if (error) throw new Error(error);
|
|
14052
14163
|
}
|
|
14053
14164
|
};
|
|
14054
|
-
const
|
|
14165
|
+
const pendingReuseClaimReleases = /* @__PURE__ */ new WeakMap();
|
|
14166
|
+
const execute = (...args) => executeRequest(...args).finally(() => {
|
|
14167
|
+
const releaseReuseClaim = pendingReuseClaimReleases.get(args[1]);
|
|
14168
|
+
pendingReuseClaimReleases.delete(args[1]);
|
|
14169
|
+
releaseReuseClaim?.();
|
|
14170
|
+
});
|
|
14171
|
+
const executeRequest = async (_id, params, signal, onUpdate, ctx, preserveActiveSession = false, parentModelOverride) => {
|
|
14055
14172
|
const projectScopeError = projectScopeTrustError(params, ctx);
|
|
14056
14173
|
if (projectScopeError) return projectScopeError;
|
|
14057
14174
|
const deps2 = withSessionProjectTrust(executorDeps, ctx);
|
|
@@ -14063,6 +14180,8 @@ function createSubagentExecutor(deps) {
|
|
|
14063
14180
|
const delegatedExecution = delegatedExecutions.has(params);
|
|
14064
14181
|
const publicExecution = publicExecutions.has(params);
|
|
14065
14182
|
const workflowResourcePermit = workflowResourcePermits.get(params);
|
|
14183
|
+
const workflowResumeLaunch = workflowResumeLaunches.get(params);
|
|
14184
|
+
const publicWorkflowLaunch = publicWorkflowLaunches.get(params);
|
|
14066
14185
|
const workflowPermitContext = workflowPermitContexts.get(params);
|
|
14067
14186
|
const delegatedWorkflowPermit = workflowPermitContext && "root" in workflowPermitContext ? workflowPermitContext.root : void 0;
|
|
14068
14187
|
const workflowChildPermitLaunch = workflowPermitContext && "child" in workflowPermitContext ? workflowPermitContext.child : void 0;
|
|
@@ -14180,13 +14299,14 @@ function createSubagentExecutor(deps) {
|
|
|
14180
14299
|
const workflowDepth = checkSubagentDepth(deps2.config.maxSubagentDepth, deps2.childRuntime).depth;
|
|
14181
14300
|
const asyncWorkflow = requestParams.async !== false;
|
|
14182
14301
|
const topLevelAsyncWorkflow = asyncWorkflow && workflowDepth === 0 && !inheritedNestedRoute(deps2) && !requestParams.workflowParentRunId;
|
|
14183
|
-
const workflowRunId = asyncWorkflow ? randomUUID5() : void 0;
|
|
14302
|
+
const workflowRunId = asyncWorkflow ? workflowResumeLaunch?.presetRunId ?? randomUUID5() : void 0;
|
|
14184
14303
|
if (requestParams.reuseFrom !== void 0 && !topLevelAsyncWorkflow) {
|
|
14185
14304
|
return { content: [{ type: "text", text: "options.reuseFrom requires an async top-level workflow." }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14186
14305
|
}
|
|
14187
|
-
let
|
|
14306
|
+
let workflowReuseSource;
|
|
14188
14307
|
try {
|
|
14189
|
-
if (requestParams.reuseFrom !== void 0)
|
|
14308
|
+
if (requestParams.reuseFrom !== void 0) workflowReuseSource = readNamedWorkflowReuseSource(DIRS.async, requestParams.reuseFrom, workflowScriptDigest(requestParams.workflowScript), workflowCwd, workflowResumeLaunch?.presetRunId);
|
|
14309
|
+
else if (workflowRunId) workflowReuseSource = findWorkflowReuseSource(DIRS.async, resolveCurrentSessionId(ctx.sessionManager), workflowScriptDigest(requestParams.workflowScript), workflowArgsDigest);
|
|
14190
14310
|
} catch (error) {
|
|
14191
14311
|
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14192
14312
|
}
|
|
@@ -14256,17 +14376,37 @@ function createSubagentExecutor(deps) {
|
|
|
14256
14376
|
const completionOwnerId = deps2.state.completionOwnerId ?? currentCompletionOwnerId();
|
|
14257
14377
|
deps2.state.completionOwnerId = completionOwnerId;
|
|
14258
14378
|
const workflowScriptSourceDigest = workflowScriptDigest(requestParams.workflowScript);
|
|
14259
|
-
const workflowReuseSource = namedWorkflowReuseSource ?? findWorkflowReuseSource(DIRS.async, currentSessionId, workflowScriptSourceDigest, workflowArgsDigest);
|
|
14260
14379
|
const workflowRunEvidence = { ...workflowArgsEvidence, scriptDigest: workflowScriptSourceDigest };
|
|
14261
14380
|
if (workflowReuseSource) workflowRunEvidence.reusedFrom = workflowReuseSource.runId;
|
|
14381
|
+
if (workflowResumeLaunch) workflowRunEvidence.resumeOrigin = workflowResumeLaunch.resumeOrigin;
|
|
14262
14382
|
const workflowJournalFingerprints = /* @__PURE__ */ new Map();
|
|
14383
|
+
const storageFailure = (error) => {
|
|
14384
|
+
workflowCapacity?.rollback();
|
|
14385
|
+
return { content: [{ type: "text", text: `Failed to create async workflow storage: ${error instanceof Error ? error.message : String(error)}` }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14386
|
+
};
|
|
14387
|
+
if (workflowReuseSource) {
|
|
14388
|
+
const reuseSourceDir = path19.join(DIRS.async, workflowReuseSource.runId);
|
|
14389
|
+
let claim;
|
|
14390
|
+
try {
|
|
14391
|
+
claim = claimWorkflowResume(reuseSourceDir, { newRunId: workflowRunId, trigger: "reuse" });
|
|
14392
|
+
} catch (error) {
|
|
14393
|
+
return storageFailure(error);
|
|
14394
|
+
}
|
|
14395
|
+
if (claim.kind !== "owner") {
|
|
14396
|
+
workflowCapacity?.rollback();
|
|
14397
|
+
return { content: [{ type: "text", text: claimedWorkflowRunRefusal(workflowReuseSource.runId, claim, requestParams.reuseFrom !== void 0) }], isError: true, details: { mode: "workflow", results: [] } };
|
|
14398
|
+
}
|
|
14399
|
+
pendingReuseClaimReleases.set(params, () => {
|
|
14400
|
+
if (!fs21.existsSync(statusPath)) releaseWorkflowResumeClaim(reuseSourceDir, workflowRunId);
|
|
14401
|
+
});
|
|
14402
|
+
}
|
|
14263
14403
|
try {
|
|
14264
14404
|
fs21.mkdirSync(asyncDir, { recursive: true });
|
|
14265
14405
|
writeRunFanoutBudgetDescriptor(asyncDir, workflowFanoutBudget);
|
|
14406
|
+
if (topLevelAsyncWorkflow && publicWorkflowLaunch) writeWorkflowLaunchRecord(asyncDir, workflowLaunchRecord(publicWorkflowLaunch, workflowCwd, workflowScriptSourceDigest));
|
|
14266
14407
|
fs21.mkdirSync(DIRS.results, { recursive: true });
|
|
14267
14408
|
} 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: [] } };
|
|
14409
|
+
return storageFailure(error);
|
|
14270
14410
|
}
|
|
14271
14411
|
const controller = new AbortController();
|
|
14272
14412
|
deps2.state.workflowControllers ??= /* @__PURE__ */ new Map();
|
|
@@ -14287,7 +14427,7 @@ function createSubagentExecutor(deps) {
|
|
|
14287
14427
|
cwd: workflowCwd,
|
|
14288
14428
|
...workflowSessionRoot ? { sessionRoot: workflowSessionRoot } : {},
|
|
14289
14429
|
...requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {},
|
|
14290
|
-
|
|
14430
|
+
...currentRecordedPid(),
|
|
14291
14431
|
...workflowCapabilityCeiling2 ? { admissionCapabilityCeiling: workflowCapabilityCeiling2 } : {},
|
|
14292
14432
|
steps: [],
|
|
14293
14433
|
...workflowPreflight ? { preflight: workflowPreflight } : {},
|
|
@@ -14876,7 +15016,7 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
14876
15016
|
const priorAsyncDir = path19.join(DIRS.async, priorRunId);
|
|
14877
15017
|
appendWorkflowChildJournal(asyncDir, { type: "start", key, fingerprint: journalFingerprint, runId: priorRunId });
|
|
14878
15018
|
recordReusedWorkflowChild(key, priorRunId);
|
|
14879
|
-
const stopListener = stopAwaitedAsyncChildOnAbort(workflowSignal, deps2.state, priorRunId, priorAsyncDir, deps2.kill,
|
|
15019
|
+
const stopListener = stopAwaitedAsyncChildOnAbort(workflowSignal, deps2.state, priorRunId, priorAsyncDir, deps2.kill, true);
|
|
14880
15020
|
const reattached = await awaitExistingAsyncRun(priorAsyncDir, priorRunId, workflowSignal).finally(stopListener.remove);
|
|
14881
15021
|
const claimedPath = reattached.status === "settled" ? claimWorkflowAwaitedResult(priorAsyncDir, workflowRunId, { ...reattached.result.importedPublication, runId: priorRunId }) : void 0;
|
|
14882
15022
|
if (reattached.status === "settled" && claimedPath) {
|
|
@@ -15052,7 +15192,7 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
15052
15192
|
if (promoted) status = promoted;
|
|
15053
15193
|
}
|
|
15054
15194
|
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 ? ` ${
|
|
15195
|
+
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
15196
|
const outputWarning = writeWorkflowAggregateOutput(workflowAggregateOutputPath2, terminalSummary, producedChildOutputPaths2);
|
|
15057
15197
|
const resultSummary = appendWorkflowOutputWarning(terminalSummary, outputWarning);
|
|
15058
15198
|
const receiptState = status.state === "complete" ? "complete" : status.state === "paused" ? "paused" : status.state === "stopped" ? "stopped" : "failed";
|
|
@@ -15115,6 +15255,7 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
15115
15255
|
let liveWorkflow = { trace: [], emits: [], console: [], ...workflowResource ? { resource: workflowResource.provenance } : {} };
|
|
15116
15256
|
const childProgress = /* @__PURE__ */ new Map();
|
|
15117
15257
|
const childLaunches = /* @__PURE__ */ new Map();
|
|
15258
|
+
const blockingWorkflowChildren = /* @__PURE__ */ new Set();
|
|
15118
15259
|
let activityTimer;
|
|
15119
15260
|
let lastProgressAt = 0;
|
|
15120
15261
|
let workflowProgressClosed = false;
|
|
@@ -15202,6 +15343,10 @@ Parent action: ${COMPLETION_ACTION}` : content,
|
|
|
15202
15343
|
workflowPermitContexts.set(childRequest, { child: { permit: delegatedWorkflowPermit, workflowRunId: foregroundWorkflowRunId, childKey: key } });
|
|
15203
15344
|
}
|
|
15204
15345
|
workflowLaunchObservers.set(childRequest, (launch) => {
|
|
15346
|
+
if (launch.async && launch.runId && (childRequest.workflowAwaitAsync === true || childRequest.action === "resume")) {
|
|
15347
|
+
(deps2.state.blockingWorkflowChildren ??= /* @__PURE__ */ new Set()).add(launch.runId);
|
|
15348
|
+
blockingWorkflowChildren.add(launch.runId);
|
|
15349
|
+
}
|
|
15205
15350
|
childLaunches.set(key, { agent: launch.agent, ...launch.runId ? { runId: launch.runId } : {} });
|
|
15206
15351
|
try {
|
|
15207
15352
|
sendWorkflowProgress();
|
|
@@ -15323,6 +15468,7 @@ ${partial.console.map((entry) => `[${entry.level}] ${entry.text}`).join("\n")}`]
|
|
|
15323
15468
|
}, workflowFanoutBudget));
|
|
15324
15469
|
} finally {
|
|
15325
15470
|
workflowProgressClosed = true;
|
|
15471
|
+
for (const runId2 of blockingWorkflowChildren) deps2.state.blockingWorkflowChildren?.delete(runId2);
|
|
15326
15472
|
if (activityTimer) clearTimeout(activityTimer);
|
|
15327
15473
|
childProgress.clear();
|
|
15328
15474
|
}
|
|
@@ -15745,6 +15891,8 @@ ${item.text}` } : item)
|
|
|
15745
15891
|
return withBudget(inspectSubagentStatus(paramsWithResolvedCwd, omitUndefinedProperties({ state: deps2.state, nested: nestedScope, sessionRoots, abandonedSlotReleaseAfterMs: resolveAbandonedSlotReleaseAfterMs(deps2.config.capacity?.abandonedSlotReleaseAfterMs) })));
|
|
15746
15892
|
}
|
|
15747
15893
|
if (action === "resume") {
|
|
15894
|
+
const workflowResumeSourceId = workflowResumeTargetId(DIRS.async, paramsWithResolvedCwd);
|
|
15895
|
+
if (workflowResumeSourceId) return resumeWorkflowById(_id, workflowResumeSourceId, signal, ctx);
|
|
15748
15896
|
return resumeAsyncRun(omitUndefinedProperties({
|
|
15749
15897
|
params: paramsWithResolvedCwd,
|
|
15750
15898
|
requestCwd,
|
|
@@ -16570,6 +16718,8 @@ ${item.text}` } : item)
|
|
|
16570
16718
|
const workflow = publicParams.workflow;
|
|
16571
16719
|
const errorResult = (text) => Promise.resolve({ content: [{ type: "text", text }], isError: true, details: { mode: publicParams.action ? "management" : "workflow", results: [] } });
|
|
16572
16720
|
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 }).";
|
|
16721
|
+
let workflowLaunch;
|
|
16722
|
+
const workflowResumeLaunch = workflowResumeLaunches.get(params);
|
|
16573
16723
|
if (publicParams.tasks !== void 0 || publicParams.chain !== void 0) {
|
|
16574
16724
|
const kind = publicParams.tasks !== void 0 ? "tasks" : "chain";
|
|
16575
16725
|
const resolved = resolveStructuredWorkflowResource({ kind, steps: publicParams[kind], task: publicParams.task });
|
|
@@ -16577,10 +16727,20 @@ ${item.text}` } : item)
|
|
|
16577
16727
|
const { tasks: _tasks, chain: _chain, task: _task, ...withoutStructuredInput } = publicParams;
|
|
16578
16728
|
publicParams = { ...withoutStructuredInput, workflowScript: resolved.resource.script };
|
|
16579
16729
|
workflowResourcePermits.set(publicParams, resolved.resource.permit);
|
|
16730
|
+
workflowLaunch = { source: "structured" };
|
|
16580
16731
|
} else if (typeof workflow === "string" && !isWorkflowScriptPath(workflow)) {
|
|
16581
16732
|
const resolved = resolveWorkflowResource(workflow, publicParams.args, ctx.sessionManager.getSessionId() ?? void 0);
|
|
16733
|
+
if (workflowResumeLaunch && !resolved.ok) {
|
|
16734
|
+
workflowResumeLaunch.refusal = { code: "authority", reason: `workflow resource '${workflow}' can no longer be resolved: ${resolved.error}` };
|
|
16735
|
+
return errorResult(workflowResumeLaunch.refusal.reason);
|
|
16736
|
+
}
|
|
16737
|
+
if (workflowResumeLaunch && resolved.ok && workflowScriptDigest(resolved.resource.script) !== workflowResumeLaunch.expectedScriptDigest) {
|
|
16738
|
+
workflowResumeLaunch.refusal = { code: "digest", reason: `workflow resource '${workflow}' changed since the run started` };
|
|
16739
|
+
return errorResult(workflowResumeLaunch.refusal.reason);
|
|
16740
|
+
}
|
|
16582
16741
|
if (!resolved.ok) return Promise.resolve({ content: [{ type: "text", text: resolved.error + scriptTextHint }], isError: true, details: { mode: "workflow", results: [] } });
|
|
16583
16742
|
const { workflow: _workflow, args: _args, ...withoutResourceInput } = publicParams;
|
|
16743
|
+
workflowLaunch = { source: "resource", params: savedWorkflowLaunchParams(publicParams) };
|
|
16584
16744
|
publicParams = { ...withoutResourceInput, workflowScript: resolved.resource.script };
|
|
16585
16745
|
workflowResourcePermits.set(publicParams, resolved.resource.permit);
|
|
16586
16746
|
} else if (workflow !== void 0 || publicParams.workflowScript !== void 0) {
|
|
@@ -16595,10 +16755,56 @@ ${item.text}` } : item)
|
|
|
16595
16755
|
}
|
|
16596
16756
|
const { workflow: _workflow, ...withoutWorkflowSource } = publicParams;
|
|
16597
16757
|
publicParams = { ...withoutWorkflowSource, workflowScript, args: "error" in normalizedArgs ? publicParams.args : deepFreezeWorkflowArgs(normalizedArgs.args) };
|
|
16758
|
+
workflowLaunch = { source: "script", params: savedWorkflowLaunchParams(publicParams) };
|
|
16598
16759
|
}
|
|
16760
|
+
if (workflowLaunch && publicParams.action === void 0) publicWorkflowLaunches.set(publicParams, workflowLaunch);
|
|
16761
|
+
if (workflowResumeLaunch) workflowResumeLaunches.set(publicParams, workflowResumeLaunch);
|
|
16599
16762
|
publicExecutions.add(publicParams);
|
|
16600
16763
|
return executeWithSingleDispatchGuard(id, publicParams, signal, onUpdate, ctx);
|
|
16601
16764
|
};
|
|
16765
|
+
const executeWorkflowResume = async (id, prepared, signal, ctx) => {
|
|
16766
|
+
const params = { ...prepared.params };
|
|
16767
|
+
const launch = { presetRunId: prepared.newRunId, resumeOrigin: prepared.resumeOrigin, expectedScriptDigest: prepared.expectedScriptDigest };
|
|
16768
|
+
workflowResumeLaunches.set(params, launch);
|
|
16769
|
+
let result2;
|
|
16770
|
+
try {
|
|
16771
|
+
result2 = await executePublic(id, params, signal, void 0, ctx);
|
|
16772
|
+
} catch (error) {
|
|
16773
|
+
result2 = { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true, details: { mode: "workflow", results: [] } };
|
|
16774
|
+
}
|
|
16775
|
+
if (resumedRunStarted(prepared.sourceAsyncDir, prepared.newRunId)) return { result: result2, launched: true };
|
|
16776
|
+
const firstText = result2.content.find((block) => block.type === "text")?.text ?? "no result";
|
|
16777
|
+
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);
|
|
16778
|
+
releaseWorkflowResumeClaim(prepared.sourceAsyncDir, prepared.newRunId);
|
|
16779
|
+
if (prepared.trigger === "auto") {
|
|
16780
|
+
try {
|
|
16781
|
+
recordWorkflowResumeRefusal(prepared.sourceAsyncDir, { reason: refusal.reason, byHand: refusal.byHand, newRunId: prepared.newRunId });
|
|
16782
|
+
} catch (error) {
|
|
16783
|
+
console.error(`Failed to record why workflow ${prepared.sourceRunId} was not resumed:`, error);
|
|
16784
|
+
}
|
|
16785
|
+
}
|
|
16786
|
+
return { result: result2, launched: false, refusal };
|
|
16787
|
+
};
|
|
16788
|
+
const resumeWorkflowById = async (id, sourceRunId, signal, ctx) => {
|
|
16789
|
+
const refused = (text) => ({ content: [{ type: "text", text }], isError: true, details: { mode: "management", results: [] } });
|
|
16790
|
+
let preparation;
|
|
16791
|
+
try {
|
|
16792
|
+
preparation = prepareWorkflowResume({ asyncDirRoot: DIRS.async, sourceRunId, trigger: "manual", now: Date.now(), currentSessionId: resolveCurrentSessionId(ctx.sessionManager) });
|
|
16793
|
+
} catch (error) {
|
|
16794
|
+
return refused(`Cannot resume workflow '${sourceRunId}': ${error instanceof Error ? error.message : String(error)}`);
|
|
16795
|
+
}
|
|
16796
|
+
if (!preparation.ok) return refused(manualWorkflowResumeRefusalText(sourceRunId, preparation));
|
|
16797
|
+
const outcome = await executeWorkflowResume(id, preparation.prepared, signal, ctx);
|
|
16798
|
+
if (!outcome.launched) return refused(manualWorkflowResumeRefusalText(sourceRunId, outcome.refusal));
|
|
16799
|
+
const resumedLine = `Resumed workflow '${sourceRunId}' as ${preparation.prepared.newRunId}.`;
|
|
16800
|
+
const textIndex = outcome.result.content.findIndex((block) => block.type === "text");
|
|
16801
|
+
const content = [...outcome.result.content];
|
|
16802
|
+
const first = content[textIndex];
|
|
16803
|
+
if (first?.type === "text") content[textIndex] = { ...first, text: `${resumedLine}
|
|
16804
|
+
${first.text}` };
|
|
16805
|
+
else content.unshift({ type: "text", text: resumedLine });
|
|
16806
|
+
return { ...outcome.result, content };
|
|
16807
|
+
};
|
|
16602
16808
|
const executeDelegated = async (id, params, signal, onUpdate, ctx) => {
|
|
16603
16809
|
const disabledFeatureError = disabledFeatureResult(params);
|
|
16604
16810
|
if (disabledFeatureError) return disabledFeatureError;
|
|
@@ -16637,7 +16843,7 @@ ${item.text}` } : item)
|
|
|
16637
16843
|
if (!ownerId) return;
|
|
16638
16844
|
for (const owner of scheduledOwnerExecutors.get(ownerId)?.values() ?? []) yield owner.state;
|
|
16639
16845
|
}
|
|
16640
|
-
return { execute: executeWithSingleDispatchGuard, executePublic, executeDelegated, executeScheduled, getCurrentSupervisorOwnerStates };
|
|
16846
|
+
return { execute: executeWithSingleDispatchGuard, executePublic, executeDelegated, executeScheduled, executeWorkflowResume, getCurrentSupervisorOwnerStates };
|
|
16641
16847
|
}
|
|
16642
16848
|
export {
|
|
16643
16849
|
DEFAULT_ASYNC_TIMEOUT_MS,
|