@bastani/atomic 0.9.19-alpha.8 → 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 +105 -0
- package/dist/builtin/intercom/CHANGELOG.md +38 -0
- package/dist/builtin/intercom/README.md +7 -7
- package/dist/builtin/intercom/broker/client.ts +4 -0
- package/dist/builtin/intercom/broker/send-handler.ts +18 -1
- package/dist/builtin/intercom/index.bundle.mjs +20 -17
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/skills/intercom/SKILL.md +3 -3
- package/dist/builtin/intercom/types.ts +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 +20 -0
- package/dist/builtin/web-access/index.bundle.mjs +19 -17
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +66 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +324 -40
- 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/intercom/reference.md +4 -0
- package/docs/intercom.md +4 -4
- package/docs/keybindings.md +17 -0
- package/docs/tui.md +34 -0
- package/docs/web-access.md +10 -0
- package/docs/workflows/api-reference.md +2 -0
- package/docs/workflows/operations.md +8 -0
- 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]));
|
|
@@ -79093,7 +79131,9 @@ function plainCollapsed(counts, activeTools) {
|
|
|
79093
79131
|
const tools = activeTools > 0 ? ` · ${activeTools} tool${activeTools === 1 ? "" : "s"}` : "";
|
|
79094
79132
|
return ` ▾ ${total} background · ${counts.active} ●${paused}${quit}${blocked}${tools}`;
|
|
79095
79133
|
}
|
|
79096
|
-
function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now()) {
|
|
79134
|
+
function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now(), layout) {
|
|
79135
|
+
if (layout)
|
|
79136
|
+
layout.runs = [];
|
|
79097
79137
|
const display = selectDisplayRuns(snap, now);
|
|
79098
79138
|
if (display.length === 0)
|
|
79099
79139
|
return [];
|
|
@@ -79112,7 +79152,7 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now()) {
|
|
|
79112
79152
|
const activeTools = display.filter(isActive).reduce((total, run) => total + activeToolNodes(run).length, 0);
|
|
79113
79153
|
if (width < COLLAPSED_BREAKPOINT_COLS) {
|
|
79114
79154
|
return [
|
|
79115
|
-
themed ? themedCollapsed(visibleCounts, activeTools, graphTheme) : plainCollapsed(visibleCounts, activeTools)
|
|
79155
|
+
truncateToWidth2(themed ? themedCollapsed(visibleCounts, activeTools, graphTheme) : plainCollapsed(visibleCounts, activeTools), width, "…")
|
|
79116
79156
|
];
|
|
79117
79157
|
}
|
|
79118
79158
|
const total = display.length;
|
|
@@ -79126,6 +79166,11 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now()) {
|
|
|
79126
79166
|
const run = display[i];
|
|
79127
79167
|
const runLines = themed ? themedRunLines(run, now, graphTheme, snap.runs, width, expandGraph) : plainRunLines(run, now, snap.runs, width, expandGraph);
|
|
79128
79168
|
body.push(...runLines);
|
|
79169
|
+
layout?.runs.push({
|
|
79170
|
+
id: run.id,
|
|
79171
|
+
start: body.length - runLines.length + 1,
|
|
79172
|
+
end: body.length + (i === display.length - 1 ? 2 : 1)
|
|
79173
|
+
});
|
|
79129
79174
|
if (i < display.length - 1)
|
|
79130
79175
|
body.push("");
|
|
79131
79176
|
}
|
|
@@ -79138,7 +79183,120 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now()) {
|
|
|
79138
79183
|
});
|
|
79139
79184
|
}
|
|
79140
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
|
+
|
|
79205
|
+
// dist/builtin/workflows/src/tui/widget-viewport.ts
|
|
79206
|
+
var WORKFLOW_WIDGET_MAX_ROWS = 10;
|
|
79207
|
+
|
|
79208
|
+
class WorkflowWidgetViewport {
|
|
79209
|
+
content;
|
|
79210
|
+
terminalRows;
|
|
79211
|
+
requestRender;
|
|
79212
|
+
getRunRows;
|
|
79213
|
+
getHint;
|
|
79214
|
+
position = 0;
|
|
79215
|
+
version = 0;
|
|
79216
|
+
collapsed = false;
|
|
79217
|
+
state;
|
|
79218
|
+
lines = [];
|
|
79219
|
+
runRows = [];
|
|
79220
|
+
constructor(content, terminalRows, requestRender, getRunRows, getHint = () => "") {
|
|
79221
|
+
this.content = content;
|
|
79222
|
+
this.terminalRows = terminalRows;
|
|
79223
|
+
this.requestRender = requestRender;
|
|
79224
|
+
this.getRunRows = getRunRows;
|
|
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;
|
|
79234
|
+
}
|
|
79235
|
+
scroll(direction) {
|
|
79236
|
+
if (this.collapsed)
|
|
79237
|
+
return;
|
|
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++;
|
|
79244
|
+
this.requestRender();
|
|
79245
|
+
}
|
|
79246
|
+
render(width) {
|
|
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;
|
|
79256
|
+
return nextLines;
|
|
79257
|
+
}
|
|
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;
|
|
79264
|
+
this.lines = nextLines;
|
|
79265
|
+
this.runRows = nextRunRows;
|
|
79266
|
+
return nextLines;
|
|
79267
|
+
}
|
|
79268
|
+
resolveAnchor(offset, next) {
|
|
79269
|
+
if (offset === 0 || next.length === 0)
|
|
79270
|
+
return 0;
|
|
79271
|
+
const index = this.runRows.findIndex((run) => offset >= run.start - 1 && offset < run.end);
|
|
79272
|
+
const anchor = this.runRows[index];
|
|
79273
|
+
if (!anchor)
|
|
79274
|
+
return 0;
|
|
79275
|
+
const byId = new Map(next.map((run) => [run.id, run]));
|
|
79276
|
+
const retained = byId.get(anchor.id);
|
|
79277
|
+
if (retained)
|
|
79278
|
+
return Math.min(retained.end - 1, retained.start + offset - anchor.start);
|
|
79279
|
+
const neighbours = [...this.runRows.slice(index + 1), ...this.runRows.slice(0, index).reverse()];
|
|
79280
|
+
for (const neighbour of neighbours) {
|
|
79281
|
+
const survivor = byId.get(neighbour.id);
|
|
79282
|
+
if (survivor)
|
|
79283
|
+
return survivor.start;
|
|
79284
|
+
}
|
|
79285
|
+
return 0;
|
|
79286
|
+
}
|
|
79287
|
+
invalidate() {
|
|
79288
|
+
this.content.invalidate?.();
|
|
79289
|
+
}
|
|
79290
|
+
dispose() {
|
|
79291
|
+
this.content.dispose?.();
|
|
79292
|
+
}
|
|
79293
|
+
}
|
|
79294
|
+
|
|
79141
79295
|
// dist/builtin/workflows/src/tui/store-widget-installer.ts
|
|
79296
|
+
var widgetViewports = new WeakMap;
|
|
79297
|
+
function scrollStoreWidget(storeInstance, direction) {
|
|
79298
|
+
widgetViewports.get(storeInstance)?.scroll(direction);
|
|
79299
|
+
}
|
|
79142
79300
|
var defaultTimerApi = {
|
|
79143
79301
|
setTimeout: (handler, delayMs) => setTimeout(handler, delayMs),
|
|
79144
79302
|
clearTimeout: (handle) => clearTimeout(handle)
|
|
@@ -79169,19 +79327,30 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
79169
79327
|
const setWidget = ui.setWidget;
|
|
79170
79328
|
const requestRender = ui.requestRender;
|
|
79171
79329
|
const onWidgetRelease = ui.onWidgetRelease;
|
|
79330
|
+
const layout = { runs: [] };
|
|
79172
79331
|
const controller = installReactiveWidget({
|
|
79173
79332
|
ui: {
|
|
79174
|
-
setWidget: (key, factory, opts) =>
|
|
79333
|
+
setWidget: (key, factory, opts) => {
|
|
79334
|
+
if (!factory)
|
|
79335
|
+
widgetViewports.delete(storeInstance);
|
|
79336
|
+
setWidget.call(ui, key, factory ? (tui, theme) => {
|
|
79337
|
+
const host = tui;
|
|
79338
|
+
const viewport = new WorkflowWidgetViewport(factory(tui, theme), () => host?.terminal?.rows ?? 30, () => requestRender ? requestRender.call(ui) : host?.requestRender?.(), () => layout.runs, workflowScrollHint);
|
|
79339
|
+
widgetViewports.set(storeInstance, viewport);
|
|
79340
|
+
return viewport;
|
|
79341
|
+
} : undefined, opts);
|
|
79342
|
+
},
|
|
79175
79343
|
...requestRender ? { requestRender: () => requestRender.call(ui) } : {},
|
|
79176
79344
|
...onWidgetRelease ? { onWidgetRelease: (key, listener) => onWidgetRelease.call(ui, key, listener) } : {}
|
|
79177
79345
|
},
|
|
79178
79346
|
key: WIDGET_KEY,
|
|
79179
79347
|
placement: "belowEditor",
|
|
79348
|
+
scroll: { maxHeight: 10, maxHeightFraction: 1 / 3 },
|
|
79180
79349
|
timers,
|
|
79181
79350
|
getSnapshot: () => liveWidgetSnapshot(storeInstance),
|
|
79182
79351
|
subscribe: (listener) => subscribeStoreInvalidation(storeInstance, listener),
|
|
79183
79352
|
getPreviewLines: (snap, now) => buildThemedWidgetLines(snap, undefined, 120, now),
|
|
79184
|
-
render: (snap, { theme, width, now }) => buildThemedWidgetLines(snap, theme, width, now),
|
|
79353
|
+
render: (snap, { theme, width, now }) => buildThemedWidgetLines(snap, theme, width, now, layout),
|
|
79185
79354
|
getNextRefreshDelayMs: (snap, now) => nextWidgetRefreshDelayMs(snap, now),
|
|
79186
79355
|
requestRenderOnStateNoop: false,
|
|
79187
79356
|
isStaleError: isStaleExtensionContextError4,
|
|
@@ -79189,7 +79358,10 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
79189
79358
|
reportWidgetFailure(ui, `Workflow progress widget could not mount: ${error.message}`);
|
|
79190
79359
|
}
|
|
79191
79360
|
});
|
|
79192
|
-
return () =>
|
|
79361
|
+
return () => {
|
|
79362
|
+
widgetViewports.delete(storeInstance);
|
|
79363
|
+
controller.dispose();
|
|
79364
|
+
};
|
|
79193
79365
|
}
|
|
79194
79366
|
function installToolExecutionHooks(pi, storeInstance) {
|
|
79195
79367
|
const eventBusOn = pi.events?.on;
|
|
@@ -106616,16 +106788,52 @@ function stageSessionExtensionRunner(current) {
|
|
|
106616
106788
|
}
|
|
106617
106789
|
return;
|
|
106618
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
|
+
}
|
|
106619
106830
|
async function disposeStageSession(current) {
|
|
106620
106831
|
if (!current)
|
|
106621
106832
|
return;
|
|
106622
|
-
|
|
106623
|
-
|
|
106624
|
-
|
|
106625
|
-
|
|
106626
|
-
} catch (error) {
|
|
106627
|
-
console.error("atomic-workflows: stage session_shutdown handler failed", error);
|
|
106628
|
-
}
|
|
106833
|
+
try {
|
|
106834
|
+
await shutdownStageSession(current);
|
|
106835
|
+
} catch (error) {
|
|
106836
|
+
console.error("atomic-workflows: stage session_shutdown handler failed", error);
|
|
106629
106837
|
}
|
|
106630
106838
|
await current.dispose();
|
|
106631
106839
|
}
|
|
@@ -107022,6 +107230,8 @@ class StageSessionController {
|
|
|
107022
107230
|
abortReason;
|
|
107023
107231
|
abortReasonGeneration = 0;
|
|
107024
107232
|
sessionPromise;
|
|
107233
|
+
sessionShutdownPromise;
|
|
107234
|
+
bindingCleanupFailure;
|
|
107025
107235
|
reattachSessionFile;
|
|
107026
107236
|
lastPromptStartIndex;
|
|
107027
107237
|
attemptUsageStartIndex;
|
|
@@ -107138,8 +107348,7 @@ class StageSessionController {
|
|
|
107138
107348
|
this.pendingFallbackWarnings.push(`[fallback] ${candidateLabel(candidate)} failed: ${error}. Retrying with ${candidateLabel(nextCandidate)}.`);
|
|
107139
107349
|
this.modelWarnings.push(...this.pendingFallbackWarnings);
|
|
107140
107350
|
this.pendingFallbackWarnings.length = 0;
|
|
107141
|
-
await this.disposeCurrentSession();
|
|
107142
|
-
this.activeCandidateIndex = index + 1;
|
|
107351
|
+
await this.disposeCurrentSession(index + 1);
|
|
107143
107352
|
this.notifyModelFallbackMetaChange();
|
|
107144
107353
|
return true;
|
|
107145
107354
|
}
|
|
@@ -107167,6 +107376,14 @@ class StageSessionController {
|
|
|
107167
107376
|
this.session?.setThinkingLevel(level);
|
|
107168
107377
|
}
|
|
107169
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
|
+
}
|
|
107170
107387
|
if (this.disposed)
|
|
107171
107388
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
107172
107389
|
if (this.session !== undefined)
|
|
@@ -107181,14 +107398,16 @@ class StageSessionController {
|
|
|
107181
107398
|
};
|
|
107182
107399
|
pending.then(release, () => {
|
|
107183
107400
|
release();
|
|
107184
|
-
if (this.sessionPromise === pending)
|
|
107401
|
+
if (this.sessionPromise === pending) {
|
|
107185
107402
|
this.sessionPromise = undefined;
|
|
107403
|
+
this.activeCandidateIndex = undefined;
|
|
107404
|
+
}
|
|
107186
107405
|
});
|
|
107187
107406
|
}
|
|
107188
107407
|
return this.sessionPromise;
|
|
107189
107408
|
}
|
|
107190
107409
|
async ensureSessionFromFile(sessionFile, consumer = "prompt") {
|
|
107191
|
-
if (!this.sessionPromise && !this.session)
|
|
107410
|
+
if (!this.sessionShutdownPromise && !this.sessionPromise && !this.session)
|
|
107192
107411
|
this.reattachSessionFile = sessionFile;
|
|
107193
107412
|
const session = await this.ensureSession(consumer);
|
|
107194
107413
|
await session.closeWorkflowStageGeneration?.();
|
|
@@ -107286,6 +107505,18 @@ class StageSessionController {
|
|
|
107286
107505
|
return;
|
|
107287
107506
|
let index = this.activeCandidateIndex ?? 0;
|
|
107288
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
|
+
}
|
|
107289
107520
|
const candidate = candidates[index];
|
|
107290
107521
|
try {
|
|
107291
107522
|
const created = this.session && this.activeCandidateIndex === index ? this.session : await this.createSessionWithThrownErrorRetry(candidate, consumer);
|
|
@@ -107677,7 +107908,8 @@ class StageSessionController {
|
|
|
107677
107908
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107678
107909
|
}
|
|
107679
107910
|
const candidates = await this.modelCandidates();
|
|
107680
|
-
const
|
|
107911
|
+
const initialIndex = this.activeCandidateIndex ?? 0;
|
|
107912
|
+
const first = candidates[initialIndex];
|
|
107681
107913
|
if (first === undefined) {
|
|
107682
107914
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107683
107915
|
}
|
|
@@ -107690,9 +107922,9 @@ class StageSessionController {
|
|
|
107690
107922
|
this.resumeCurrentSession = true;
|
|
107691
107923
|
return resumed;
|
|
107692
107924
|
}
|
|
107693
|
-
this.activeCandidateIndex =
|
|
107925
|
+
this.activeCandidateIndex = initialIndex;
|
|
107694
107926
|
this.selectedModel = first.id;
|
|
107695
|
-
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 }));
|
|
107696
107928
|
}
|
|
107697
107929
|
async createInitialSessionCandidateWalk(candidates, consumer, startIndex, initialFailure) {
|
|
107698
107930
|
let index = startIndex;
|
|
@@ -107774,6 +108006,8 @@ class StageSessionController {
|
|
|
107774
108006
|
}
|
|
107775
108007
|
return await this.createSessionObservingPause(candidate, consumer);
|
|
107776
108008
|
} catch (error) {
|
|
108009
|
+
if (error instanceof StageSessionBindingCleanupFailure)
|
|
108010
|
+
throw error;
|
|
107777
108011
|
const errorSettingsManager = retrySettingsManagerFromError(error);
|
|
107778
108012
|
if (errorSettingsManager !== undefined)
|
|
107779
108013
|
this.sessionSettingsManager = errorSettingsManager;
|
|
@@ -107807,6 +108041,20 @@ class StageSessionController {
|
|
|
107807
108041
|
}
|
|
107808
108042
|
}
|
|
107809
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);
|
|
107810
108058
|
const creation = this.createSessionAttempt(candidate, consumer, resumeOptions);
|
|
107811
108059
|
this.activeCreation = creation;
|
|
107812
108060
|
creation.finally(() => {
|
|
@@ -107833,6 +108081,10 @@ class StageSessionController {
|
|
|
107833
108081
|
...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
|
|
107834
108082
|
}) : missingAdapter(consumer);
|
|
107835
108083
|
} catch (error) {
|
|
108084
|
+
if (error instanceof StageSessionBindingCleanupFailure) {
|
|
108085
|
+
this.bindingCleanupFailure = error;
|
|
108086
|
+
throw error;
|
|
108087
|
+
}
|
|
107836
108088
|
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration)
|
|
107837
108089
|
throw this.disposed ? new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`) : this.staleCreationReason(startGeneration);
|
|
107838
108090
|
throw error;
|
|
@@ -107896,12 +108148,16 @@ class StageSessionController {
|
|
|
107896
108148
|
});
|
|
107897
108149
|
return result.session;
|
|
107898
108150
|
}
|
|
107899
|
-
async disposeCurrentSession() {
|
|
108151
|
+
async disposeCurrentSession(nextCandidateIndex) {
|
|
108152
|
+
if (this.sessionShutdownPromise !== undefined)
|
|
108153
|
+
await this.sessionShutdownPromise;
|
|
108154
|
+
const startGeneration = this.abortGeneration;
|
|
107900
108155
|
this.abortThrownErrorRetries(new Error(`atomic-workflows: stage "${this.opts.stageName}" session was replaced`));
|
|
107901
108156
|
const current = this.session;
|
|
107902
108157
|
this.messageAdmission.reset();
|
|
107903
108158
|
this.replacement.retire(current);
|
|
107904
108159
|
this.session = undefined;
|
|
108160
|
+
this.activeCandidateIndex = nextCandidateIndex;
|
|
107905
108161
|
if (this.sessionPromise !== this.ownedCreationPromise)
|
|
107906
108162
|
this.sessionPromise = undefined;
|
|
107907
108163
|
this.sessionSettingsManager = undefined;
|
|
@@ -107912,6 +108168,15 @@ class StageSessionController {
|
|
|
107912
108168
|
this.unsubscribeTerminateWatcher?.();
|
|
107913
108169
|
this.unsubscribeTerminateWatcher = undefined;
|
|
107914
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);
|
|
107915
108180
|
}
|
|
107916
108181
|
async promptWithPauseResume(activeSession, initialText, sdkOptions) {
|
|
107917
108182
|
let nextText = initialText;
|
|
@@ -108021,12 +108286,13 @@ class StageSessionController {
|
|
|
108021
108286
|
throw err;
|
|
108022
108287
|
}
|
|
108023
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])}.`);
|
|
108024
|
-
await this.disposeCurrentSession();
|
|
108025
|
-
this.activeCandidateIndex = resumedOverflowNextIndex;
|
|
108289
|
+
await this.disposeCurrentSession(resumedOverflowNextIndex);
|
|
108026
108290
|
return false;
|
|
108027
108291
|
}
|
|
108028
108292
|
}
|
|
108029
108293
|
async handleCandidateFailure(err, candidate, candidates, index) {
|
|
108294
|
+
if (err instanceof StageSessionBindingCleanupFailure)
|
|
108295
|
+
throw err;
|
|
108030
108296
|
const message = errorMessage4(err);
|
|
108031
108297
|
const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
|
|
108032
108298
|
if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
|
|
@@ -108050,7 +108316,7 @@ class StageSessionController {
|
|
|
108050
108316
|
}
|
|
108051
108317
|
const nextCandidate = candidates[index + 1];
|
|
108052
108318
|
this.pendingFallbackWarnings.push(`[fallback] ${candidateLabel(candidate)} failed: ${message}. Retrying with ${candidateLabel(nextCandidate)}.`);
|
|
108053
|
-
await this.disposeCurrentSession();
|
|
108319
|
+
await this.disposeCurrentSession(index + 1);
|
|
108054
108320
|
return "retry";
|
|
108055
108321
|
}
|
|
108056
108322
|
capturedStructuredOutputForAttempt() {
|
|
@@ -112802,6 +113068,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112802
113068
|
return;
|
|
112803
113069
|
const ownedRunIds = new Set;
|
|
112804
113070
|
const runs = activeStore.runs();
|
|
113071
|
+
const resolveBoundarySegments = createWorkflowBoundarySegmentsResolver(runs);
|
|
112805
113072
|
for (const run of runs) {
|
|
112806
113073
|
const rootRunId = durableRootRunIdForRun(runs, run.id);
|
|
112807
113074
|
if (rootRunId === undefined)
|
|
@@ -112822,7 +113089,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112822
113089
|
...run.stages.filter((stage) => !isNonAgentStage(stage) && workflowInvocationOwnsGroup(workflowInvocationIntercomGroup(rootRunId), stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId))).map((stage) => ({
|
|
112823
113090
|
stageId: stage.id,
|
|
112824
113091
|
stageName: stage.name,
|
|
112825
|
-
target: stageRouteTarget(runs, rootRunId, run.id, stage.id),
|
|
113092
|
+
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
112826
113093
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
112827
113094
|
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status === "pending" || stage.status === "running" || stage.status === "awaiting_input" || stage.status === "paused" || stage.status === "blocked"),
|
|
112828
113095
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
@@ -112830,7 +113097,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112830
113097
|
...nonAgentNodes(run).map((node) => ({
|
|
112831
113098
|
stageId: node.id,
|
|
112832
113099
|
stageName: node.name,
|
|
112833
|
-
target: stageRouteTarget(runs, rootRunId, run.id, node.id),
|
|
113100
|
+
target: stageRouteTarget(runs, rootRunId, run.id, node.id, resolveBoundarySegments),
|
|
112834
113101
|
lifecycle: "pending",
|
|
112835
113102
|
routeEligible: false,
|
|
112836
113103
|
recipientPurpose: "control",
|
|
@@ -112953,8 +113220,8 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
112953
113220
|
pi.on?.("session_shutdown", dispose);
|
|
112954
113221
|
return dispose;
|
|
112955
113222
|
}
|
|
112956
|
-
function stageRouteTarget(runs, rootRunId, runId, stageId) {
|
|
112957
|
-
const boundarySegments = runId === rootRunId ? [] :
|
|
113223
|
+
function stageRouteTarget(runs, rootRunId, runId, stageId, resolveBoundarySegments = (id) => workflowBoundarySegments(runs, id)) {
|
|
113224
|
+
const boundarySegments = runId === rootRunId ? [] : resolveBoundarySegments(runId);
|
|
112958
113225
|
return formatWorkflowStageTarget(rootRunId, ...boundarySegments ?? [runId], stageId);
|
|
112959
113226
|
}
|
|
112960
113227
|
function possibleStageRows(runs, rootRunId, rootRun) {
|
|
@@ -113801,8 +114068,13 @@ function buildRuntimeAdapters(pi, options = {}) {
|
|
|
113801
114068
|
const sessionOptions = withWorkflowStageSessionOptions(stripWorkflowOnlyOptions2(stageOptions) ?? {}, meta, pi);
|
|
113802
114069
|
const result = await createSession(sessionOptions);
|
|
113803
114070
|
const bindable = result.session;
|
|
113804
|
-
|
|
113805
|
-
|
|
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;
|
|
113806
114078
|
}
|
|
113807
114079
|
return result;
|
|
113808
114080
|
}
|
|
@@ -117735,6 +118007,18 @@ function registerWorkflowShortcut(pi, overlay) {
|
|
|
117735
118007
|
description: "Open workflow orchestrator pane",
|
|
117736
118008
|
handler: openPane
|
|
117737
118009
|
});
|
|
118010
|
+
pi.registerShortcut("alt+pageUp", {
|
|
118011
|
+
description: "Scroll background workflows up",
|
|
118012
|
+
keybinding: "app.workflows.scrollUp",
|
|
118013
|
+
preferEditor: true,
|
|
118014
|
+
handler: () => scrollStoreWidget(store, -1)
|
|
118015
|
+
});
|
|
118016
|
+
pi.registerShortcut("alt+pageDown", {
|
|
118017
|
+
description: "Scroll background workflows down",
|
|
118018
|
+
keybinding: "app.workflows.scrollDown",
|
|
118019
|
+
preferEditor: true,
|
|
118020
|
+
handler: () => scrollStoreWidget(store, 1)
|
|
118021
|
+
});
|
|
117738
118022
|
}
|
|
117739
118023
|
function registerIntercomControl(pi, intercomControlRef) {
|
|
117740
118024
|
intercomControlRef.current = subscribeIntercomControl(pi, buildIntercomCallbacks({
|