@bastani/atomic 0.9.19-alpha.9 → 0.9.19
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 +91 -0
- package/dist/builtin/intercom/CHANGELOG.md +24 -0
- 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 +59 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +236 -68
- package/dist/builtin/workflows/src/index.js +97 -18
- 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/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 +5 -1
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
|
@@ -68525,19 +68525,57 @@ function formatWorkflowStageTarget(rootRunId, ...segments) {
|
|
|
68525
68525
|
|
|
68526
68526
|
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
68527
68527
|
function workflowBoundarySegments(runs, runId) {
|
|
68528
|
+
return createWorkflowBoundarySegmentsResolver(runs)(runId);
|
|
68529
|
+
}
|
|
68530
|
+
function createWorkflowBoundarySegmentsResolver(runs) {
|
|
68528
68531
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
68529
|
-
const
|
|
68530
|
-
|
|
68531
|
-
|
|
68532
|
-
const
|
|
68533
|
-
const
|
|
68534
|
-
|
|
68535
|
-
|
|
68536
|
-
|
|
68537
|
-
|
|
68538
|
-
|
|
68532
|
+
const stagesByRun = new Map;
|
|
68533
|
+
const childrenByParent = new Map;
|
|
68534
|
+
for (const run of runs) {
|
|
68535
|
+
const byId = new Map;
|
|
68536
|
+
const byName = new Map;
|
|
68537
|
+
for (const stage of run.stages) {
|
|
68538
|
+
const ids = byId.get(stage.id) ?? [];
|
|
68539
|
+
ids.push(stage);
|
|
68540
|
+
byId.set(stage.id, ids);
|
|
68541
|
+
const names = byName.get(stage.name) ?? [];
|
|
68542
|
+
names.push(stage);
|
|
68543
|
+
byName.set(stage.name, names);
|
|
68544
|
+
}
|
|
68545
|
+
stagesByRun.set(run.id, { byId, byName });
|
|
68546
|
+
if (run.parentRunId === undefined || run.parentStageId === undefined)
|
|
68547
|
+
continue;
|
|
68548
|
+
const byStage = childrenByParent.get(run.parentRunId) ?? new Map;
|
|
68549
|
+
const children = byStage.get(run.parentStageId) ?? [];
|
|
68550
|
+
children.push(run);
|
|
68551
|
+
byStage.set(run.parentStageId, children);
|
|
68552
|
+
childrenByParent.set(run.parentRunId, byStage);
|
|
68539
68553
|
}
|
|
68540
|
-
|
|
68554
|
+
const cachedSegments = new Map;
|
|
68555
|
+
return (runId) => {
|
|
68556
|
+
if (cachedSegments.has(runId))
|
|
68557
|
+
return cachedSegments.get(runId);
|
|
68558
|
+
const segments = [];
|
|
68559
|
+
let current = runById.get(runId);
|
|
68560
|
+
while (current !== undefined && current.parentRunId !== undefined) {
|
|
68561
|
+
const parent = runById.get(current.parentRunId);
|
|
68562
|
+
const stages = stagesByRun.get(current.parentRunId);
|
|
68563
|
+
const boundary = current.parentStageId === undefined ? undefined : stages?.byId.get(current.parentStageId)?.[0];
|
|
68564
|
+
if (parent === undefined || stages === undefined || boundary === undefined) {
|
|
68565
|
+
cachedSegments.set(runId, undefined);
|
|
68566
|
+
return;
|
|
68567
|
+
}
|
|
68568
|
+
const boundaryName = boundary.name;
|
|
68569
|
+
const matchingBoundaries = stages.byId.get(boundaryName) ?? stages.byName.get(boundaryName);
|
|
68570
|
+
const matchingBoundary = matchingBoundaries?.length === 1 ? matchingBoundaries[0] : undefined;
|
|
68571
|
+
const children = matchingBoundary === undefined ? undefined : childrenByParent.get(parent.id)?.get(matchingBoundary.id);
|
|
68572
|
+
segments.unshift(boundaryName.length > 0 && !boundaryName.includes("/") && !boundaryName.includes("*") && children?.length === 1 && children[0]?.id === current.id ? boundaryName : current.id);
|
|
68573
|
+
current = parent;
|
|
68574
|
+
}
|
|
68575
|
+
const result = current === undefined ? undefined : segments;
|
|
68576
|
+
cachedSegments.set(runId, result);
|
|
68577
|
+
return result;
|
|
68578
|
+
};
|
|
68541
68579
|
}
|
|
68542
68580
|
function workflowBoundaryHops(runs, runId) {
|
|
68543
68581
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
@@ -79145,8 +79183,26 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now(), la
|
|
|
79145
79183
|
});
|
|
79146
79184
|
}
|
|
79147
79185
|
|
|
79186
|
+
// dist/builtin/workflows/src/tui/widget-scroll-hint.ts
|
|
79187
|
+
import { keybindingIdentity } from "@bastani/atomic";
|
|
79188
|
+
import { getKeybindings, matchesKey as matchesKey2 } from "@earendil-works/pi-tui";
|
|
79189
|
+
var legacyInputs = Array.from({ length: 128 }, (_, code) => String.fromCharCode(code)).flatMap((data) => [
|
|
79190
|
+
data,
|
|
79191
|
+
`\x1B${data}`
|
|
79192
|
+
]);
|
|
79193
|
+
function workflowScrollHint(bindings = getKeybindings().getResolvedBindings(), platform = process.platform) {
|
|
79194
|
+
const keys = ["app.workflows.scrollUp", "app.workflows.scrollDown"].map((action) => {
|
|
79195
|
+
const configured = bindings[action] ?? [];
|
|
79196
|
+
return (Array.isArray(configured) ? configured : [configured]).find((key) => {
|
|
79197
|
+
const inputs = legacyInputs.filter((data) => matchesKey2(data, key));
|
|
79198
|
+
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)))));
|
|
79199
|
+
});
|
|
79200
|
+
}).filter((key) => key !== undefined);
|
|
79201
|
+
const label = keys.map((key) => key.replace(/^alt\+/i, platform === "darwin" ? "Option+" : "Alt+")).join("/");
|
|
79202
|
+
return ` ↑↓ scroll${label ? ` · ${label}` : ""}`;
|
|
79203
|
+
}
|
|
79204
|
+
|
|
79148
79205
|
// dist/builtin/workflows/src/tui/widget-viewport.ts
|
|
79149
|
-
import { ScrollableComponentViewport } from "@bastani/atomic";
|
|
79150
79206
|
var WORKFLOW_WIDGET_MAX_ROWS = 10;
|
|
79151
79207
|
|
|
79152
79208
|
class WorkflowWidgetViewport {
|
|
@@ -79154,53 +79210,60 @@ class WorkflowWidgetViewport {
|
|
|
79154
79210
|
terminalRows;
|
|
79155
79211
|
requestRender;
|
|
79156
79212
|
getRunRows;
|
|
79157
|
-
|
|
79213
|
+
getHint;
|
|
79214
|
+
position = 0;
|
|
79215
|
+
version = 0;
|
|
79216
|
+
collapsed = false;
|
|
79217
|
+
state;
|
|
79158
79218
|
lines = [];
|
|
79159
|
-
scrollable = false;
|
|
79160
79219
|
runRows = [];
|
|
79161
|
-
constructor(content, terminalRows, requestRender, getRunRows) {
|
|
79220
|
+
constructor(content, terminalRows, requestRender, getRunRows, getHint = () => "") {
|
|
79162
79221
|
this.content = content;
|
|
79163
79222
|
this.terminalRows = terminalRows;
|
|
79164
79223
|
this.requestRender = requestRender;
|
|
79165
79224
|
this.getRunRows = getRunRows;
|
|
79166
|
-
this.
|
|
79167
|
-
|
|
79225
|
+
this.getHint = getHint;
|
|
79226
|
+
}
|
|
79227
|
+
getScrollRequest() {
|
|
79228
|
+
return { version: this.version, scrollTop: this.collapsed ? 0 : this.position };
|
|
79229
|
+
}
|
|
79230
|
+
onScroll(state) {
|
|
79231
|
+
this.state = state;
|
|
79232
|
+
if (!this.collapsed)
|
|
79233
|
+
this.position = state.scrollTop;
|
|
79168
79234
|
}
|
|
79169
79235
|
scroll(direction) {
|
|
79170
|
-
if (
|
|
79236
|
+
if (this.collapsed)
|
|
79171
79237
|
return;
|
|
79172
|
-
this.
|
|
79238
|
+
const height = this.state?.viewportHeight ?? Math.max(1, Math.min(WORKFLOW_WIDGET_MAX_ROWS, Math.floor(this.terminalRows() / 3)));
|
|
79239
|
+
const next = Math.max(0, Math.min(Math.max(0, this.lines.length - height), this.position + direction));
|
|
79240
|
+
if (next === this.position)
|
|
79241
|
+
return;
|
|
79242
|
+
this.position = next;
|
|
79243
|
+
this.version++;
|
|
79173
79244
|
this.requestRender();
|
|
79174
79245
|
}
|
|
79175
79246
|
render(width) {
|
|
79176
|
-
const
|
|
79177
|
-
const
|
|
79178
|
-
const
|
|
79179
|
-
|
|
79180
|
-
|
|
79247
|
+
const content = this.content.render(width);
|
|
79248
|
+
const hint = content.length > 1 ? this.getHint() : "";
|
|
79249
|
+
const nextLines = hint ? [...content, truncateToWidth2(hint, width, "…")] : content;
|
|
79250
|
+
const nextRunRows = (this.getRunRows?.() ?? []).map((run, index, rows) => hint && index === rows.length - 1 ? { ...run, end: run.end + 1 } : run);
|
|
79251
|
+
const collapsed = Boolean(this.getRunRows && nextLines.length === 1 && nextRunRows.length === 0);
|
|
79252
|
+
if (collapsed) {
|
|
79253
|
+
if (!this.collapsed)
|
|
79254
|
+
this.version++;
|
|
79255
|
+
this.collapsed = true;
|
|
79181
79256
|
return nextLines;
|
|
79182
79257
|
}
|
|
79183
|
-
const
|
|
79184
|
-
|
|
79185
|
-
|
|
79258
|
+
const anchoredOffset = this.getRunRows ? this.resolveAnchor(this.position, nextRunRows) : this.position;
|
|
79259
|
+
if (this.collapsed || anchoredOffset !== this.position) {
|
|
79260
|
+
this.position = anchoredOffset;
|
|
79261
|
+
this.version++;
|
|
79262
|
+
}
|
|
79263
|
+
this.collapsed = false;
|
|
79186
79264
|
this.lines = nextLines;
|
|
79187
79265
|
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, "…")];
|
|
79266
|
+
return nextLines;
|
|
79204
79267
|
}
|
|
79205
79268
|
resolveAnchor(offset, next) {
|
|
79206
79269
|
if (offset === 0 || next.length === 0)
|
|
@@ -79272,7 +79335,7 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
79272
79335
|
widgetViewports.delete(storeInstance);
|
|
79273
79336
|
setWidget.call(ui, key, factory ? (tui, theme) => {
|
|
79274
79337
|
const host = tui;
|
|
79275
|
-
const viewport = new WorkflowWidgetViewport(factory(tui, theme), () => host?.terminal?.rows ?? 30, () => requestRender ? requestRender.call(ui) : host?.requestRender?.(), () => layout.runs);
|
|
79338
|
+
const viewport = new WorkflowWidgetViewport(factory(tui, theme), () => host?.terminal?.rows ?? 30, () => requestRender ? requestRender.call(ui) : host?.requestRender?.(), () => layout.runs, workflowScrollHint);
|
|
79276
79339
|
widgetViewports.set(storeInstance, viewport);
|
|
79277
79340
|
return viewport;
|
|
79278
79341
|
} : undefined, opts);
|
|
@@ -79282,6 +79345,7 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
79282
79345
|
},
|
|
79283
79346
|
key: WIDGET_KEY,
|
|
79284
79347
|
placement: "belowEditor",
|
|
79348
|
+
scroll: { maxHeight: 10, maxHeightFraction: 1 / 3 },
|
|
79285
79349
|
timers,
|
|
79286
79350
|
getSnapshot: () => liveWidgetSnapshot(storeInstance),
|
|
79287
79351
|
subscribe: (listener) => subscribeStoreInvalidation(storeInstance, listener),
|
|
@@ -106724,16 +106788,52 @@ function stageSessionExtensionRunner(current) {
|
|
|
106724
106788
|
}
|
|
106725
106789
|
return;
|
|
106726
106790
|
}
|
|
106791
|
+
var shutdowns = new WeakMap;
|
|
106792
|
+
function shutdownStageSession(current) {
|
|
106793
|
+
if (!current)
|
|
106794
|
+
return Promise.resolve();
|
|
106795
|
+
const existing = shutdowns.get(current);
|
|
106796
|
+
if (existing)
|
|
106797
|
+
return existing;
|
|
106798
|
+
const shutdown = Promise.resolve().then(async () => {
|
|
106799
|
+
const runner = stageSessionExtensionRunner(current);
|
|
106800
|
+
if (runner?.hasHandlers("session_shutdown"))
|
|
106801
|
+
await runner.emit({ type: "session_shutdown", reason: "quit" });
|
|
106802
|
+
});
|
|
106803
|
+
shutdowns.set(current, shutdown);
|
|
106804
|
+
return shutdown;
|
|
106805
|
+
}
|
|
106806
|
+
|
|
106807
|
+
class StageSessionBindingCleanupFailure extends AggregateError {
|
|
106808
|
+
constructor(bindingError, cleanupErrors) {
|
|
106809
|
+
super([bindingError, ...cleanupErrors], "atomic-workflows: failed binding cleanup did not release session ownership", {
|
|
106810
|
+
cause: bindingError
|
|
106811
|
+
});
|
|
106812
|
+
this.name = "StageSessionBindingCleanupFailure";
|
|
106813
|
+
}
|
|
106814
|
+
}
|
|
106815
|
+
async function cleanupFailedStageSessionBinding(current, bindingError) {
|
|
106816
|
+
const cleanupErrors = [];
|
|
106817
|
+
try {
|
|
106818
|
+
await shutdownStageSession(current);
|
|
106819
|
+
} catch (error) {
|
|
106820
|
+
cleanupErrors.push(error);
|
|
106821
|
+
}
|
|
106822
|
+
try {
|
|
106823
|
+
await current.dispose();
|
|
106824
|
+
} catch (error) {
|
|
106825
|
+
cleanupErrors.push(error);
|
|
106826
|
+
}
|
|
106827
|
+
if (cleanupErrors.length > 0)
|
|
106828
|
+
throw new StageSessionBindingCleanupFailure(bindingError, cleanupErrors);
|
|
106829
|
+
}
|
|
106727
106830
|
async function disposeStageSession(current) {
|
|
106728
106831
|
if (!current)
|
|
106729
106832
|
return;
|
|
106730
|
-
|
|
106731
|
-
|
|
106732
|
-
|
|
106733
|
-
|
|
106734
|
-
} catch (error) {
|
|
106735
|
-
console.error("atomic-workflows: stage session_shutdown handler failed", error);
|
|
106736
|
-
}
|
|
106833
|
+
try {
|
|
106834
|
+
await shutdownStageSession(current);
|
|
106835
|
+
} catch (error) {
|
|
106836
|
+
console.error("atomic-workflows: stage session_shutdown handler failed", error);
|
|
106737
106837
|
}
|
|
106738
106838
|
await current.dispose();
|
|
106739
106839
|
}
|
|
@@ -107130,6 +107230,8 @@ class StageSessionController {
|
|
|
107130
107230
|
abortReason;
|
|
107131
107231
|
abortReasonGeneration = 0;
|
|
107132
107232
|
sessionPromise;
|
|
107233
|
+
sessionShutdownPromise;
|
|
107234
|
+
bindingCleanupFailure;
|
|
107133
107235
|
reattachSessionFile;
|
|
107134
107236
|
lastPromptStartIndex;
|
|
107135
107237
|
attemptUsageStartIndex;
|
|
@@ -107246,8 +107348,7 @@ class StageSessionController {
|
|
|
107246
107348
|
this.pendingFallbackWarnings.push(`[fallback] ${candidateLabel(candidate)} failed: ${error}. Retrying with ${candidateLabel(nextCandidate)}.`);
|
|
107247
107349
|
this.modelWarnings.push(...this.pendingFallbackWarnings);
|
|
107248
107350
|
this.pendingFallbackWarnings.length = 0;
|
|
107249
|
-
await this.disposeCurrentSession();
|
|
107250
|
-
this.activeCandidateIndex = index + 1;
|
|
107351
|
+
await this.disposeCurrentSession(index + 1);
|
|
107251
107352
|
this.notifyModelFallbackMetaChange();
|
|
107252
107353
|
return true;
|
|
107253
107354
|
}
|
|
@@ -107275,6 +107376,14 @@ class StageSessionController {
|
|
|
107275
107376
|
this.session?.setThinkingLevel(level);
|
|
107276
107377
|
}
|
|
107277
107378
|
async ensureSession(consumer = "prompt") {
|
|
107379
|
+
if (this.bindingCleanupFailure !== undefined)
|
|
107380
|
+
throw this.bindingCleanupFailure;
|
|
107381
|
+
if (this.sessionShutdownPromise !== undefined) {
|
|
107382
|
+
const generation = this.abortGeneration;
|
|
107383
|
+
await this.sessionShutdownPromise;
|
|
107384
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== generation)
|
|
107385
|
+
throw this.staleCreationReason(generation);
|
|
107386
|
+
}
|
|
107278
107387
|
if (this.disposed)
|
|
107279
107388
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
107280
107389
|
if (this.session !== undefined)
|
|
@@ -107289,14 +107398,16 @@ class StageSessionController {
|
|
|
107289
107398
|
};
|
|
107290
107399
|
pending.then(release, () => {
|
|
107291
107400
|
release();
|
|
107292
|
-
if (this.sessionPromise === pending)
|
|
107401
|
+
if (this.sessionPromise === pending) {
|
|
107293
107402
|
this.sessionPromise = undefined;
|
|
107403
|
+
this.activeCandidateIndex = undefined;
|
|
107404
|
+
}
|
|
107294
107405
|
});
|
|
107295
107406
|
}
|
|
107296
107407
|
return this.sessionPromise;
|
|
107297
107408
|
}
|
|
107298
107409
|
async ensureSessionFromFile(sessionFile, consumer = "prompt") {
|
|
107299
|
-
if (!this.sessionPromise && !this.session)
|
|
107410
|
+
if (!this.sessionShutdownPromise && !this.sessionPromise && !this.session)
|
|
107300
107411
|
this.reattachSessionFile = sessionFile;
|
|
107301
107412
|
const session = await this.ensureSession(consumer);
|
|
107302
107413
|
await session.closeWorkflowStageGeneration?.();
|
|
@@ -107394,6 +107505,18 @@ class StageSessionController {
|
|
|
107394
107505
|
return;
|
|
107395
107506
|
let index = this.activeCandidateIndex ?? 0;
|
|
107396
107507
|
while (index < candidates.length) {
|
|
107508
|
+
if (this.session === undefined && this.ownedCreationPromise !== undefined) {
|
|
107509
|
+
try {
|
|
107510
|
+
await this.ownedCreationPromise;
|
|
107511
|
+
} catch (error) {
|
|
107512
|
+
if (error instanceof StageSessionCreationCancelled)
|
|
107513
|
+
return;
|
|
107514
|
+
throw error;
|
|
107515
|
+
}
|
|
107516
|
+
index = this.activeCandidateIndex ?? index;
|
|
107517
|
+
promptText = this.pendingCreationResumeMessage ?? promptText;
|
|
107518
|
+
this.pendingCreationResumeMessage = undefined;
|
|
107519
|
+
}
|
|
107397
107520
|
const candidate = candidates[index];
|
|
107398
107521
|
try {
|
|
107399
107522
|
const created = this.session && this.activeCandidateIndex === index ? this.session : await this.createSessionWithThrownErrorRetry(candidate, consumer);
|
|
@@ -107785,7 +107908,8 @@ class StageSessionController {
|
|
|
107785
107908
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107786
107909
|
}
|
|
107787
107910
|
const candidates = await this.modelCandidates();
|
|
107788
|
-
const
|
|
107911
|
+
const initialIndex = this.activeCandidateIndex ?? 0;
|
|
107912
|
+
const first = candidates[initialIndex];
|
|
107789
107913
|
if (first === undefined) {
|
|
107790
107914
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107791
107915
|
}
|
|
@@ -107798,9 +107922,9 @@ class StageSessionController {
|
|
|
107798
107922
|
this.resumeCurrentSession = true;
|
|
107799
107923
|
return resumed;
|
|
107800
107924
|
}
|
|
107801
|
-
this.activeCandidateIndex =
|
|
107925
|
+
this.activeCandidateIndex = initialIndex;
|
|
107802
107926
|
this.selectedModel = first.id;
|
|
107803
|
-
return this.createSessionObservingPause(first, consumer).catch((error) => this.createInitialSessionCandidateWalk(candidates, consumer,
|
|
107927
|
+
return this.createSessionObservingPause(first, consumer).catch((error) => this.createInitialSessionCandidateWalk(candidates, consumer, initialIndex, { error }));
|
|
107804
107928
|
}
|
|
107805
107929
|
async createInitialSessionCandidateWalk(candidates, consumer, startIndex, initialFailure) {
|
|
107806
107930
|
let index = startIndex;
|
|
@@ -107882,6 +108006,8 @@ class StageSessionController {
|
|
|
107882
108006
|
}
|
|
107883
108007
|
return await this.createSessionObservingPause(candidate, consumer);
|
|
107884
108008
|
} catch (error) {
|
|
108009
|
+
if (error instanceof StageSessionBindingCleanupFailure)
|
|
108010
|
+
throw error;
|
|
107885
108011
|
const errorSettingsManager = retrySettingsManagerFromError(error);
|
|
107886
108012
|
if (errorSettingsManager !== undefined)
|
|
107887
108013
|
this.sessionSettingsManager = errorSettingsManager;
|
|
@@ -107915,6 +108041,20 @@ class StageSessionController {
|
|
|
107915
108041
|
}
|
|
107916
108042
|
}
|
|
107917
108043
|
createSession(candidate, consumer, resumeOptions) {
|
|
108044
|
+
if (this.bindingCleanupFailure !== undefined)
|
|
108045
|
+
return Promise.reject(this.bindingCleanupFailure);
|
|
108046
|
+
if (this.sessionShutdownPromise !== undefined) {
|
|
108047
|
+
const generation = this.abortGeneration;
|
|
108048
|
+
return this.sessionShutdownPromise.then(() => {
|
|
108049
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== generation)
|
|
108050
|
+
throw this.staleCreationReason(generation);
|
|
108051
|
+
return this.createSession(candidate, consumer, resumeOptions);
|
|
108052
|
+
});
|
|
108053
|
+
}
|
|
108054
|
+
if (this.activeCreation !== undefined)
|
|
108055
|
+
return this.activeCreation;
|
|
108056
|
+
if (this.session !== undefined)
|
|
108057
|
+
return Promise.resolve(this.session);
|
|
107918
108058
|
const creation = this.createSessionAttempt(candidate, consumer, resumeOptions);
|
|
107919
108059
|
this.activeCreation = creation;
|
|
107920
108060
|
creation.finally(() => {
|
|
@@ -107941,6 +108081,10 @@ class StageSessionController {
|
|
|
107941
108081
|
...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
|
|
107942
108082
|
}) : missingAdapter(consumer);
|
|
107943
108083
|
} catch (error) {
|
|
108084
|
+
if (error instanceof StageSessionBindingCleanupFailure) {
|
|
108085
|
+
this.bindingCleanupFailure = error;
|
|
108086
|
+
throw error;
|
|
108087
|
+
}
|
|
107944
108088
|
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration)
|
|
107945
108089
|
throw this.disposed ? new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`) : this.staleCreationReason(startGeneration);
|
|
107946
108090
|
throw error;
|
|
@@ -108004,12 +108148,16 @@ class StageSessionController {
|
|
|
108004
108148
|
});
|
|
108005
108149
|
return result.session;
|
|
108006
108150
|
}
|
|
108007
|
-
async disposeCurrentSession() {
|
|
108151
|
+
async disposeCurrentSession(nextCandidateIndex) {
|
|
108152
|
+
if (this.sessionShutdownPromise !== undefined)
|
|
108153
|
+
await this.sessionShutdownPromise;
|
|
108154
|
+
const startGeneration = this.abortGeneration;
|
|
108008
108155
|
this.abortThrownErrorRetries(new Error(`atomic-workflows: stage "${this.opts.stageName}" session was replaced`));
|
|
108009
108156
|
const current = this.session;
|
|
108010
108157
|
this.messageAdmission.reset();
|
|
108011
108158
|
this.replacement.retire(current);
|
|
108012
108159
|
this.session = undefined;
|
|
108160
|
+
this.activeCandidateIndex = nextCandidateIndex;
|
|
108013
108161
|
if (this.sessionPromise !== this.ownedCreationPromise)
|
|
108014
108162
|
this.sessionPromise = undefined;
|
|
108015
108163
|
this.sessionSettingsManager = undefined;
|
|
@@ -108020,6 +108168,15 @@ class StageSessionController {
|
|
|
108020
108168
|
this.unsubscribeTerminateWatcher?.();
|
|
108021
108169
|
this.unsubscribeTerminateWatcher = undefined;
|
|
108022
108170
|
this.terminatingToolCallIds.clear();
|
|
108171
|
+
const shutdown = Promise.resolve().then(() => shutdownStageSession(current));
|
|
108172
|
+
this.sessionShutdownPromise = shutdown;
|
|
108173
|
+
shutdown.then(() => {
|
|
108174
|
+
if (this.sessionShutdownPromise === shutdown)
|
|
108175
|
+
this.sessionShutdownPromise = undefined;
|
|
108176
|
+
}, () => {});
|
|
108177
|
+
await shutdown;
|
|
108178
|
+
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration)
|
|
108179
|
+
throw this.staleCreationReason(startGeneration);
|
|
108023
108180
|
}
|
|
108024
108181
|
async promptWithPauseResume(activeSession, initialText, sdkOptions) {
|
|
108025
108182
|
let nextText = initialText;
|
|
@@ -108129,12 +108286,13 @@ class StageSessionController {
|
|
|
108129
108286
|
throw err;
|
|
108130
108287
|
}
|
|
108131
108288
|
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;
|
|
108289
|
+
await this.disposeCurrentSession(resumedOverflowNextIndex);
|
|
108134
108290
|
return false;
|
|
108135
108291
|
}
|
|
108136
108292
|
}
|
|
108137
108293
|
async handleCandidateFailure(err, candidate, candidates, index) {
|
|
108294
|
+
if (err instanceof StageSessionBindingCleanupFailure)
|
|
108295
|
+
throw err;
|
|
108138
108296
|
const message = errorMessage4(err);
|
|
108139
108297
|
const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
|
|
108140
108298
|
if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
|
|
@@ -108158,7 +108316,7 @@ class StageSessionController {
|
|
|
108158
108316
|
}
|
|
108159
108317
|
const nextCandidate = candidates[index + 1];
|
|
108160
108318
|
this.pendingFallbackWarnings.push(`[fallback] ${candidateLabel(candidate)} failed: ${message}. Retrying with ${candidateLabel(nextCandidate)}.`);
|
|
108161
|
-
await this.disposeCurrentSession();
|
|
108319
|
+
await this.disposeCurrentSession(index + 1);
|
|
108162
108320
|
return "retry";
|
|
108163
108321
|
}
|
|
108164
108322
|
capturedStructuredOutputForAttempt() {
|
|
@@ -112910,6 +113068,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112910
113068
|
return;
|
|
112911
113069
|
const ownedRunIds = new Set;
|
|
112912
113070
|
const runs = activeStore.runs();
|
|
113071
|
+
const resolveBoundarySegments = createWorkflowBoundarySegmentsResolver(runs);
|
|
112913
113072
|
for (const run of runs) {
|
|
112914
113073
|
const rootRunId = durableRootRunIdForRun(runs, run.id);
|
|
112915
113074
|
if (rootRunId === undefined)
|
|
@@ -112930,7 +113089,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112930
113089
|
...run.stages.filter((stage) => !isNonAgentStage(stage) && workflowInvocationOwnsGroup(workflowInvocationIntercomGroup(rootRunId), stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId))).map((stage) => ({
|
|
112931
113090
|
stageId: stage.id,
|
|
112932
113091
|
stageName: stage.name,
|
|
112933
|
-
target: stageRouteTarget(runs, rootRunId, run.id, stage.id),
|
|
113092
|
+
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
112934
113093
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
112935
113094
|
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status === "pending" || stage.status === "running" || stage.status === "awaiting_input" || stage.status === "paused" || stage.status === "blocked"),
|
|
112936
113095
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
@@ -112938,7 +113097,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112938
113097
|
...nonAgentNodes(run).map((node) => ({
|
|
112939
113098
|
stageId: node.id,
|
|
112940
113099
|
stageName: node.name,
|
|
112941
|
-
target: stageRouteTarget(runs, rootRunId, run.id, node.id),
|
|
113100
|
+
target: stageRouteTarget(runs, rootRunId, run.id, node.id, resolveBoundarySegments),
|
|
112942
113101
|
lifecycle: "pending",
|
|
112943
113102
|
routeEligible: false,
|
|
112944
113103
|
recipientPurpose: "control",
|
|
@@ -113061,8 +113220,8 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113061
113220
|
pi.on?.("session_shutdown", dispose);
|
|
113062
113221
|
return dispose;
|
|
113063
113222
|
}
|
|
113064
|
-
function stageRouteTarget(runs, rootRunId, runId, stageId) {
|
|
113065
|
-
const boundarySegments = runId === rootRunId ? [] :
|
|
113223
|
+
function stageRouteTarget(runs, rootRunId, runId, stageId, resolveBoundarySegments = (id) => workflowBoundarySegments(runs, id)) {
|
|
113224
|
+
const boundarySegments = runId === rootRunId ? [] : resolveBoundarySegments(runId);
|
|
113066
113225
|
return formatWorkflowStageTarget(rootRunId, ...boundarySegments ?? [runId], stageId);
|
|
113067
113226
|
}
|
|
113068
113227
|
function possibleStageRows(runs, rootRunId, rootRun) {
|
|
@@ -113909,8 +114068,13 @@ function buildRuntimeAdapters(pi, options = {}) {
|
|
|
113909
114068
|
const sessionOptions = withWorkflowStageSessionOptions(stripWorkflowOnlyOptions2(stageOptions) ?? {}, meta, pi);
|
|
113910
114069
|
const result = await createSession(sessionOptions);
|
|
113911
114070
|
const bindable = result.session;
|
|
113912
|
-
|
|
113913
|
-
|
|
114071
|
+
try {
|
|
114072
|
+
if (typeof bindable.bindExtensions === "function") {
|
|
114073
|
+
await bindable.bindExtensions(shouldBindStageUiContext(pi, meta) ? { uiContext: makeStageExtensionUiContext(pi.ui ?? {}, meta, broker) } : {});
|
|
114074
|
+
}
|
|
114075
|
+
} catch (error) {
|
|
114076
|
+
await cleanupFailedStageSessionBinding(result.session, error);
|
|
114077
|
+
throw error;
|
|
113914
114078
|
}
|
|
113915
114079
|
return result;
|
|
113916
114080
|
}
|
|
@@ -117845,10 +118009,14 @@ function registerWorkflowShortcut(pi, overlay) {
|
|
|
117845
118009
|
});
|
|
117846
118010
|
pi.registerShortcut("alt+pageUp", {
|
|
117847
118011
|
description: "Scroll background workflows up",
|
|
118012
|
+
keybinding: "app.workflows.scrollUp",
|
|
118013
|
+
preferEditor: true,
|
|
117848
118014
|
handler: () => scrollStoreWidget(store, -1)
|
|
117849
118015
|
});
|
|
117850
118016
|
pi.registerShortcut("alt+pageDown", {
|
|
117851
118017
|
description: "Scroll background workflows down",
|
|
118018
|
+
keybinding: "app.workflows.scrollDown",
|
|
118019
|
+
preferEditor: true,
|
|
117852
118020
|
handler: () => scrollStoreWidget(store, 1)
|
|
117853
118021
|
});
|
|
117854
118022
|
}
|