@bastani/atomic 0.9.19-alpha.9 → 0.9.20-alpha.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 +97 -0
- package/dist/builtin/intercom/CHANGELOG.md +30 -0
- package/dist/builtin/intercom/index.bundle.mjs +15 -1
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +8 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +30 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +14 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +67 -0
- package/dist/builtin/workflows/builtin/{chunk-nkrafh9s.js → chunk-ewkkkbak.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-1jth021m.js → chunk-zqtm1d2c.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +546 -133
- package/dist/builtin/workflows/src/index.js +326 -72
- package/dist/core/extensions/api-types.d.ts +2 -0
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-api.d.ts.map +1 -1
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/loader-host-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-host-modules.js +3 -1
- package/dist/core/extensions/loader-host-modules.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +2 -0
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/reactive-widget.d.ts +6 -0
- package/dist/core/extensions/reactive-widget.d.ts.map +1 -1
- package/dist/core/extensions/reactive-widget.js +7 -1
- package/dist/core/extensions/reactive-widget.js.map +1 -1
- package/dist/core/extensions/runner-shortcuts.d.ts.map +1 -1
- package/dist/core/extensions/runner-shortcuts.js +32 -3
- package/dist/core/extensions/runner-shortcuts.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +4 -0
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/ui-types.d.ts +20 -0
- package/dist/core/extensions/ui-types.d.ts.map +1 -1
- package/dist/core/extensions/ui-types.js.map +1 -1
- package/dist/core/keybinding-identity.d.ts +4 -0
- package/dist/core/keybinding-identity.d.ts.map +1 -0
- package/dist/core/keybinding-identity.js +10 -0
- package/dist/core/keybinding-identity.js.map +1 -0
- package/dist/core/keybindings.d.ts +10 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +7 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/scroll-widget.d.ts +23 -0
- package/dist/modes/interactive/components/scroll-widget.d.ts.map +1 -0
- package/dist/modes/interactive/components/scroll-widget.js +61 -0
- package/dist/modes/interactive/components/scroll-widget.js.map +1 -0
- package/dist/modes/interactive/interactive-extension-runtime.js +10 -3
- package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +3 -2
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts +4 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +15 -7
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-dialog-host.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-dialog-host.js +4 -1
- package/dist/modes/interactive-engine/engine-dialog-host.js.map +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.js +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
- package/dist/modes/interactive-engine/protocol.d.ts +12 -1
- package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
- package/dist/modes/interactive-engine/protocol.js +45 -2
- package/dist/modes/interactive-engine/protocol.js.map +1 -1
- package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-component.js +18 -8
- package/dist/modes/interactive-engine/remote-component.js.map +1 -1
- package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-extension-ui.js +2 -1
- package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +4 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/background-tasks.md +2 -0
- package/docs/extensions/api-reference.md +2 -0
- package/docs/extensions/authoring.md +2 -0
- package/docs/keybindings.md +17 -0
- package/docs/tui.md +34 -0
- package/docs/workflows/api-reference.md +2 -0
- package/docs/workflows/operations.md +13 -1
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- /package/dist/builtin/workflows/builtin/{chunk-ngkqkzej.js → chunk-m0xfsef8.js} +0 -0
|
@@ -67164,6 +67164,13 @@ function topLevelWorkflowRuns(runs) {
|
|
|
67164
67164
|
}
|
|
67165
67165
|
|
|
67166
67166
|
// dist/builtin/workflows/src/shared/timing.ts
|
|
67167
|
+
function stageTimingFields(stage = {}) {
|
|
67168
|
+
return {
|
|
67169
|
+
...stage.startedAt !== undefined ? { startedAt: stage.startedAt } : {},
|
|
67170
|
+
...stage.endedAt !== undefined ? { endedAt: stage.endedAt } : {},
|
|
67171
|
+
...stage.durationMs !== undefined ? { durationMs: stage.durationMs } : {}
|
|
67172
|
+
};
|
|
67173
|
+
}
|
|
67167
67174
|
function nonNegative(ms) {
|
|
67168
67175
|
return Math.max(0, ms);
|
|
67169
67176
|
}
|
|
@@ -67189,6 +67196,8 @@ function elapsedStageMs(stage, now = Date.now()) {
|
|
|
67189
67196
|
return nonNegative(stage.durationMs);
|
|
67190
67197
|
if (stage.startedAt === undefined)
|
|
67191
67198
|
return;
|
|
67199
|
+
if (stage.replayed && stage.endedAt === undefined)
|
|
67200
|
+
return;
|
|
67192
67201
|
const effectiveNow = stage.endedAt ?? now;
|
|
67193
67202
|
return elapsedFromStart(stage.startedAt, effectiveNow, stage.pausedDurationMs, stage.pausedAt);
|
|
67194
67203
|
}
|
|
@@ -68525,19 +68534,57 @@ function formatWorkflowStageTarget(rootRunId, ...segments) {
|
|
|
68525
68534
|
|
|
68526
68535
|
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
68527
68536
|
function workflowBoundarySegments(runs, runId) {
|
|
68537
|
+
return createWorkflowBoundarySegmentsResolver(runs)(runId);
|
|
68538
|
+
}
|
|
68539
|
+
function createWorkflowBoundarySegmentsResolver(runs) {
|
|
68528
68540
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
68529
|
-
const
|
|
68530
|
-
|
|
68531
|
-
|
|
68532
|
-
const
|
|
68533
|
-
const
|
|
68534
|
-
|
|
68535
|
-
|
|
68536
|
-
|
|
68537
|
-
|
|
68538
|
-
|
|
68541
|
+
const stagesByRun = new Map;
|
|
68542
|
+
const childrenByParent = new Map;
|
|
68543
|
+
for (const run of runs) {
|
|
68544
|
+
const byId = new Map;
|
|
68545
|
+
const byName = new Map;
|
|
68546
|
+
for (const stage of run.stages) {
|
|
68547
|
+
const ids = byId.get(stage.id) ?? [];
|
|
68548
|
+
ids.push(stage);
|
|
68549
|
+
byId.set(stage.id, ids);
|
|
68550
|
+
const names = byName.get(stage.name) ?? [];
|
|
68551
|
+
names.push(stage);
|
|
68552
|
+
byName.set(stage.name, names);
|
|
68553
|
+
}
|
|
68554
|
+
stagesByRun.set(run.id, { byId, byName });
|
|
68555
|
+
if (run.parentRunId === undefined || run.parentStageId === undefined)
|
|
68556
|
+
continue;
|
|
68557
|
+
const byStage = childrenByParent.get(run.parentRunId) ?? new Map;
|
|
68558
|
+
const children = byStage.get(run.parentStageId) ?? [];
|
|
68559
|
+
children.push(run);
|
|
68560
|
+
byStage.set(run.parentStageId, children);
|
|
68561
|
+
childrenByParent.set(run.parentRunId, byStage);
|
|
68539
68562
|
}
|
|
68540
|
-
|
|
68563
|
+
const cachedSegments = new Map;
|
|
68564
|
+
return (runId) => {
|
|
68565
|
+
if (cachedSegments.has(runId))
|
|
68566
|
+
return cachedSegments.get(runId);
|
|
68567
|
+
const segments = [];
|
|
68568
|
+
let current = runById.get(runId);
|
|
68569
|
+
while (current !== undefined && current.parentRunId !== undefined) {
|
|
68570
|
+
const parent = runById.get(current.parentRunId);
|
|
68571
|
+
const stages = stagesByRun.get(current.parentRunId);
|
|
68572
|
+
const boundary = current.parentStageId === undefined ? undefined : stages?.byId.get(current.parentStageId)?.[0];
|
|
68573
|
+
if (parent === undefined || stages === undefined || boundary === undefined) {
|
|
68574
|
+
cachedSegments.set(runId, undefined);
|
|
68575
|
+
return;
|
|
68576
|
+
}
|
|
68577
|
+
const boundaryName = boundary.name;
|
|
68578
|
+
const matchingBoundaries = stages.byId.get(boundaryName) ?? stages.byName.get(boundaryName);
|
|
68579
|
+
const matchingBoundary = matchingBoundaries?.length === 1 ? matchingBoundaries[0] : undefined;
|
|
68580
|
+
const children = matchingBoundary === undefined ? undefined : childrenByParent.get(parent.id)?.get(matchingBoundary.id);
|
|
68581
|
+
segments.unshift(boundaryName.length > 0 && !boundaryName.includes("/") && !boundaryName.includes("*") && children?.length === 1 && children[0]?.id === current.id ? boundaryName : current.id);
|
|
68582
|
+
current = parent;
|
|
68583
|
+
}
|
|
68584
|
+
const result = current === undefined ? undefined : segments;
|
|
68585
|
+
cachedSegments.set(runId, result);
|
|
68586
|
+
return result;
|
|
68587
|
+
};
|
|
68541
68588
|
}
|
|
68542
68589
|
function workflowBoundaryHops(runs, runId) {
|
|
68543
68590
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
@@ -68593,6 +68640,15 @@ function pendingWorkflowStageStatuses(run, resolveOwningRunStatus, resolveBounda
|
|
|
68593
68640
|
});
|
|
68594
68641
|
}
|
|
68595
68642
|
|
|
68643
|
+
// dist/builtin/workflows/src/shared/stage-startup.ts
|
|
68644
|
+
function formatStageStartup(startup, now = Date.now()) {
|
|
68645
|
+
const observedAt = startup.state === "dispatched" ? startup.phaseStartedAt : startup.settledAt ?? now;
|
|
68646
|
+
const age = Math.max(0, Math.floor((observedAt - startup.phaseStartedAt) / 1000));
|
|
68647
|
+
const total = Math.max(0, Math.floor((observedAt - startup.startedAt) / 1000));
|
|
68648
|
+
const recovery = startup.state === "cancelled" && startup.ownershipPending ? "; cleanup pending — do not retry in-process; stop the owning Atomic process before fresh execution" : "";
|
|
68649
|
+
return `startup ${startup.phase} (${total}s total, ${age}s on current step; ${startup.state})${recovery}`;
|
|
68650
|
+
}
|
|
68651
|
+
|
|
68596
68652
|
// dist/builtin/workflows/src/tui/status-helpers.ts
|
|
68597
68653
|
function statusColor(status, theme) {
|
|
68598
68654
|
switch (status) {
|
|
@@ -68848,9 +68904,15 @@ function pendingStageRows(runId, rootRunId, runStatus, stage, width, theme, reso
|
|
|
68848
68904
|
const text = hexToAnsi(theme.text);
|
|
68849
68905
|
return wrapped.map(({ prefix, chunk }, index) => index === 0 ? ` ${muted}${pad(label, 16)}${RESET}${text}${chunk}${RESET} ` : `${prefix}${text}${chunk}${RESET} `);
|
|
68850
68906
|
}
|
|
68907
|
+
function startupRows(stage, now, width, theme) {
|
|
68908
|
+
if (stage.startup === undefined)
|
|
68909
|
+
return [];
|
|
68910
|
+
return wrapIdentifierLines(formatStageStartup(stage.startup, now), Math.max(1, width - 2), " ", " ").map(({ prefix, chunk }) => theme === undefined ? `${prefix}${chunk}` : `${prefix}${hexToAnsi(theme.textMuted)}${chunk}${RESET}`);
|
|
68911
|
+
}
|
|
68851
68912
|
function renderStageRowsPlain(runId, rootRunId, runStatus, stage, now, width, resolveOwningRunStatus, resolveBoundarySegments) {
|
|
68852
68913
|
const rows = [
|
|
68853
68914
|
` ${stageLinePlain(stage, now, Math.max(1, width - 2))} `,
|
|
68915
|
+
...startupRows(stage, now, width),
|
|
68854
68916
|
...pendingStageRows(runId, rootRunId, runStatus, stage, width, undefined, resolveOwningRunStatus, resolveBoundarySegments)
|
|
68855
68917
|
];
|
|
68856
68918
|
if (stage.error) {
|
|
@@ -68862,6 +68924,7 @@ function renderStageRowsPlain(runId, rootRunId, runStatus, stage, now, width, re
|
|
|
68862
68924
|
function renderStageRowsThemed(runId, rootRunId, runStatus, stage, now, theme, width, resolveOwningRunStatus, resolveBoundarySegments) {
|
|
68863
68925
|
const rows = [
|
|
68864
68926
|
` ${stageLineThemed(stage, now, theme, Math.max(1, width - 2))} `,
|
|
68927
|
+
...startupRows(stage, now, width, theme),
|
|
68865
68928
|
...pendingStageRows(runId, rootRunId, runStatus, stage, width, theme, resolveOwningRunStatus, resolveBoundarySegments)
|
|
68866
68929
|
];
|
|
68867
68930
|
if (stage.error) {
|
|
@@ -79145,8 +79208,26 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now(), la
|
|
|
79145
79208
|
});
|
|
79146
79209
|
}
|
|
79147
79210
|
|
|
79211
|
+
// dist/builtin/workflows/src/tui/widget-scroll-hint.ts
|
|
79212
|
+
import { keybindingIdentity } from "@bastani/atomic";
|
|
79213
|
+
import { getKeybindings, matchesKey as matchesKey2 } from "@earendil-works/pi-tui";
|
|
79214
|
+
var legacyInputs = Array.from({ length: 128 }, (_, code) => String.fromCharCode(code)).flatMap((data) => [
|
|
79215
|
+
data,
|
|
79216
|
+
`\x1B${data}`
|
|
79217
|
+
]);
|
|
79218
|
+
function workflowScrollHint(bindings = getKeybindings().getResolvedBindings(), platform = process.platform) {
|
|
79219
|
+
const keys = ["app.workflows.scrollUp", "app.workflows.scrollDown"].map((action) => {
|
|
79220
|
+
const configured = bindings[action] ?? [];
|
|
79221
|
+
return (Array.isArray(configured) ? configured : [configured]).find((key) => {
|
|
79222
|
+
const inputs = legacyInputs.filter((data) => matchesKey2(data, key));
|
|
79223
|
+
return !Object.entries(bindings).some(([other, values]) => other !== action && (Array.isArray(values) ? values : [values]).some((value2) => value2 !== undefined && (keybindingIdentity(value2) === keybindingIdentity(key) || inputs.some((data) => matchesKey2(data, value2)))));
|
|
79224
|
+
});
|
|
79225
|
+
}).filter((key) => key !== undefined);
|
|
79226
|
+
const label = keys.map((key) => key.replace(/^alt\+/i, platform === "darwin" ? "Option+" : "Alt+")).join("/");
|
|
79227
|
+
return ` ↑↓ scroll${label ? ` · ${label}` : ""}`;
|
|
79228
|
+
}
|
|
79229
|
+
|
|
79148
79230
|
// dist/builtin/workflows/src/tui/widget-viewport.ts
|
|
79149
|
-
import { ScrollableComponentViewport } from "@bastani/atomic";
|
|
79150
79231
|
var WORKFLOW_WIDGET_MAX_ROWS = 10;
|
|
79151
79232
|
|
|
79152
79233
|
class WorkflowWidgetViewport {
|
|
@@ -79154,53 +79235,60 @@ class WorkflowWidgetViewport {
|
|
|
79154
79235
|
terminalRows;
|
|
79155
79236
|
requestRender;
|
|
79156
79237
|
getRunRows;
|
|
79157
|
-
|
|
79238
|
+
getHint;
|
|
79239
|
+
position = 0;
|
|
79240
|
+
version = 0;
|
|
79241
|
+
collapsed = false;
|
|
79242
|
+
state;
|
|
79158
79243
|
lines = [];
|
|
79159
|
-
scrollable = false;
|
|
79160
79244
|
runRows = [];
|
|
79161
|
-
constructor(content, terminalRows, requestRender, getRunRows) {
|
|
79245
|
+
constructor(content, terminalRows, requestRender, getRunRows, getHint = () => "") {
|
|
79162
79246
|
this.content = content;
|
|
79163
79247
|
this.terminalRows = terminalRows;
|
|
79164
79248
|
this.requestRender = requestRender;
|
|
79165
79249
|
this.getRunRows = getRunRows;
|
|
79166
|
-
this.
|
|
79167
|
-
|
|
79250
|
+
this.getHint = getHint;
|
|
79251
|
+
}
|
|
79252
|
+
getScrollRequest() {
|
|
79253
|
+
return { version: this.version, scrollTop: this.collapsed ? 0 : this.position };
|
|
79254
|
+
}
|
|
79255
|
+
onScroll(state) {
|
|
79256
|
+
this.state = state;
|
|
79257
|
+
if (!this.collapsed)
|
|
79258
|
+
this.position = state.scrollTop;
|
|
79168
79259
|
}
|
|
79169
79260
|
scroll(direction) {
|
|
79170
|
-
if (
|
|
79261
|
+
if (this.collapsed)
|
|
79171
79262
|
return;
|
|
79172
|
-
this.
|
|
79263
|
+
const height = this.state?.viewportHeight ?? Math.max(1, Math.min(WORKFLOW_WIDGET_MAX_ROWS, Math.floor(this.terminalRows() / 3)));
|
|
79264
|
+
const next = Math.max(0, Math.min(Math.max(0, this.lines.length - height), this.position + direction));
|
|
79265
|
+
if (next === this.position)
|
|
79266
|
+
return;
|
|
79267
|
+
this.position = next;
|
|
79268
|
+
this.version++;
|
|
79173
79269
|
this.requestRender();
|
|
79174
79270
|
}
|
|
79175
79271
|
render(width) {
|
|
79176
|
-
const
|
|
79177
|
-
const
|
|
79178
|
-
const
|
|
79179
|
-
|
|
79180
|
-
|
|
79272
|
+
const content = this.content.render(width);
|
|
79273
|
+
const hint = content.length > 1 ? this.getHint() : "";
|
|
79274
|
+
const nextLines = hint ? [...content, truncateToWidth2(hint, width, "…")] : content;
|
|
79275
|
+
const nextRunRows = (this.getRunRows?.() ?? []).map((run, index, rows) => hint && index === rows.length - 1 ? { ...run, end: run.end + 1 } : run);
|
|
79276
|
+
const collapsed = Boolean(this.getRunRows && nextLines.length === 1 && nextRunRows.length === 0);
|
|
79277
|
+
if (collapsed) {
|
|
79278
|
+
if (!this.collapsed)
|
|
79279
|
+
this.version++;
|
|
79280
|
+
this.collapsed = true;
|
|
79181
79281
|
return nextLines;
|
|
79182
79282
|
}
|
|
79183
|
-
const
|
|
79184
|
-
|
|
79185
|
-
|
|
79283
|
+
const anchoredOffset = this.getRunRows ? this.resolveAnchor(this.position, nextRunRows) : this.position;
|
|
79284
|
+
if (this.collapsed || anchoredOffset !== this.position) {
|
|
79285
|
+
this.position = anchoredOffset;
|
|
79286
|
+
this.version++;
|
|
79287
|
+
}
|
|
79288
|
+
this.collapsed = false;
|
|
79186
79289
|
this.lines = nextLines;
|
|
79187
79290
|
this.runRows = nextRunRows;
|
|
79188
|
-
|
|
79189
|
-
this.viewport.scrollTo(anchoredOffset);
|
|
79190
|
-
} else if (previousLineCount <= 1 || this.lines.length < previousLineCount && this.lines.length <= cap) {
|
|
79191
|
-
this.viewport.scrollTo(0);
|
|
79192
|
-
}
|
|
79193
|
-
this.scrollable = this.lines.length > 1;
|
|
79194
|
-
this.viewport.setVisibleRows(1);
|
|
79195
|
-
this.viewport.render(width);
|
|
79196
|
-
if (!this.scrollable)
|
|
79197
|
-
return this.lines;
|
|
79198
|
-
const first = this.viewport.getMaxScroll() - this.viewport.getScrollFromBottom() + 1;
|
|
79199
|
-
const visible = this.lines.slice(first - 1, first - 1 + Math.max(1, cap - 1));
|
|
79200
|
-
if (cap === 1)
|
|
79201
|
-
return visible;
|
|
79202
|
-
const hint = ` ${first}–${first + visible.length - 1}/${this.lines.length} · Alt+PgUp/PgDn scroll workflows`;
|
|
79203
|
-
return [...visible, truncateToWidth2(hint, width, "…")];
|
|
79291
|
+
return nextLines;
|
|
79204
79292
|
}
|
|
79205
79293
|
resolveAnchor(offset, next) {
|
|
79206
79294
|
if (offset === 0 || next.length === 0)
|
|
@@ -79272,7 +79360,7 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
79272
79360
|
widgetViewports.delete(storeInstance);
|
|
79273
79361
|
setWidget.call(ui, key, factory ? (tui, theme) => {
|
|
79274
79362
|
const host = tui;
|
|
79275
|
-
const viewport = new WorkflowWidgetViewport(factory(tui, theme), () => host?.terminal?.rows ?? 30, () => requestRender ? requestRender.call(ui) : host?.requestRender?.(), () => layout.runs);
|
|
79363
|
+
const viewport = new WorkflowWidgetViewport(factory(tui, theme), () => host?.terminal?.rows ?? 30, () => requestRender ? requestRender.call(ui) : host?.requestRender?.(), () => layout.runs, workflowScrollHint);
|
|
79276
79364
|
widgetViewports.set(storeInstance, viewport);
|
|
79277
79365
|
return viewport;
|
|
79278
79366
|
} : undefined, opts);
|
|
@@ -79282,6 +79370,7 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
79282
79370
|
},
|
|
79283
79371
|
key: WIDGET_KEY,
|
|
79284
79372
|
placement: "belowEditor",
|
|
79373
|
+
scroll: { maxHeight: 10, maxHeightFraction: 1 / 3 },
|
|
79285
79374
|
timers,
|
|
79286
79375
|
getSnapshot: () => liveWidgetSnapshot(storeInstance),
|
|
79287
79376
|
subscribe: (listener) => subscribeStoreInvalidation(storeInstance, listener),
|
|
@@ -87809,6 +87898,7 @@ function cachedStageId(runId, replayKey) {
|
|
|
87809
87898
|
function stageMetadataCheckpointId(replayKey, stage) {
|
|
87810
87899
|
return `${stableCheckpointId("stage-meta", replayKey)}:${durableHash({
|
|
87811
87900
|
stageId: stage.id,
|
|
87901
|
+
...stage.replayed === true ? { replayed: true } : {},
|
|
87812
87902
|
status: stage.status,
|
|
87813
87903
|
endedAt: stage.endedAt ?? 0,
|
|
87814
87904
|
durationMs: stage.durationMs ?? 0,
|
|
@@ -87816,11 +87906,9 @@ function stageMetadataCheckpointId(replayKey, stage) {
|
|
|
87816
87906
|
})}`;
|
|
87817
87907
|
}
|
|
87818
87908
|
function recordCachedStageIntoStore(store, runId, name, replayKey, output, completedStageReplayKeys, parentIds, checkpoint) {
|
|
87819
|
-
const now = Date.now();
|
|
87820
87909
|
const sourceStageId = checkpoint?.topology?.run?.runId === runId ? checkpoint.topology.stageId : undefined;
|
|
87821
87910
|
const stageId = sourceStageId ?? cachedStageId(runId, replayKey);
|
|
87822
87911
|
const result = checkpoint?.result ?? (typeof output === "string" ? output : JSON.stringify(output));
|
|
87823
|
-
const endedAt = checkpoint?.endedAt ?? checkpoint?.completedAt ?? now;
|
|
87824
87912
|
const hasCurrentIdentity = checkpoint?.topology?.sourceOrder !== undefined || checkpoint?.topology?.status !== undefined || checkpoint?.topology?.occurrenceKey !== undefined || checkpoint?.topology?.boundary !== undefined;
|
|
87825
87913
|
const childResult = parseWorkflowChildResult(output) ?? (hasCurrentIdentity ? undefined : parseLegacyWorkflowChildResult(output));
|
|
87826
87914
|
const workflowChild = childResult === undefined ? undefined : workflowChildSnapshotFromResult(childResult);
|
|
@@ -87830,9 +87918,7 @@ function recordCachedStageIntoStore(store, runId, name, replayKey, output, compl
|
|
|
87830
87918
|
name,
|
|
87831
87919
|
status: "completed",
|
|
87832
87920
|
parentIds: parentIds !== undefined ? Object.freeze([...parentIds]) : [],
|
|
87833
|
-
|
|
87834
|
-
endedAt,
|
|
87835
|
-
durationMs: checkpoint?.durationMs ?? 0,
|
|
87921
|
+
...stageTimingFields(checkpoint),
|
|
87836
87922
|
result,
|
|
87837
87923
|
replayKey,
|
|
87838
87924
|
replayed: true,
|
|
@@ -88196,7 +88282,7 @@ function appendStageStart(api, payload) {
|
|
|
88196
88282
|
...payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {},
|
|
88197
88283
|
...payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {},
|
|
88198
88284
|
...payload.replayed !== undefined ? { replayed: payload.replayed } : {},
|
|
88199
|
-
ts: payload.ts
|
|
88285
|
+
...payload.ts !== undefined ? { ts: payload.ts } : {}
|
|
88200
88286
|
});
|
|
88201
88287
|
}
|
|
88202
88288
|
function appendStageEnd(api, payload, opts) {
|
|
@@ -88207,6 +88293,7 @@ function appendStageEnd(api, payload, opts) {
|
|
|
88207
88293
|
stageId: payload.stageId,
|
|
88208
88294
|
status: payload.status,
|
|
88209
88295
|
...payload.durationMs !== undefined ? { durationMs: payload.durationMs } : {},
|
|
88296
|
+
...payload.endedAt !== undefined ? { endedAt: payload.endedAt } : {},
|
|
88210
88297
|
...payload.summary !== undefined ? { summary: payload.summary } : {},
|
|
88211
88298
|
...payload.error !== undefined ? { error: payload.error } : {},
|
|
88212
88299
|
...payload.failureKind !== undefined ? { failureKind: payload.failureKind } : {},
|
|
@@ -100857,6 +100944,26 @@ function createContinuationReplayIndex(continuation, sourceToContinuationNodeIds
|
|
|
100857
100944
|
}
|
|
100858
100945
|
|
|
100859
100946
|
// dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts
|
|
100947
|
+
function continuationPromptAnswer(store, sourceRun, sourceStage) {
|
|
100948
|
+
let run = sourceRun;
|
|
100949
|
+
let stage = sourceStage;
|
|
100950
|
+
const visited = new Set;
|
|
100951
|
+
while (!visited.has(stage.id)) {
|
|
100952
|
+
visited.add(stage.id);
|
|
100953
|
+
const answer = store.getStagePromptAnswer(run.id, stage.id);
|
|
100954
|
+
if (answer !== undefined)
|
|
100955
|
+
return answer;
|
|
100956
|
+
if (!stage.replayed || stage.replayedFromStageId === undefined || run.resumedFromRunId === undefined)
|
|
100957
|
+
break;
|
|
100958
|
+
const parentRun = store.runs().find((candidate) => candidate.id === run.resumedFromRunId);
|
|
100959
|
+
const parentStage = parentRun?.stages.find((candidate) => candidate.id === stage.replayedFromStageId);
|
|
100960
|
+
if (parentRun === undefined || parentStage === undefined)
|
|
100961
|
+
break;
|
|
100962
|
+
run = parentRun;
|
|
100963
|
+
stage = parentStage;
|
|
100964
|
+
}
|
|
100965
|
+
return;
|
|
100966
|
+
}
|
|
100860
100967
|
function buildPromptNodeUiAdapter(input) {
|
|
100861
100968
|
const ask = async (descriptor, durableReplay) => {
|
|
100862
100969
|
input.throwIfWorkflowExitSelected();
|
|
@@ -100871,6 +100978,9 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100871
100978
|
const prompt = makePrompt(descriptor);
|
|
100872
100979
|
const replayKey = promptReplayKey(descriptor);
|
|
100873
100980
|
const durableTopology = input.durableTopologyForReplayKey?.(replayKey);
|
|
100981
|
+
if (durableTopology?.status === "completed" && durableReplay === undefined) {
|
|
100982
|
+
throw new Error(`insufficient_state: missing durable UI answer for completed prompt ${durableTopology.stageId}`);
|
|
100983
|
+
}
|
|
100874
100984
|
const stageId = durableTopology?.stageId ?? crypto.randomUUID();
|
|
100875
100985
|
const provisionalParentIds = input.tracker.onSpawn(stageId, descriptor.kind);
|
|
100876
100986
|
const replayDecision = input.replayIndex.decide({
|
|
@@ -100884,7 +100994,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100884
100994
|
if (!sameStringSet(parentIds, provisionalParentIds))
|
|
100885
100995
|
input.tracker.replaceParents(stageId, parentIds);
|
|
100886
100996
|
const replaySource = replayDecision.source;
|
|
100887
|
-
const continuationAnswer = replayDecision.kind === "replay" ? input.activeStore
|
|
100997
|
+
const continuationAnswer = replayDecision.kind === "replay" ? continuationPromptAnswer(input.activeStore, input.opts.continuation.source, replayDecision.source) : undefined;
|
|
100888
100998
|
const replayAnswer = durableReplay === undefined ? continuationAnswer : { value: durableReplay.response };
|
|
100889
100999
|
const shouldReplay = replayAnswer !== undefined;
|
|
100890
101000
|
if (shouldReplay && durableReplay === undefined)
|
|
@@ -100897,13 +101007,11 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100897
101007
|
replayKey,
|
|
100898
101008
|
status: shouldReplay ? "completed" : "running",
|
|
100899
101009
|
parentIds: Object.freeze(parentIds),
|
|
100900
|
-
startedAt: prompt.createdAt,
|
|
101010
|
+
...shouldReplay ? stageTimingFields(durableReplay === undefined ? replaySource : input.durableTimingForStageId?.(stageId)) : { startedAt: prompt.createdAt },
|
|
100901
101011
|
promptFootprint: { ...prompt },
|
|
100902
101012
|
toolEvents: [],
|
|
100903
101013
|
attachable: !shouldReplay,
|
|
100904
101014
|
...shouldReplay ? {
|
|
100905
|
-
endedAt: prompt.createdAt,
|
|
100906
|
-
durationMs: 0,
|
|
100907
101015
|
promptAnswerState: promptAnswerStatus,
|
|
100908
101016
|
replayedFromStageId: replaySourceId,
|
|
100909
101017
|
replayed: true
|
|
@@ -100933,8 +101041,10 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100933
101041
|
pauseGate = undefined;
|
|
100934
101042
|
currentPauseGate?.resolve();
|
|
100935
101043
|
stageSnapshot.status = status;
|
|
100936
|
-
|
|
100937
|
-
|
|
101044
|
+
if (!shouldReplay) {
|
|
101045
|
+
stageSnapshot.endedAt = Date.now();
|
|
101046
|
+
stageSnapshot.durationMs = elapsedStageMs(stageSnapshot, stageSnapshot.endedAt);
|
|
101047
|
+
}
|
|
100938
101048
|
input.activeStore.recordStageAttachable(input.runId, stageId, false);
|
|
100939
101049
|
input.activeStore.recordStageEnd(input.runId, stageSnapshot);
|
|
100940
101050
|
await input.opts.onStageEnd?.(input.runId, stageSnapshot);
|
|
@@ -100944,6 +101054,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100944
101054
|
stageId,
|
|
100945
101055
|
status: stageSnapshot.status,
|
|
100946
101056
|
durationMs: stageSnapshot.durationMs,
|
|
101057
|
+
endedAt: stageSnapshot.endedAt,
|
|
100947
101058
|
...stageSnapshot.error !== undefined ? { error: stageSnapshot.error } : {},
|
|
100948
101059
|
...stageSnapshot.failureKind !== undefined ? { failureKind: stageSnapshot.failureKind } : {},
|
|
100949
101060
|
...stageSnapshot.failureCode !== undefined ? { failureCode: stageSnapshot.failureCode } : {},
|
|
@@ -101010,7 +101121,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
101010
101121
|
name: stageSnapshot.name,
|
|
101011
101122
|
parentIds: stageSnapshot.parentIds,
|
|
101012
101123
|
...stageReplayFields(stageSnapshot),
|
|
101013
|
-
ts:
|
|
101124
|
+
ts: stageSnapshot.startedAt
|
|
101014
101125
|
});
|
|
101015
101126
|
}
|
|
101016
101127
|
if (shouldReplay) {
|
|
@@ -102281,7 +102392,7 @@ function wrapUiWithDurable(base, deps) {
|
|
|
102281
102392
|
// dist/builtin/workflows/src/engine/primitives/ui.ts
|
|
102282
102393
|
function buildExitGatedUiContext(input) {
|
|
102283
102394
|
const base = input.opts.usePromptNodesForUi === true ? input.baseFromPromptNodes() : input.opts.executionMode === "non_interactive" && input.opts.ui === undefined ? makeHeadlessUnavailableUIContext() : normalizeUIContext(input.opts.ui);
|
|
102284
|
-
const promptNodeReplay = input.opts.usePromptNodesForUi === true && input.opts.continuation !== undefined;
|
|
102395
|
+
const promptNodeReplay = input.opts.usePromptNodesForUi === true && input.opts.continuation !== undefined && input.opts.continuation.source.id !== input.durableUi?.workflowId;
|
|
102285
102396
|
const durableBase = input.durableUi !== undefined && !promptNodeReplay ? wrapUiWithDurable(base, input.durableUi) : base;
|
|
102286
102397
|
const invoke = (call) => {
|
|
102287
102398
|
input.throwIfWorkflowExitSelected();
|
|
@@ -102805,7 +102916,7 @@ function mergeStageDraft(existing, checkpoint, sequence) {
|
|
|
102805
102916
|
...valueOrExisting("thinkingLevel", checkpoint, existing),
|
|
102806
102917
|
...valueOrExisting("attemptedModels", checkpoint, existing),
|
|
102807
102918
|
...valueOrExisting("modelAttempts", checkpoint, existing),
|
|
102808
|
-
...checkpoint.topology !== undefined ? { topology: checkpoint.topology } : existing?.topology !== undefined ? { topology: existing.topology } : {}
|
|
102919
|
+
...existing?.topology?.run !== undefined && checkpoint.topology?.run === undefined ? { topology: existing.topology } : checkpoint.topology !== undefined ? { topology: checkpoint.topology } : existing?.topology !== undefined ? { topology: existing.topology } : {}
|
|
102809
102920
|
};
|
|
102810
102921
|
}
|
|
102811
102922
|
function valueOrExisting(key, checkpoint, existing) {
|
|
@@ -103026,7 +103137,7 @@ function resolveToolResumeFrontier(source, backend) {
|
|
|
103026
103137
|
if (source.failedToolNodeId === undefined && !checkpoints.some((checkpoint) => checkpoint.kind === "tool" && checkpoint.throwingFailureError === source.error && checkpoint.argsHash === frontier.argsHash && checkpoint.topology?.nodeId === frontier.id && checkpoint.topology.ordinal === frontier.ordinal))
|
|
103027
103138
|
return fail("missing typed tool failure checkpoint for legacy frontier");
|
|
103028
103139
|
for (const stage of source.stages) {
|
|
103029
|
-
if (stage.status !== "completed" || !checkpoints.some((checkpoint) => checkpoint.kind === "stage" && checkpoint.replayKey === stage.replayKey && checkpoint.output !== undefined))
|
|
103140
|
+
if (stage.status !== "completed" || !checkpoints.some((checkpoint) => checkpoint.kind === "stage" && checkpoint.replayKey === stage.replayKey && (checkpoint.output !== undefined || ["input", "confirm", "select", "editor", "custom"].includes(stage.name) && stage.replayKey?.startsWith(`prompt:${stage.name}:`) === true && checkpoint.name === stage.name && checkpoint.topology?.stageId === stage.id && checkpoint.topology.status === "completed" && checkpoint.topology.run?.runId === source.id)))
|
|
103030
103141
|
return fail(`unfinished or missing completed stage checkpoint ${stage.id}`);
|
|
103031
103142
|
}
|
|
103032
103143
|
for (const tool of tools) {
|
|
@@ -104446,13 +104557,11 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104446
104557
|
replayKey,
|
|
104447
104558
|
status: replayedChild !== undefined ? "completed" : "running",
|
|
104448
104559
|
parentIds: Object.freeze([...parentIds]),
|
|
104449
|
-
startedAt,
|
|
104560
|
+
...replayedChild === undefined ? { startedAt } : stageTimingFields(replaySource),
|
|
104450
104561
|
toolEvents: [],
|
|
104451
104562
|
attachable: false,
|
|
104452
104563
|
...replaySource !== undefined ? { replayedFromStageId: replaySource.id, replayed: replayedChild !== undefined } : {},
|
|
104453
104564
|
...replayedChild !== undefined && replayChildSnapshot !== undefined ? {
|
|
104454
|
-
endedAt: startedAt,
|
|
104455
|
-
durationMs: 0,
|
|
104456
104565
|
...replayDecision.kind === "replay" && replayDecision.source.result !== undefined ? { result: replayDecision.source.result } : {},
|
|
104457
104566
|
workflowChild: cloneWorkflowChildReplaySnapshot(replayChildSnapshot)
|
|
104458
104567
|
} : {}
|
|
@@ -104469,7 +104578,7 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104469
104578
|
name,
|
|
104470
104579
|
parentIds: stageSnapshot.parentIds,
|
|
104471
104580
|
...stageReplayFields(stageSnapshot),
|
|
104472
|
-
ts: startedAt
|
|
104581
|
+
ts: stageSnapshot.startedAt
|
|
104473
104582
|
});
|
|
104474
104583
|
};
|
|
104475
104584
|
const appendStageEndForSnapshot = () => {
|
|
@@ -104480,6 +104589,7 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104480
104589
|
stageId,
|
|
104481
104590
|
status: stageSnapshot.status,
|
|
104482
104591
|
durationMs: stageSnapshot.durationMs,
|
|
104592
|
+
endedAt: stageSnapshot.endedAt,
|
|
104483
104593
|
...stageSnapshot.error !== undefined ? { error: stageSnapshot.error } : {},
|
|
104484
104594
|
...stageSnapshot.failureKind !== undefined ? { failureKind: stageSnapshot.failureKind } : {},
|
|
104485
104595
|
...stageSnapshot.failureCode !== undefined ? { failureCode: stageSnapshot.failureCode } : {},
|
|
@@ -104516,8 +104626,10 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104516
104626
|
clearBoundaryChildMetadata();
|
|
104517
104627
|
applyFailureToStage(stageSnapshot, input.classifyExecutorFailure(failureError));
|
|
104518
104628
|
}
|
|
104519
|
-
|
|
104520
|
-
|
|
104629
|
+
if (replayedChild === undefined) {
|
|
104630
|
+
stageSnapshot.endedAt = Date.now();
|
|
104631
|
+
stageSnapshot.durationMs = elapsedStageMs(stageSnapshot, stageSnapshot.endedAt);
|
|
104632
|
+
}
|
|
104521
104633
|
input.activeStore.recordStageEnd(input.runId, stageSnapshot);
|
|
104522
104634
|
input.opts.onStageEnd?.(input.runId, stageSnapshot);
|
|
104523
104635
|
appendStageEndForSnapshot();
|
|
@@ -104585,6 +104697,34 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104585
104697
|
// dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts
|
|
104586
104698
|
import { runCallback as runCallback3, runSynchronousCallback } from "@bastani/atomic";
|
|
104587
104699
|
|
|
104700
|
+
// dist/builtin/workflows/src/shared/pending-stage-route-readiness.ts
|
|
104701
|
+
var owners = new WeakMap;
|
|
104702
|
+
function registerWorkflowPendingStageRouteReadiness(store, ready) {
|
|
104703
|
+
owners.get(store)?.retire();
|
|
104704
|
+
const controller = new AbortController;
|
|
104705
|
+
const owner = {
|
|
104706
|
+
ready(runId) {
|
|
104707
|
+
const completion = ready(runId);
|
|
104708
|
+
return completion === undefined ? undefined : {
|
|
104709
|
+
completion: raceAbort2(completion, controller.signal),
|
|
104710
|
+
assertCurrent: () => controller.signal.throwIfAborted()
|
|
104711
|
+
};
|
|
104712
|
+
},
|
|
104713
|
+
retire() {
|
|
104714
|
+
controller.abort(new Error("atomic-workflows: Intercom route authority owner retired before stage startup"));
|
|
104715
|
+
}
|
|
104716
|
+
};
|
|
104717
|
+
owners.set(store, owner);
|
|
104718
|
+
return () => {
|
|
104719
|
+
owner.retire();
|
|
104720
|
+
if (owners.get(store) === owner)
|
|
104721
|
+
owners.delete(store);
|
|
104722
|
+
};
|
|
104723
|
+
}
|
|
104724
|
+
function workflowPendingStageRouteReady(store, runId) {
|
|
104725
|
+
return owners.get(store)?.ready(runId);
|
|
104726
|
+
}
|
|
104727
|
+
|
|
104588
104728
|
// dist/builtin/workflows/src/runs/foreground/executor-queued-user-message.ts
|
|
104589
104729
|
function removedMessages(before, after) {
|
|
104590
104730
|
const remaining = [...after];
|
|
@@ -105439,7 +105579,7 @@ function createReplayStageContext(input) {
|
|
|
105439
105579
|
name,
|
|
105440
105580
|
parentIds: stageSnapshot.parentIds,
|
|
105441
105581
|
...stageReplayFields(stageSnapshot),
|
|
105442
|
-
ts: stageSnapshot.startedAt
|
|
105582
|
+
ts: stageSnapshot.startedAt
|
|
105443
105583
|
});
|
|
105444
105584
|
};
|
|
105445
105585
|
const appendReplayStageEnd = () => {
|
|
@@ -105449,7 +105589,8 @@ function createReplayStageContext(input) {
|
|
|
105449
105589
|
runId,
|
|
105450
105590
|
stageId,
|
|
105451
105591
|
status: stageSnapshot.status,
|
|
105452
|
-
durationMs: stageSnapshot.durationMs
|
|
105592
|
+
durationMs: stageSnapshot.durationMs,
|
|
105593
|
+
endedAt: stageSnapshot.endedAt,
|
|
105453
105594
|
...stageSnapshot.status === "completed" && stageSnapshot.result !== undefined ? { summary: stageSnapshot.result } : {},
|
|
105454
105595
|
...stageSnapshot.skippedReason !== undefined ? { skippedReason: stageSnapshot.skippedReason } : {},
|
|
105455
105596
|
...stageSnapshot.sessionId !== undefined ? { sessionId: stageSnapshot.sessionId } : {},
|
|
@@ -105467,8 +105608,6 @@ function createReplayStageContext(input) {
|
|
|
105467
105608
|
delete stageSnapshot.result;
|
|
105468
105609
|
stageSnapshot.skippedReason = input.workflowExitSkippedReason(reason);
|
|
105469
105610
|
}
|
|
105470
|
-
stageSnapshot.endedAt = Date.now();
|
|
105471
|
-
stageSnapshot.durationMs = elapsedStageMs(stageSnapshot, stageSnapshot.endedAt);
|
|
105472
105611
|
input.activeStore.recordStageEnd(runId, stageSnapshot);
|
|
105473
105612
|
input.opts.onStageEnd?.(runId, stageSnapshot);
|
|
105474
105613
|
appendReplayStageEnd();
|
|
@@ -106724,16 +106863,52 @@ function stageSessionExtensionRunner(current) {
|
|
|
106724
106863
|
}
|
|
106725
106864
|
return;
|
|
106726
106865
|
}
|
|
106866
|
+
var shutdowns = new WeakMap;
|
|
106867
|
+
function shutdownStageSession(current) {
|
|
106868
|
+
if (!current)
|
|
106869
|
+
return Promise.resolve();
|
|
106870
|
+
const existing = shutdowns.get(current);
|
|
106871
|
+
if (existing)
|
|
106872
|
+
return existing;
|
|
106873
|
+
const shutdown = Promise.resolve().then(async () => {
|
|
106874
|
+
const runner = stageSessionExtensionRunner(current);
|
|
106875
|
+
if (runner?.hasHandlers("session_shutdown"))
|
|
106876
|
+
await runner.emit({ type: "session_shutdown", reason: "quit" });
|
|
106877
|
+
});
|
|
106878
|
+
shutdowns.set(current, shutdown);
|
|
106879
|
+
return shutdown;
|
|
106880
|
+
}
|
|
106881
|
+
|
|
106882
|
+
class StageSessionBindingCleanupFailure extends AggregateError {
|
|
106883
|
+
constructor(bindingError, cleanupErrors) {
|
|
106884
|
+
super([bindingError, ...cleanupErrors], "atomic-workflows: failed binding cleanup did not release session ownership", {
|
|
106885
|
+
cause: bindingError
|
|
106886
|
+
});
|
|
106887
|
+
this.name = "StageSessionBindingCleanupFailure";
|
|
106888
|
+
}
|
|
106889
|
+
}
|
|
106890
|
+
async function cleanupFailedStageSessionBinding(current, bindingError) {
|
|
106891
|
+
const cleanupErrors = [];
|
|
106892
|
+
try {
|
|
106893
|
+
await shutdownStageSession(current);
|
|
106894
|
+
} catch (error) {
|
|
106895
|
+
cleanupErrors.push(error);
|
|
106896
|
+
}
|
|
106897
|
+
try {
|
|
106898
|
+
await current.dispose();
|
|
106899
|
+
} catch (error) {
|
|
106900
|
+
cleanupErrors.push(error);
|
|
106901
|
+
}
|
|
106902
|
+
if (cleanupErrors.length > 0)
|
|
106903
|
+
throw new StageSessionBindingCleanupFailure(bindingError, cleanupErrors);
|
|
106904
|
+
}
|
|
106727
106905
|
async function disposeStageSession(current) {
|
|
106728
106906
|
if (!current)
|
|
106729
106907
|
return;
|
|
106730
|
-
|
|
106731
|
-
|
|
106732
|
-
|
|
106733
|
-
|
|
106734
|
-
} catch (error) {
|
|
106735
|
-
console.error("atomic-workflows: stage session_shutdown handler failed", error);
|
|
106736
|
-
}
|
|
106908
|
+
try {
|
|
106909
|
+
await shutdownStageSession(current);
|
|
106910
|
+
} catch (error) {
|
|
106911
|
+
console.error("atomic-workflows: stage session_shutdown handler failed", error);
|
|
106737
106912
|
}
|
|
106738
106913
|
await current.dispose();
|
|
106739
106914
|
}
|
|
@@ -107047,6 +107222,27 @@ function terminatingToolCallId(event) {
|
|
|
107047
107222
|
return typeof callId === "string" && callId.length > 0 ? callId : undefined;
|
|
107048
107223
|
}
|
|
107049
107224
|
|
|
107225
|
+
// dist/builtin/workflows/src/runs/foreground/stage-startup-wait.ts
|
|
107226
|
+
function waitForStageStartup(operation, signal) {
|
|
107227
|
+
return new Promise((resolve, reject) => {
|
|
107228
|
+
const onAbort = () => {
|
|
107229
|
+
signal.removeEventListener("abort", onAbort);
|
|
107230
|
+
reject(signal.reason ?? new DOMException("Stage startup cancelled", "AbortError"));
|
|
107231
|
+
};
|
|
107232
|
+
operation.then((value2) => {
|
|
107233
|
+
signal.removeEventListener("abort", onAbort);
|
|
107234
|
+
resolve(value2);
|
|
107235
|
+
}, (error) => {
|
|
107236
|
+
signal.removeEventListener("abort", onAbort);
|
|
107237
|
+
reject(error);
|
|
107238
|
+
});
|
|
107239
|
+
if (signal.aborted)
|
|
107240
|
+
onAbort();
|
|
107241
|
+
else
|
|
107242
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
107243
|
+
});
|
|
107244
|
+
}
|
|
107245
|
+
|
|
107050
107246
|
// dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts
|
|
107051
107247
|
function hasMeaningfulUsage(usage) {
|
|
107052
107248
|
if (usage === undefined)
|
|
@@ -107127,9 +107323,14 @@ class StageSessionController {
|
|
|
107127
107323
|
activeCreation;
|
|
107128
107324
|
ownedCreationPromise;
|
|
107129
107325
|
abortGeneration = 0;
|
|
107326
|
+
routeAuthorityWait;
|
|
107327
|
+
startupWait = new AbortController;
|
|
107328
|
+
startup;
|
|
107130
107329
|
abortReason;
|
|
107131
107330
|
abortReasonGeneration = 0;
|
|
107132
107331
|
sessionPromise;
|
|
107332
|
+
sessionShutdownPromise;
|
|
107333
|
+
bindingCleanupFailure;
|
|
107133
107334
|
reattachSessionFile;
|
|
107134
107335
|
lastPromptStartIndex;
|
|
107135
107336
|
attemptUsageStartIndex;
|
|
@@ -107246,8 +107447,7 @@ class StageSessionController {
|
|
|
107246
107447
|
this.pendingFallbackWarnings.push(`[fallback] ${candidateLabel(candidate)} failed: ${error}. Retrying with ${candidateLabel(nextCandidate)}.`);
|
|
107247
107448
|
this.modelWarnings.push(...this.pendingFallbackWarnings);
|
|
107248
107449
|
this.pendingFallbackWarnings.length = 0;
|
|
107249
|
-
await this.disposeCurrentSession();
|
|
107250
|
-
this.activeCandidateIndex = index + 1;
|
|
107450
|
+
await this.disposeCurrentSession(index + 1);
|
|
107251
107451
|
this.notifyModelFallbackMetaChange();
|
|
107252
107452
|
return true;
|
|
107253
107453
|
}
|
|
@@ -107275,28 +107475,41 @@ class StageSessionController {
|
|
|
107275
107475
|
this.session?.setThinkingLevel(level);
|
|
107276
107476
|
}
|
|
107277
107477
|
async ensureSession(consumer = "prompt") {
|
|
107478
|
+
if (this.bindingCleanupFailure !== undefined)
|
|
107479
|
+
throw this.bindingCleanupFailure;
|
|
107480
|
+
if (this.sessionShutdownPromise !== undefined) {
|
|
107481
|
+
const generation = this.abortGeneration;
|
|
107482
|
+
await this.sessionShutdownPromise;
|
|
107483
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== generation)
|
|
107484
|
+
throw this.staleCreationReason(generation);
|
|
107485
|
+
}
|
|
107278
107486
|
if (this.disposed)
|
|
107279
107487
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
107280
|
-
|
|
107488
|
+
this.opts.signal?.throwIfAborted();
|
|
107489
|
+
if (this.session !== undefined && this.activeCreation === undefined)
|
|
107281
107490
|
return this.session;
|
|
107282
107491
|
if (!this.sessionPromise) {
|
|
107492
|
+
this.beginStartup();
|
|
107283
107493
|
const pending = this.createInitialSession(consumer);
|
|
107284
107494
|
this.sessionPromise = pending;
|
|
107285
107495
|
this.ownedCreationPromise = pending;
|
|
107286
|
-
const release = () => {
|
|
107496
|
+
const release = (failed = false) => {
|
|
107287
107497
|
if (this.ownedCreationPromise === pending)
|
|
107288
107498
|
this.ownedCreationPromise = undefined;
|
|
107499
|
+
this.settleStartup(failed);
|
|
107289
107500
|
};
|
|
107290
|
-
pending.then(release, () => {
|
|
107291
|
-
release();
|
|
107292
|
-
if (this.sessionPromise === pending)
|
|
107501
|
+
pending.then(() => release(), () => {
|
|
107502
|
+
release(true);
|
|
107503
|
+
if (this.sessionPromise === pending) {
|
|
107293
107504
|
this.sessionPromise = undefined;
|
|
107505
|
+
this.activeCandidateIndex = undefined;
|
|
107506
|
+
}
|
|
107294
107507
|
});
|
|
107295
107508
|
}
|
|
107296
|
-
return this.sessionPromise;
|
|
107509
|
+
return waitForStageStartup(this.sessionPromise, this.startupWait.signal);
|
|
107297
107510
|
}
|
|
107298
107511
|
async ensureSessionFromFile(sessionFile, consumer = "prompt") {
|
|
107299
|
-
if (!this.sessionPromise && !this.session)
|
|
107512
|
+
if (!this.sessionShutdownPromise && !this.sessionPromise && !this.session)
|
|
107300
107513
|
this.reattachSessionFile = sessionFile;
|
|
107301
107514
|
const session = await this.ensureSession(consumer);
|
|
107302
107515
|
await session.closeWorkflowStageGeneration?.();
|
|
@@ -107341,6 +107554,10 @@ class StageSessionController {
|
|
|
107341
107554
|
this.artifactCapture.close();
|
|
107342
107555
|
}
|
|
107343
107556
|
async promptWithFallback(text, sdkOptions, consumer = "prompt") {
|
|
107557
|
+
if (this.session !== undefined && this.activeCreation === undefined && this.ownedCreationPromise === undefined && this.startupWait.signal.aborted) {
|
|
107558
|
+
this.opts.signal?.throwIfAborted();
|
|
107559
|
+
this.startupWait = new AbortController;
|
|
107560
|
+
}
|
|
107344
107561
|
if (!this.hasExplicitModelFallbackConfig) {
|
|
107345
107562
|
try {
|
|
107346
107563
|
const activeSession = await this.ensureSession(consumer);
|
|
@@ -107363,7 +107580,13 @@ class StageSessionController {
|
|
|
107363
107580
|
}
|
|
107364
107581
|
return;
|
|
107365
107582
|
}
|
|
107366
|
-
const
|
|
107583
|
+
const readinessOwner = this.ownedCreationPromise ?? this.activeCreation;
|
|
107584
|
+
if (readinessOwner !== undefined)
|
|
107585
|
+
await waitForStageStartup(readinessOwner, this.startupWait.signal);
|
|
107586
|
+
if (this.session === undefined)
|
|
107587
|
+
this.beginStartup();
|
|
107588
|
+
const startupSignal = this.startupWait.signal;
|
|
107589
|
+
const candidates = await waitForStageStartup(this.modelCandidates(), startupSignal);
|
|
107367
107590
|
if (candidates.length === 0) {
|
|
107368
107591
|
try {
|
|
107369
107592
|
const activeSession = await this.ensureSession(consumer);
|
|
@@ -107379,14 +107602,9 @@ class StageSessionController {
|
|
|
107379
107602
|
}
|
|
107380
107603
|
return;
|
|
107381
107604
|
}
|
|
107382
|
-
|
|
107383
|
-
|
|
107384
|
-
|
|
107385
|
-
} catch (error) {
|
|
107386
|
-
if (error instanceof StageSessionCreationCancelled)
|
|
107387
|
-
return;
|
|
107388
|
-
}
|
|
107389
|
-
}
|
|
107605
|
+
const creationOwner = this.ownedCreationPromise ?? this.activeCreation;
|
|
107606
|
+
if (creationOwner !== undefined)
|
|
107607
|
+
await waitForStageStartup(creationOwner, startupSignal);
|
|
107390
107608
|
const resumedText = this.pendingCreationResumeMessage;
|
|
107391
107609
|
this.pendingCreationResumeMessage = undefined;
|
|
107392
107610
|
let promptText = resumedText ?? text;
|
|
@@ -107394,9 +107612,21 @@ class StageSessionController {
|
|
|
107394
107612
|
return;
|
|
107395
107613
|
let index = this.activeCandidateIndex ?? 0;
|
|
107396
107614
|
while (index < candidates.length) {
|
|
107615
|
+
if (this.ownedCreationPromise !== undefined || this.activeCreation !== undefined) {
|
|
107616
|
+
try {
|
|
107617
|
+
await waitForStageStartup(this.ownedCreationPromise ?? this.activeCreation, startupSignal);
|
|
107618
|
+
} catch (error) {
|
|
107619
|
+
if (error instanceof StageSessionCreationCancelled)
|
|
107620
|
+
return;
|
|
107621
|
+
throw error;
|
|
107622
|
+
}
|
|
107623
|
+
index = this.activeCandidateIndex ?? index;
|
|
107624
|
+
promptText = this.pendingCreationResumeMessage ?? promptText;
|
|
107625
|
+
this.pendingCreationResumeMessage = undefined;
|
|
107626
|
+
}
|
|
107397
107627
|
const candidate = candidates[index];
|
|
107398
107628
|
try {
|
|
107399
|
-
const created = this.session && this.activeCandidateIndex === index ? this.session : await this.createSessionWithThrownErrorRetry(candidate, consumer);
|
|
107629
|
+
const created = this.session && this.activeCandidateIndex === index ? this.session : await waitForStageStartup(this.createSessionWithThrownErrorRetry(candidate, consumer), startupSignal);
|
|
107400
107630
|
if (isSessionCreationPauseResult(created)) {
|
|
107401
107631
|
if (created.resumeMessage === undefined)
|
|
107402
107632
|
return;
|
|
@@ -107423,8 +107653,10 @@ class StageSessionController {
|
|
|
107423
107653
|
const failure = await this.handleCandidateFailure(err, candidate, candidates, index);
|
|
107424
107654
|
if (failure === "handled")
|
|
107425
107655
|
return;
|
|
107426
|
-
if (failure === "throw")
|
|
107656
|
+
if (failure === "throw") {
|
|
107657
|
+
this.settleStartup(true);
|
|
107427
107658
|
throw err;
|
|
107659
|
+
}
|
|
107428
107660
|
index += 1;
|
|
107429
107661
|
}
|
|
107430
107662
|
}
|
|
@@ -107467,7 +107699,8 @@ class StageSessionController {
|
|
|
107467
107699
|
this.messageAdmission.dispose();
|
|
107468
107700
|
this.deliveryActivity.dispose();
|
|
107469
107701
|
await this.replacement.dispose();
|
|
107470
|
-
|
|
107702
|
+
if (this.activeCreation === undefined)
|
|
107703
|
+
await disposeStageSession(this.session);
|
|
107471
107704
|
}
|
|
107472
107705
|
async drainPendingDisposal() {
|
|
107473
107706
|
if (!this.pendingDisposal)
|
|
@@ -107541,6 +107774,12 @@ class StageSessionController {
|
|
|
107541
107774
|
this.abortGeneration += 1;
|
|
107542
107775
|
this.abortReason = reason;
|
|
107543
107776
|
this.abortReasonGeneration = this.abortGeneration;
|
|
107777
|
+
this.routeAuthorityWait?.abort(reason);
|
|
107778
|
+
this.startupWait.abort(reason);
|
|
107779
|
+
if (this.startup?.state === "active") {
|
|
107780
|
+
this.startup = { ...this.startup, state: "cancelled" };
|
|
107781
|
+
this.opts.onStartupChange?.(this.startup);
|
|
107782
|
+
}
|
|
107544
107783
|
this.abortThrownErrorRetries(reason);
|
|
107545
107784
|
}
|
|
107546
107785
|
pauseThrownErrorRetries(resume) {
|
|
@@ -107781,11 +108020,15 @@ class StageSessionController {
|
|
|
107781
108020
|
return this.candidatesPromise;
|
|
107782
108021
|
}
|
|
107783
108022
|
async createInitialSession(consumer) {
|
|
108023
|
+
const generation = this.abortGeneration;
|
|
107784
108024
|
if (!this.hasExplicitModelFallbackConfig) {
|
|
107785
108025
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107786
108026
|
}
|
|
107787
108027
|
const candidates = await this.modelCandidates();
|
|
107788
|
-
|
|
108028
|
+
if (this.abortGeneration !== generation || this.opts.signal?.aborted || this.disposed)
|
|
108029
|
+
throw this.staleCreationReason(generation);
|
|
108030
|
+
const initialIndex = this.activeCandidateIndex ?? 0;
|
|
108031
|
+
const first = candidates[initialIndex];
|
|
107789
108032
|
if (first === undefined) {
|
|
107790
108033
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107791
108034
|
}
|
|
@@ -107798,9 +108041,9 @@ class StageSessionController {
|
|
|
107798
108041
|
this.resumeCurrentSession = true;
|
|
107799
108042
|
return resumed;
|
|
107800
108043
|
}
|
|
107801
|
-
this.activeCandidateIndex =
|
|
108044
|
+
this.activeCandidateIndex = initialIndex;
|
|
107802
108045
|
this.selectedModel = first.id;
|
|
107803
|
-
return this.createSessionObservingPause(first, consumer).catch((error) => this.createInitialSessionCandidateWalk(candidates, consumer,
|
|
108046
|
+
return this.createSessionObservingPause(first, consumer).catch((error) => this.createInitialSessionCandidateWalk(candidates, consumer, initialIndex, { error }));
|
|
107804
108047
|
}
|
|
107805
108048
|
async createInitialSessionCandidateWalk(candidates, consumer, startIndex, initialFailure) {
|
|
107806
108049
|
let index = startIndex;
|
|
@@ -107882,11 +108125,13 @@ class StageSessionController {
|
|
|
107882
108125
|
}
|
|
107883
108126
|
return await this.createSessionObservingPause(candidate, consumer);
|
|
107884
108127
|
} catch (error) {
|
|
108128
|
+
if (error instanceof StageSessionBindingCleanupFailure)
|
|
108129
|
+
throw error;
|
|
107885
108130
|
const errorSettingsManager = retrySettingsManagerFromError(error);
|
|
107886
108131
|
if (errorSettingsManager !== undefined)
|
|
107887
108132
|
this.sessionSettingsManager = errorSettingsManager;
|
|
107888
108133
|
const decision = isWorkflowPendingStageDeliveryFailure(error) ? undefined : nextRetryDecision(this.retrySettings(), retryAttempt, isRetryableSameModelFailure(error));
|
|
107889
|
-
if (decision === undefined || this.disposed || this.opts.signal?.aborted === true || this.capturedStructuredOutputForAttempt()) {
|
|
108134
|
+
if (decision === undefined || this.disposed || this.opts.signal?.aborted === true || this.startupWait.signal.aborted || this.capturedStructuredOutputForAttempt()) {
|
|
107890
108135
|
throw error;
|
|
107891
108136
|
}
|
|
107892
108137
|
retryAttempt = decision.attempt;
|
|
@@ -107915,16 +108160,86 @@ class StageSessionController {
|
|
|
107915
108160
|
}
|
|
107916
108161
|
}
|
|
107917
108162
|
createSession(candidate, consumer, resumeOptions) {
|
|
108163
|
+
if (this.bindingCleanupFailure !== undefined)
|
|
108164
|
+
return Promise.reject(this.bindingCleanupFailure);
|
|
108165
|
+
if (this.sessionShutdownPromise !== undefined) {
|
|
108166
|
+
const generation = this.abortGeneration;
|
|
108167
|
+
return this.sessionShutdownPromise.then(() => {
|
|
108168
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== generation)
|
|
108169
|
+
throw this.staleCreationReason(generation);
|
|
108170
|
+
return this.createSession(candidate, consumer, resumeOptions);
|
|
108171
|
+
});
|
|
108172
|
+
}
|
|
108173
|
+
if (this.activeCreation !== undefined)
|
|
108174
|
+
return this.activeCreation;
|
|
108175
|
+
if (this.session !== undefined)
|
|
108176
|
+
return Promise.resolve(this.session);
|
|
108177
|
+
this.startupWait.signal.throwIfAborted();
|
|
107918
108178
|
const creation = this.createSessionAttempt(candidate, consumer, resumeOptions);
|
|
107919
108179
|
this.activeCreation = creation;
|
|
107920
108180
|
creation.finally(() => {
|
|
107921
108181
|
if (this.activeCreation === creation)
|
|
107922
108182
|
this.activeCreation = undefined;
|
|
108183
|
+
this.settleStartup();
|
|
107923
108184
|
}).catch(() => {});
|
|
107924
108185
|
return creation;
|
|
107925
108186
|
}
|
|
108187
|
+
settleStartup(failed = false) {
|
|
108188
|
+
if (this.activeCreation !== undefined || this.ownedCreationPromise !== undefined || this.startup === undefined)
|
|
108189
|
+
return;
|
|
108190
|
+
if (this.startup.state === "dispatched" || this.startup.phase === "ready")
|
|
108191
|
+
return;
|
|
108192
|
+
if (this.startup.state === "active" && !failed && this.bindingCleanupFailure === undefined)
|
|
108193
|
+
return;
|
|
108194
|
+
this.startup = {
|
|
108195
|
+
...this.startup,
|
|
108196
|
+
state: this.startup.state === "active" ? "failed" : this.startup.state,
|
|
108197
|
+
ownershipPending: this.bindingCleanupFailure !== undefined,
|
|
108198
|
+
...this.bindingCleanupFailure === undefined ? { settledAt: Date.now() } : {}
|
|
108199
|
+
};
|
|
108200
|
+
this.opts.onStartupChange?.(this.startup);
|
|
108201
|
+
}
|
|
108202
|
+
beginStartup() {
|
|
108203
|
+
if (this.activeCreation !== undefined || this.ownedCreationPromise !== undefined || this.sessionPromise !== undefined)
|
|
108204
|
+
return;
|
|
108205
|
+
this.opts.signal?.throwIfAborted();
|
|
108206
|
+
if (this.startupWait.signal.aborted)
|
|
108207
|
+
this.startupWait = new AbortController;
|
|
108208
|
+
this.reportStartupPhase("model-resolution", true);
|
|
108209
|
+
}
|
|
108210
|
+
reportStartupPhase(phase, reset = false) {
|
|
108211
|
+
if (!reset && this.startup !== undefined && this.startup.state !== "active")
|
|
108212
|
+
return;
|
|
108213
|
+
const now = Date.now();
|
|
108214
|
+
this.startup = {
|
|
108215
|
+
phase,
|
|
108216
|
+
startedAt: reset ? now : this.startup?.startedAt ?? now,
|
|
108217
|
+
phaseStartedAt: now,
|
|
108218
|
+
state: phase === "first-dispatch" ? "dispatched" : "active",
|
|
108219
|
+
ownershipPending: phase !== "first-dispatch" && phase !== "ready"
|
|
108220
|
+
};
|
|
108221
|
+
this.opts.onStartupChange?.(this.startup);
|
|
108222
|
+
}
|
|
107926
108223
|
async createSessionAttempt(candidate, consumer, resumeOptions) {
|
|
107927
108224
|
const startGeneration = this.abortGeneration;
|
|
108225
|
+
if (this.disposed || this.opts.signal?.aborted)
|
|
108226
|
+
throw this.staleCreationReason(startGeneration);
|
|
108227
|
+
this.reportStartupPhase("route-authority");
|
|
108228
|
+
const authority = this.opts.routeAuthorityReady?.();
|
|
108229
|
+
if (authority !== undefined) {
|
|
108230
|
+
const wait = new AbortController;
|
|
108231
|
+
this.routeAuthorityWait = wait;
|
|
108232
|
+
try {
|
|
108233
|
+
await raceAbort2(authority.completion, wait.signal);
|
|
108234
|
+
authority.assertCurrent();
|
|
108235
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== startGeneration)
|
|
108236
|
+
throw this.staleCreationReason(startGeneration);
|
|
108237
|
+
} finally {
|
|
108238
|
+
if (this.routeAuthorityWait === wait)
|
|
108239
|
+
this.routeAuthorityWait = undefined;
|
|
108240
|
+
}
|
|
108241
|
+
}
|
|
108242
|
+
this.reportStartupPhase("resource-preparation");
|
|
107928
108243
|
this.applyCandidateThinking(candidate);
|
|
107929
108244
|
const stageOptions = buildStageSessionOptions({
|
|
107930
108245
|
effectiveStageOptions: this.effectiveStageOptions,
|
|
@@ -107937,10 +108252,19 @@ class StageSessionController {
|
|
|
107937
108252
|
try {
|
|
107938
108253
|
created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta, this.opts.pendingStageDelivery), {
|
|
107939
108254
|
...this.meta,
|
|
108255
|
+
startupSignal: this.startupWait.signal,
|
|
108256
|
+
onStartupPhase: (phase) => {
|
|
108257
|
+
if (this.abortGeneration === startGeneration)
|
|
108258
|
+
this.reportStartupPhase(phase);
|
|
108259
|
+
},
|
|
107940
108260
|
stageOptions,
|
|
107941
108261
|
...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
|
|
107942
108262
|
}) : missingAdapter(consumer);
|
|
107943
108263
|
} catch (error) {
|
|
108264
|
+
if (error instanceof StageSessionBindingCleanupFailure) {
|
|
108265
|
+
this.bindingCleanupFailure = error;
|
|
108266
|
+
throw error;
|
|
108267
|
+
}
|
|
107944
108268
|
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration)
|
|
107945
108269
|
throw this.disposed ? new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`) : this.staleCreationReason(startGeneration);
|
|
107946
108270
|
throw error;
|
|
@@ -107951,20 +108275,28 @@ class StageSessionController {
|
|
|
107951
108275
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
107952
108276
|
throw this.staleCreationReason(startGeneration);
|
|
107953
108277
|
}
|
|
108278
|
+
this.reportStartupPhase("session-attachment");
|
|
107954
108279
|
const session = attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
|
|
107955
108280
|
const attachedSession = session instanceof Promise ? await session : session;
|
|
107956
|
-
|
|
107957
|
-
|
|
108281
|
+
this.reportStartupPhase("delivery-readiness");
|
|
108282
|
+
try {
|
|
108283
|
+
await this.sharedOrchestrationContext?.pendingStageDelivery?.ready();
|
|
108284
|
+
await this.opts.onSessionReady?.();
|
|
108285
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== startGeneration)
|
|
108286
|
+
throw this.staleCreationReason(startGeneration);
|
|
108287
|
+
} catch (reason) {
|
|
108288
|
+
if (this.session === attachedSession)
|
|
108289
|
+
this.session = undefined;
|
|
107958
108290
|
try {
|
|
107959
|
-
await
|
|
108291
|
+
await cleanupFailedStageSessionBinding(attachedSession, reason);
|
|
107960
108292
|
} catch (error) {
|
|
107961
|
-
if (
|
|
107962
|
-
this.
|
|
107963
|
-
await disposeStageSession(attachedSession).catch(() => {});
|
|
108293
|
+
if (error instanceof StageSessionBindingCleanupFailure)
|
|
108294
|
+
this.bindingCleanupFailure = error;
|
|
107964
108295
|
throw error;
|
|
107965
108296
|
}
|
|
108297
|
+
throw reason;
|
|
107966
108298
|
}
|
|
107967
|
-
|
|
108299
|
+
this.reportStartupPhase("ready");
|
|
107968
108300
|
return attachedSession;
|
|
107969
108301
|
}
|
|
107970
108302
|
attachSession(created) {
|
|
@@ -108004,12 +108336,16 @@ class StageSessionController {
|
|
|
108004
108336
|
});
|
|
108005
108337
|
return result.session;
|
|
108006
108338
|
}
|
|
108007
|
-
async disposeCurrentSession() {
|
|
108339
|
+
async disposeCurrentSession(nextCandidateIndex) {
|
|
108340
|
+
if (this.sessionShutdownPromise !== undefined)
|
|
108341
|
+
await this.sessionShutdownPromise;
|
|
108342
|
+
const startGeneration = this.abortGeneration;
|
|
108008
108343
|
this.abortThrownErrorRetries(new Error(`atomic-workflows: stage "${this.opts.stageName}" session was replaced`));
|
|
108009
108344
|
const current = this.session;
|
|
108010
108345
|
this.messageAdmission.reset();
|
|
108011
108346
|
this.replacement.retire(current);
|
|
108012
108347
|
this.session = undefined;
|
|
108348
|
+
this.activeCandidateIndex = nextCandidateIndex;
|
|
108013
108349
|
if (this.sessionPromise !== this.ownedCreationPromise)
|
|
108014
108350
|
this.sessionPromise = undefined;
|
|
108015
108351
|
this.sessionSettingsManager = undefined;
|
|
@@ -108020,6 +108356,15 @@ class StageSessionController {
|
|
|
108020
108356
|
this.unsubscribeTerminateWatcher?.();
|
|
108021
108357
|
this.unsubscribeTerminateWatcher = undefined;
|
|
108022
108358
|
this.terminatingToolCallIds.clear();
|
|
108359
|
+
const shutdown = Promise.resolve().then(() => shutdownStageSession(current));
|
|
108360
|
+
this.sessionShutdownPromise = shutdown;
|
|
108361
|
+
shutdown.then(() => {
|
|
108362
|
+
if (this.sessionShutdownPromise === shutdown)
|
|
108363
|
+
this.sessionShutdownPromise = undefined;
|
|
108364
|
+
}, () => {});
|
|
108365
|
+
await shutdown;
|
|
108366
|
+
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration)
|
|
108367
|
+
throw this.staleCreationReason(startGeneration);
|
|
108023
108368
|
}
|
|
108024
108369
|
async promptWithPauseResume(activeSession, initialText, sdkOptions) {
|
|
108025
108370
|
let nextText = initialText;
|
|
@@ -108037,6 +108382,7 @@ class StageSessionController {
|
|
|
108037
108382
|
this.lastPromptStartIndex = promptStartIndex;
|
|
108038
108383
|
this.unresolvedContextOverflowMessage = undefined;
|
|
108039
108384
|
try {
|
|
108385
|
+
this.reportStartupPhase("first-dispatch");
|
|
108040
108386
|
await activeSession.prompt(nextText, sdkOptions);
|
|
108041
108387
|
const pendingPauseAfterPrompt = this.pauseControl.currentResume();
|
|
108042
108388
|
if (pendingPauseAfterPrompt) {
|
|
@@ -108129,12 +108475,13 @@ class StageSessionController {
|
|
|
108129
108475
|
throw err;
|
|
108130
108476
|
}
|
|
108131
108477
|
this.pendingFallbackWarnings.push(resumedOverflowNextIndex === undefined ? `[fallback] resume on ${resumedLabel} failed: ${message}. Restarting fallback from ${candidateLabel(candidates[0])}.` : `[fallback] resume on ${resumedLabel} failed: ${message}. Retrying with ${candidateLabel(candidates[resumedOverflowNextIndex])}.`);
|
|
108132
|
-
await this.disposeCurrentSession();
|
|
108133
|
-
this.activeCandidateIndex = resumedOverflowNextIndex;
|
|
108478
|
+
await this.disposeCurrentSession(resumedOverflowNextIndex);
|
|
108134
108479
|
return false;
|
|
108135
108480
|
}
|
|
108136
108481
|
}
|
|
108137
108482
|
async handleCandidateFailure(err, candidate, candidates, index) {
|
|
108483
|
+
if (err instanceof StageSessionBindingCleanupFailure)
|
|
108484
|
+
throw err;
|
|
108138
108485
|
const message = errorMessage4(err);
|
|
108139
108486
|
const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
|
|
108140
108487
|
if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
|
|
@@ -108150,7 +108497,7 @@ class StageSessionController {
|
|
|
108150
108497
|
...usage === undefined ? {} : { usage },
|
|
108151
108498
|
error: message
|
|
108152
108499
|
});
|
|
108153
|
-
if (this.opts.signal?.aborted || terminalStageDelivery || !isRetryableModelFailure(err) || index === candidates.length - 1) {
|
|
108500
|
+
if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !isRetryableModelFailure(err) || index === candidates.length - 1) {
|
|
108154
108501
|
this.modelWarnings.push(...this.pendingFallbackWarnings);
|
|
108155
108502
|
this.pendingFallbackWarnings.length = 0;
|
|
108156
108503
|
this.notifyModelFallbackMetaChange();
|
|
@@ -108158,7 +108505,7 @@ class StageSessionController {
|
|
|
108158
108505
|
}
|
|
108159
108506
|
const nextCandidate = candidates[index + 1];
|
|
108160
108507
|
this.pendingFallbackWarnings.push(`[fallback] ${candidateLabel(candidate)} failed: ${message}. Retrying with ${candidateLabel(nextCandidate)}.`);
|
|
108161
|
-
await this.disposeCurrentSession();
|
|
108508
|
+
await this.disposeCurrentSession(index + 1);
|
|
108162
108509
|
return "retry";
|
|
108163
108510
|
}
|
|
108164
108511
|
capturedStructuredOutputForAttempt() {
|
|
@@ -108799,9 +109146,7 @@ function createWorkflowStageFactory(input) {
|
|
|
108799
109146
|
toolEvents: [],
|
|
108800
109147
|
pendingStageDeliveryAvailable,
|
|
108801
109148
|
...shouldReplay ? {
|
|
108802
|
-
|
|
108803
|
-
endedAt: Date.now(),
|
|
108804
|
-
durationMs: 0,
|
|
109149
|
+
...stageTimingFields(replaySource),
|
|
108805
109150
|
...replaySource.result !== undefined ? { result: replaySource.result } : {},
|
|
108806
109151
|
...replaySource.sessionId !== undefined ? { sessionId: replaySource.sessionId } : {},
|
|
108807
109152
|
...replaySource.sessionFile !== undefined ? { sessionFile: replaySource.sessionFile } : {},
|
|
@@ -108864,11 +109209,19 @@ function createWorkflowStageFactory(input) {
|
|
|
108864
109209
|
signal: input.signal,
|
|
108865
109210
|
stageOptions: stageOptionsForContext,
|
|
108866
109211
|
...pendingStageDeliveryAvailable ? {
|
|
109212
|
+
routeAuthorityReady: () => workflowPendingStageRouteReady(input.activeStore, input.runId),
|
|
108867
109213
|
pendingStageDelivery: createWorkflowPendingStageDelivery(input.activeStore, input.runId, stageId, name)
|
|
108868
109214
|
} : {},
|
|
108869
109215
|
models: input.opts.models,
|
|
108870
109216
|
executionMode: input.opts.executionMode,
|
|
108871
109217
|
defaultSessionDir: input.opts.defaultSessionDir,
|
|
109218
|
+
onStartupChange(startup) {
|
|
109219
|
+
const current = input.activeStore.runs().find((run) => run.id === input.runId);
|
|
109220
|
+
if (!current?.stages.includes(stageSnapshot))
|
|
109221
|
+
return;
|
|
109222
|
+
stageSnapshot.startup = startup;
|
|
109223
|
+
input.activeStore.recordStageStart(input.runId, stageSnapshot);
|
|
109224
|
+
},
|
|
108872
109225
|
onModelFallbackMetaChange(meta) {
|
|
108873
109226
|
applyModelFallbackMeta(meta);
|
|
108874
109227
|
if (stageSnapshot.status === "running")
|
|
@@ -109031,6 +109384,7 @@ function createWorkflowStageFactory(input) {
|
|
|
109031
109384
|
stageId,
|
|
109032
109385
|
status: stageSnapshot.status,
|
|
109033
109386
|
durationMs: stageSnapshot.durationMs,
|
|
109387
|
+
endedAt: stageSnapshot.endedAt,
|
|
109034
109388
|
...stageSnapshot.error !== undefined ? { error: stageSnapshot.error } : {},
|
|
109035
109389
|
...stageSnapshot.failureKind !== undefined ? { failureKind: stageSnapshot.failureKind } : {},
|
|
109036
109390
|
...stageSnapshot.failureCode !== undefined ? { failureCode: stageSnapshot.failureCode } : {},
|
|
@@ -109636,6 +109990,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
109636
109990
|
};
|
|
109637
109991
|
};
|
|
109638
109992
|
const resolvePromptNodeTopology = createDurableStageTopologyResolver(durableBackend, runId);
|
|
109993
|
+
const priorPromptStageCheckpoints = durableBackend.listCheckpoints(runId).filter((checkpoint) => checkpoint.kind === "stage");
|
|
109639
109994
|
let promptNodeUi;
|
|
109640
109995
|
const getPromptNodeUi = () => {
|
|
109641
109996
|
promptNodeUi ??= buildPromptNodeUiAdapter({
|
|
@@ -109652,6 +110007,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
109652
110007
|
workflowExitSkippedReason: exit.workflowExitSkippedReason,
|
|
109653
110008
|
preserveWorkflowExitSkippedReason: exit.preserveWorkflowExitSkippedReason,
|
|
109654
110009
|
durableTopologyForReplayKey: resolvePromptNodeTopology,
|
|
110010
|
+
durableTimingForStageId: (stageId) => priorPromptStageCheckpoints.find((checkpoint) => checkpoint.topology?.stageId === stageId && checkpoint.topology.status === "completed" && (checkpoint.topology.run === undefined || checkpoint.topology.run.runId === runId)),
|
|
109655
110011
|
onPendingStage: async (pendingRunId, snapshot) => pendingRunId === runId ? void await recordDurableActiveStage(durableStageDeps, snapshot) : undefined
|
|
109656
110012
|
});
|
|
109657
110013
|
return promptNodeUi;
|
|
@@ -112905,11 +113261,14 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112905
113261
|
return payload.handled && await payload.completion === true;
|
|
112906
113262
|
};
|
|
112907
113263
|
const announcedRoutes = new Map;
|
|
113264
|
+
const routeCompletions = new Map;
|
|
113265
|
+
const disposeReadiness = registerWorkflowPendingStageRouteReadiness(activeStore, (runId) => routeCompletions.get(runId));
|
|
112908
113266
|
const announceRoutes = () => {
|
|
112909
113267
|
if (disposed)
|
|
112910
113268
|
return;
|
|
112911
113269
|
const ownedRunIds = new Set;
|
|
112912
113270
|
const runs = activeStore.runs();
|
|
113271
|
+
const resolveBoundarySegments = createWorkflowBoundarySegmentsResolver(runs);
|
|
112913
113272
|
for (const run of runs) {
|
|
112914
113273
|
const rootRunId = durableRootRunIdForRun(runs, run.id);
|
|
112915
113274
|
if (rootRunId === undefined)
|
|
@@ -112930,7 +113289,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112930
113289
|
...run.stages.filter((stage) => !isNonAgentStage(stage) && workflowInvocationOwnsGroup(workflowInvocationIntercomGroup(rootRunId), stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId))).map((stage) => ({
|
|
112931
113290
|
stageId: stage.id,
|
|
112932
113291
|
stageName: stage.name,
|
|
112933
|
-
target: stageRouteTarget(runs, rootRunId, run.id, stage.id),
|
|
113292
|
+
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
112934
113293
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
112935
113294
|
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status === "pending" || stage.status === "running" || stage.status === "awaiting_input" || stage.status === "paused" || stage.status === "blocked"),
|
|
112936
113295
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
@@ -112938,7 +113297,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112938
113297
|
...nonAgentNodes(run).map((node) => ({
|
|
112939
113298
|
stageId: node.id,
|
|
112940
113299
|
stageName: node.name,
|
|
112941
|
-
target: stageRouteTarget(runs, rootRunId, run.id, node.id),
|
|
113300
|
+
target: stageRouteTarget(runs, rootRunId, run.id, node.id, resolveBoundarySegments),
|
|
112942
113301
|
lifecycle: "pending",
|
|
112943
113302
|
routeEligible: false,
|
|
112944
113303
|
recipientPurpose: "control",
|
|
@@ -112957,12 +113316,17 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112957
113316
|
} catch (error) {
|
|
112958
113317
|
if (announcedRoutes.get(run.id) === entry)
|
|
112959
113318
|
announcedRoutes.delete(run.id);
|
|
113319
|
+
const failure = Promise.reject(error);
|
|
113320
|
+
failure.catch(() => {});
|
|
113321
|
+
routeCompletions.set(run.id, failure);
|
|
112960
113322
|
throw error;
|
|
112961
113323
|
}
|
|
112962
113324
|
const completion = announcement.completion;
|
|
112963
113325
|
if (completion === undefined) {
|
|
112964
113326
|
announcedRoutes.delete(run.id);
|
|
113327
|
+
routeCompletions.delete(run.id);
|
|
112965
113328
|
} else {
|
|
113329
|
+
routeCompletions.set(run.id, completion);
|
|
112966
113330
|
completion.catch(() => {
|
|
112967
113331
|
if (announcedRoutes.get(run.id) === entry)
|
|
112968
113332
|
announcedRoutes.delete(run.id);
|
|
@@ -112973,6 +113337,10 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112973
113337
|
if (!ownedRunIds.has(runId))
|
|
112974
113338
|
announcedRoutes.delete(runId);
|
|
112975
113339
|
}
|
|
113340
|
+
for (const runId of routeCompletions.keys()) {
|
|
113341
|
+
if (!ownedRunIds.has(runId))
|
|
113342
|
+
routeCompletions.delete(runId);
|
|
113343
|
+
}
|
|
112976
113344
|
sweepPromise = sweepPromise.then(() => settleUndeliverablePendingStageMessages(activeStore, notifyUndeliverable)).then(() => {
|
|
112977
113345
|
return;
|
|
112978
113346
|
}).catch((error) => reportWarning(`atomic-workflows: pending stage delivery sweep failed: ${error.message}`));
|
|
@@ -113051,6 +113419,8 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113051
113419
|
});
|
|
113052
113420
|
const dispose = () => {
|
|
113053
113421
|
disposed = true;
|
|
113422
|
+
disposeReadiness();
|
|
113423
|
+
routeCompletions.clear();
|
|
113054
113424
|
unsubscribeStore();
|
|
113055
113425
|
if (typeof subscription === "function")
|
|
113056
113426
|
subscription();
|
|
@@ -113061,8 +113431,8 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113061
113431
|
pi.on?.("session_shutdown", dispose);
|
|
113062
113432
|
return dispose;
|
|
113063
113433
|
}
|
|
113064
|
-
function stageRouteTarget(runs, rootRunId, runId, stageId) {
|
|
113065
|
-
const boundarySegments = runId === rootRunId ? [] :
|
|
113434
|
+
function stageRouteTarget(runs, rootRunId, runId, stageId, resolveBoundarySegments = (id) => workflowBoundarySegments(runs, id)) {
|
|
113435
|
+
const boundarySegments = runId === rootRunId ? [] : resolveBoundarySegments(runId);
|
|
113066
113436
|
return formatWorkflowStageTarget(rootRunId, ...boundarySegments ?? [runId], stageId);
|
|
113067
113437
|
}
|
|
113068
113438
|
function possibleStageRows(runs, rootRunId, rootRun) {
|
|
@@ -113537,6 +113907,8 @@ function resolveSessionCwd(options) {
|
|
|
113537
113907
|
return options?.cwd ?? options?.sessionManager?.getCwd() ?? process.cwd();
|
|
113538
113908
|
}
|
|
113539
113909
|
async function prepareAtomicStageSessionOptions(options, sdk, prepareOptions = {}) {
|
|
113910
|
+
prepareOptions.signal?.throwIfAborted();
|
|
113911
|
+
prepareOptions.onStartupPhase?.("resource-preparation");
|
|
113540
113912
|
const atomicOptions = options;
|
|
113541
113913
|
if (atomicOptions?.resourceLoader !== undefined)
|
|
113542
113914
|
return atomicOptions;
|
|
@@ -113555,7 +113927,8 @@ async function prepareAtomicStageSessionOptions(options, sdk, prepareOptions = {
|
|
|
113555
113927
|
resourceLoaderInheritanceSnapshot: inheritanceSnapshot,
|
|
113556
113928
|
builtinPackagePaths: stageBuiltinPackagePaths(builtinPackagePaths)
|
|
113557
113929
|
});
|
|
113558
|
-
await reloadWorkflowStageResources(resourceLoader);
|
|
113930
|
+
await reloadWorkflowStageResources(resourceLoader, prepareOptions);
|
|
113931
|
+
prepareOptions.signal?.throwIfAborted();
|
|
113559
113932
|
return {
|
|
113560
113933
|
...atomicOptions,
|
|
113561
113934
|
cwd,
|
|
@@ -113592,8 +113965,13 @@ function stageBuiltinPackagePaths(paths) {
|
|
|
113592
113965
|
});
|
|
113593
113966
|
}
|
|
113594
113967
|
var workflowStageResourceReloadQueue = Promise.resolve();
|
|
113595
|
-
async function reloadWorkflowStageResources(resourceLoader) {
|
|
113596
|
-
|
|
113968
|
+
async function reloadWorkflowStageResources(resourceLoader, options) {
|
|
113969
|
+
options.onStartupPhase?.("reload-queued");
|
|
113970
|
+
const queuedReload = workflowStageResourceReloadQueue.then(() => {
|
|
113971
|
+
options.signal?.throwIfAborted();
|
|
113972
|
+
options.onStartupPhase?.("reload-active");
|
|
113973
|
+
return resourceLoader.reload();
|
|
113974
|
+
});
|
|
113597
113975
|
workflowStageResourceReloadQueue = queuedReload.catch(() => {
|
|
113598
113976
|
return;
|
|
113599
113977
|
});
|
|
@@ -113628,8 +114006,8 @@ function attachSettingsManager(error, settingsManager) {
|
|
|
113628
114006
|
});
|
|
113629
114007
|
return wrapped;
|
|
113630
114008
|
}
|
|
113631
|
-
async function createPiSdkAgentSession(options, prepareOptions) {
|
|
113632
|
-
const sdk = await import("@bastani/atomic");
|
|
114009
|
+
async function createPiSdkAgentSession(options, prepareOptions, injectedSdk) {
|
|
114010
|
+
const sdk = injectedSdk ?? await import("@bastani/atomic");
|
|
113633
114011
|
let settingsManager;
|
|
113634
114012
|
try {
|
|
113635
114013
|
const sessionOptions = await prepareAtomicStageSessionOptions(options, sdk, {
|
|
@@ -113640,6 +114018,8 @@ async function createPiSdkAgentSession(options, prepareOptions) {
|
|
|
113640
114018
|
}
|
|
113641
114019
|
});
|
|
113642
114020
|
settingsManager = sessionOptions?.settingsManager ?? settingsManager;
|
|
114021
|
+
prepareOptions?.signal?.throwIfAborted();
|
|
114022
|
+
prepareOptions?.onStartupPhase?.("sdk-creation");
|
|
113643
114023
|
const result = await sdk.createAgentSession(sessionOptions);
|
|
113644
114024
|
const resultSettingsManager = result.session.settingsManager;
|
|
113645
114025
|
settingsManager = sessionOptions?.settingsManager ?? resultSettingsManager ?? settingsManager;
|
|
@@ -113899,18 +114279,28 @@ function makeStageExtensionUiContext(ui, meta, broker) {
|
|
|
113899
114279
|
};
|
|
113900
114280
|
}
|
|
113901
114281
|
function buildRuntimeAdapters(pi, options = {}) {
|
|
113902
|
-
const createSession = options.createAgentSession ?? pi.createAgentSession ?? (isTestContext() ? createTestAgentSession : (sessionOptions) => createPiSdkAgentSession(sessionOptions, {
|
|
113903
|
-
resourceLoaderInheritanceSnapshot: pi.getResourceLoaderInheritanceSnapshot?.()
|
|
113904
|
-
|
|
114282
|
+
const createSession = options.createAgentSession ?? pi.createAgentSession ?? (isTestContext() && options.sdk === undefined ? createTestAgentSession : (sessionOptions, prepareOptions) => createPiSdkAgentSession(sessionOptions, {
|
|
114283
|
+
resourceLoaderInheritanceSnapshot: pi.getResourceLoaderInheritanceSnapshot?.(),
|
|
114284
|
+
...prepareOptions
|
|
114285
|
+
}, options.sdk));
|
|
113905
114286
|
const broker = options.stageUiBroker ?? stageUiBroker;
|
|
113906
114287
|
const adapters = {
|
|
113907
114288
|
agentSession: {
|
|
113908
114289
|
async create(stageOptions, meta) {
|
|
113909
114290
|
const sessionOptions = withWorkflowStageSessionOptions(stripWorkflowOnlyOptions2(stageOptions) ?? {}, meta, pi);
|
|
113910
|
-
const
|
|
114291
|
+
const signal = meta?.startupSignal ?? meta?.signal;
|
|
114292
|
+
const result = await createSession(sessionOptions, { signal, onStartupPhase: meta?.onStartupPhase });
|
|
113911
114293
|
const bindable = result.session;
|
|
113912
|
-
|
|
113913
|
-
|
|
114294
|
+
try {
|
|
114295
|
+
signal?.throwIfAborted();
|
|
114296
|
+
meta?.onStartupPhase?.("extension-binding");
|
|
114297
|
+
if (typeof bindable.bindExtensions === "function") {
|
|
114298
|
+
await bindable.bindExtensions(shouldBindStageUiContext(pi, meta) ? { uiContext: makeStageExtensionUiContext(pi.ui ?? {}, meta, broker) } : {});
|
|
114299
|
+
}
|
|
114300
|
+
signal?.throwIfAborted();
|
|
114301
|
+
} catch (error) {
|
|
114302
|
+
await cleanupFailedStageSessionBinding(result.session, error);
|
|
114303
|
+
throw error;
|
|
113914
114304
|
}
|
|
113915
114305
|
return result;
|
|
113916
114306
|
}
|
|
@@ -115475,7 +115865,21 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
|
|
|
115475
115865
|
return true;
|
|
115476
115866
|
runId = picked.runId;
|
|
115477
115867
|
} else if (action === "resume") {
|
|
115478
|
-
|
|
115868
|
+
let backend;
|
|
115869
|
+
try {
|
|
115870
|
+
try {
|
|
115871
|
+
backend = getDurableBackend();
|
|
115872
|
+
} catch (error) {
|
|
115873
|
+
if (!(error instanceof DbosNotReadyError))
|
|
115874
|
+
throw error;
|
|
115875
|
+
await ensureWorkflowResourcesVisible();
|
|
115876
|
+
await deps.runtimeForContext(ctx).prepareDurableResumable(target);
|
|
115877
|
+
backend = getDurableBackend();
|
|
115878
|
+
}
|
|
115879
|
+
} catch (error) {
|
|
115880
|
+
fail(`Failed to resolve workflow resume target: ${error instanceof Error ? error.message : String(error)}`);
|
|
115881
|
+
return true;
|
|
115882
|
+
}
|
|
115479
115883
|
const localResolution = resolveRunId(target);
|
|
115480
115884
|
const localBeforePreparation = localResolution.kind === "exact" ? store.runs().find((run) => run.id === localResolution.runId) : undefined;
|
|
115481
115885
|
const exactBeforePreparation = localBeforePreparation?.id === target ? localBeforePreparation : undefined;
|
|
@@ -116329,6 +116733,8 @@ function renderStagesToolContent(result) {
|
|
|
116329
116733
|
lines.push("stages:");
|
|
116330
116734
|
result.stages.forEach((stage, index) => {
|
|
116331
116735
|
lines.push(`[${index + 1}] ${stage.name} (${stage.id}) ${stage.status}`);
|
|
116736
|
+
if (stage.startup)
|
|
116737
|
+
lines.push(formatStageStartup(stage.startup));
|
|
116332
116738
|
if (stage.sessionId)
|
|
116333
116739
|
lines.push(`sessionId: ${stage.sessionId}`);
|
|
116334
116740
|
if (stage.sessionFile)
|
|
@@ -116369,6 +116775,8 @@ function renderStageToolContent(result) {
|
|
|
116369
116775
|
`);
|
|
116370
116776
|
}
|
|
116371
116777
|
lines.push("stage:");
|
|
116778
|
+
if (result.stage.startup)
|
|
116779
|
+
lines.push(formatStageStartup(result.stage.startup));
|
|
116372
116780
|
lines.push(JSON.stringify(result.stage, null, 2));
|
|
116373
116781
|
if (result.stage.sessionFile) {
|
|
116374
116782
|
lines.push(`transcriptPath: ${result.stage.sessionFile}`);
|
|
@@ -116847,6 +117255,7 @@ function summarizeStage(stage) {
|
|
|
116847
117255
|
id: stage.id,
|
|
116848
117256
|
name: stage.name,
|
|
116849
117257
|
status: stage.status,
|
|
117258
|
+
...stage.startup === undefined ? {} : { startup: { ...stage.startup } },
|
|
116850
117259
|
sessionId: stage.sessionId,
|
|
116851
117260
|
sessionFile: stage.sessionFile,
|
|
116852
117261
|
transcriptPath: stage.sessionFile,
|
|
@@ -117845,10 +118254,14 @@ function registerWorkflowShortcut(pi, overlay) {
|
|
|
117845
118254
|
});
|
|
117846
118255
|
pi.registerShortcut("alt+pageUp", {
|
|
117847
118256
|
description: "Scroll background workflows up",
|
|
118257
|
+
keybinding: "app.workflows.scrollUp",
|
|
118258
|
+
preferEditor: true,
|
|
117848
118259
|
handler: () => scrollStoreWidget(store, -1)
|
|
117849
118260
|
});
|
|
117850
118261
|
pi.registerShortcut("alt+pageDown", {
|
|
117851
118262
|
description: "Scroll background workflows down",
|
|
118263
|
+
keybinding: "app.workflows.scrollDown",
|
|
118264
|
+
preferEditor: true,
|
|
117852
118265
|
handler: () => scrollStoreWidget(store, 1)
|
|
117853
118266
|
});
|
|
117854
118267
|
}
|