@bastani/atomic 0.9.19-alpha.6 → 0.9.19-alpha.8
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 +6 -0
- package/README.md +2 -2
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/index.bundle.mjs +22 -3
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +19 -0
- package/dist/builtin/workflows/README.md +1 -1
- package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
- package/dist/builtin/workflows/builtin/{chunk-vhmnzdj9.js → chunk-1jth021m.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-p8jjwfg6.js → chunk-2377r57g.js} +4 -2
- package/dist/builtin/workflows/builtin/{chunk-hbnwv56f.js → chunk-31j2gs7h.js} +2 -2
- package/dist/builtin/workflows/builtin/{chunk-n8zysf1t.js → chunk-ngkqkzej.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-1nbq96fh.js → chunk-nkrafh9s.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-1kx4aggw.js → chunk-wf741bv3.js} +2 -2
- package/dist/builtin/workflows/builtin/{chunk-t6x2d78s.js → chunk-z29qbehr.js} +1 -1
- package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
- package/dist/builtin/workflows/builtin/goal.js +3 -3
- package/dist/builtin/workflows/builtin/index.js +7 -7
- package/dist/builtin/workflows/builtin/ralph.js +3 -3
- package/dist/builtin/workflows/builtin/tournament.js +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +590 -256
- package/dist/builtin/workflows/src/index.js +67 -19
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -0
- package/dist/modes/interactive/components/task-live-transcript.d.ts +1 -1
- package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-live-transcript.js +19 -11
- package/dist/modes/interactive/components/task-live-transcript.js.map +1 -1
- package/docs/background-tasks.md +1 -1
- package/docs/build.md +51 -0
- package/docs/changelog.mdx +8 -8
- package/docs/compaction/reference.md +267 -0
- package/docs/compaction.md +36 -219
- package/docs/computer-use.md +35 -0
- package/docs/containerization.md +2 -0
- package/docs/custom-provider/api-reference.md +145 -0
- package/docs/custom-provider/oauth.md +131 -0
- package/docs/custom-provider/override.md +34 -0
- package/docs/custom-provider/registration.md +163 -0
- package/docs/custom-provider/streaming.md +214 -0
- package/docs/custom-provider.md +43 -607
- package/docs/development.md +76 -0
- package/docs/docs.json +199 -77
- package/docs/environment-variables.md +1 -1
- package/docs/extensions/api-reference.md +1001 -0
- package/docs/extensions/authoring.md +676 -0
- package/docs/extensions/events.md +793 -0
- package/docs/extensions/examples.md +94 -0
- package/docs/extensions/ui.md +470 -0
- package/docs/extensions.md +270 -2768
- package/docs/getting-started/authentication.md +55 -0
- package/docs/getting-started/first-session.md +172 -0
- package/docs/getting-started/installation.md +154 -0
- package/docs/getting-started/project-instructions.md +43 -0
- package/docs/guides/configuration.md +65 -0
- package/docs/guides/intercom.md +24 -0
- package/docs/guides/non-interactive.md +33 -0
- package/docs/guides/subagents.md +24 -0
- package/docs/guides/workflows.md +27 -0
- package/docs/guides.md +41 -0
- package/docs/index.md +13 -45
- package/docs/intercom/operations.md +178 -0
- package/docs/intercom/reference.md +146 -0
- package/docs/intercom.md +54 -259
- package/docs/json.md +17 -0
- package/docs/llama-cpp.md +5 -0
- package/docs/models/artificial-analysis-index.md +89 -0
- package/docs/models/evals.md +2 -2
- package/docs/models/model-selection.md +3 -3
- package/docs/models/pareto-efficiency.md +2 -2
- package/docs/models/reference.md +601 -0
- package/docs/models.md +45 -550
- package/docs/packages/authoring.md +88 -0
- package/docs/packages/reference.md +43 -0
- package/docs/packages.md +28 -107
- package/docs/programmatic.md +29 -0
- package/docs/prompt-templates.md +11 -0
- package/docs/providers/reference.md +23 -0
- package/docs/providers.md +10 -15
- package/docs/quickstart.md +44 -238
- package/docs/reference/cli.md +252 -0
- package/docs/reference.md +52 -0
- package/docs/rpc/examples.md +64 -0
- package/docs/rpc/extension-ui.md +198 -0
- package/docs/rpc/protocol.md +1341 -0
- package/docs/rpc.md +109 -1346
- package/docs/sdk/reference.md +1090 -0
- package/docs/sdk.md +56 -1002
- package/docs/session-format.md +2 -0
- package/docs/sessions.md +6 -10
- package/docs/settings.md +6 -45
- package/docs/skills/authoring.md +95 -0
- package/docs/skills/reference.md +60 -0
- package/docs/skills.md +20 -122
- package/docs/subagents/authoring.md +37 -0
- package/docs/subagents/reference.md +60 -0
- package/docs/subagents.md +39 -95
- package/docs/terminal-setup.md +1 -1
- package/docs/themes/reference.md +176 -0
- package/docs/themes.md +21 -135
- package/docs/tmux.md +5 -0
- package/docs/tools/edit.md +5 -0
- package/docs/tools.md +5 -0
- package/docs/tui/reference.md +343 -0
- package/docs/tui.md +23 -286
- package/docs/usage.md +26 -209
- package/docs/web-access.md +2 -0
- package/docs/windows.md +2 -1
- package/docs/workflows/api-reference.md +11 -4
- package/docs/workflows/authoring.md +4 -2
- package/docs/workflows/builtins.md +2 -2
- package/docs/workflows/operations.md +15 -10
- package/docs/workflows/reliable-design.md +21 -3
- package/docs/workflows/verification.md +8 -0
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
|
@@ -69012,9 +69012,9 @@ function renderDetailHintRows(detail, width, theme) {
|
|
|
69012
69012
|
}
|
|
69013
69013
|
function formatTime(ms) {
|
|
69014
69014
|
const d = new Date(ms);
|
|
69015
|
-
const hh = String(d.
|
|
69016
|
-
const mm = String(d.
|
|
69017
|
-
const ss = String(d.
|
|
69015
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
69016
|
+
const mm = String(d.getMinutes()).padStart(2, "0");
|
|
69017
|
+
const ss = String(d.getSeconds()).padStart(2, "0");
|
|
69018
69018
|
return `${hh}:${mm}:${ss}`;
|
|
69019
69019
|
}
|
|
69020
69020
|
|
|
@@ -72599,7 +72599,7 @@ class GraphCanvas {
|
|
|
72599
72599
|
|
|
72600
72600
|
// dist/builtin/workflows/src/tui/layout.ts
|
|
72601
72601
|
var NODE_W = 24;
|
|
72602
|
-
var NODE_H =
|
|
72602
|
+
var NODE_H = 5;
|
|
72603
72603
|
function computeLayout(stages, opts = {}) {
|
|
72604
72604
|
const colGap = opts.colGap ?? 4;
|
|
72605
72605
|
const rowGap = opts.rowGap ?? 3;
|
|
@@ -72682,17 +72682,255 @@ function computeLayout(stages, opts = {}) {
|
|
|
72682
72682
|
rowIndex.set(ids[i], i);
|
|
72683
72683
|
}
|
|
72684
72684
|
}
|
|
72685
|
+
const heights = new Map(stages.map((stage) => [stage.id, opts.nodeHeight?.(stage) ?? NODE_H]));
|
|
72686
|
+
const verticalOffsets = new Map;
|
|
72687
|
+
const horizontalOffsets = new Map;
|
|
72688
|
+
let depthY = 0;
|
|
72689
|
+
for (const depth of [...colGroups.keys()].sort((a, b) => a - b)) {
|
|
72690
|
+
const ids = colGroups.get(depth);
|
|
72691
|
+
verticalOffsets.set(depth, depthY);
|
|
72692
|
+
let siblingY = 0;
|
|
72693
|
+
let tallest = 0;
|
|
72694
|
+
for (const id of ids) {
|
|
72695
|
+
const height = heights.get(id);
|
|
72696
|
+
horizontalOffsets.set(id, siblingY);
|
|
72697
|
+
siblingY += height + rowGap;
|
|
72698
|
+
tallest = Math.max(tallest, height);
|
|
72699
|
+
}
|
|
72700
|
+
depthY += tallest + rowGap;
|
|
72701
|
+
}
|
|
72685
72702
|
const nodes = [];
|
|
72686
72703
|
for (const s of stages) {
|
|
72687
72704
|
const col = colMap.get(s.id) ?? 0;
|
|
72688
72705
|
const row = rowIndex.get(s.id) ?? 0;
|
|
72689
72706
|
const x = orientation === "vertical" ? row * (NODE_W + colGap) + (centreShift.get(col) ?? 0) : col * (NODE_W + colGap);
|
|
72690
|
-
const y = orientation === "vertical" ? col
|
|
72691
|
-
nodes.push({ stage: s, col, row, x, y });
|
|
72707
|
+
const y = orientation === "vertical" ? verticalOffsets.get(col) : horizontalOffsets.get(s.id);
|
|
72708
|
+
nodes.push({ stage: s, col, row, x, y, ...opts.nodeHeight ? { height: heights.get(s.id) } : {} });
|
|
72692
72709
|
}
|
|
72693
72710
|
return nodes;
|
|
72694
72711
|
}
|
|
72695
72712
|
|
|
72713
|
+
// dist/builtin/workflows/src/tui/node-card.ts
|
|
72714
|
+
import { stripTerminalSequences } from "@earendil-works/pi-tui";
|
|
72715
|
+
function pulseT(phase) {
|
|
72716
|
+
return (Math.sin(phase * Math.PI * 2 - Math.PI / 2) + 1) / 2;
|
|
72717
|
+
}
|
|
72718
|
+
function queuedBadgeCount(count) {
|
|
72719
|
+
if (typeof count !== "number" || !Number.isFinite(count))
|
|
72720
|
+
return 0;
|
|
72721
|
+
return Math.max(0, Math.trunc(count));
|
|
72722
|
+
}
|
|
72723
|
+
function queuedBadgeText(count) {
|
|
72724
|
+
return `✉ ${count} queued`;
|
|
72725
|
+
}
|
|
72726
|
+
function pickBorder(status, focused, phase, theme) {
|
|
72727
|
+
switch (status) {
|
|
72728
|
+
case "running":
|
|
72729
|
+
if (focused)
|
|
72730
|
+
return theme.warning;
|
|
72731
|
+
return lerpColor(theme.borderDim, theme.warning, pulseT(phase));
|
|
72732
|
+
case "paused":
|
|
72733
|
+
return theme.warning;
|
|
72734
|
+
case "awaiting_input":
|
|
72735
|
+
if (focused)
|
|
72736
|
+
return theme.info;
|
|
72737
|
+
return lerpColor(theme.borderDim, theme.info, pulseT(phase));
|
|
72738
|
+
case "completed":
|
|
72739
|
+
return theme.success;
|
|
72740
|
+
case "failed":
|
|
72741
|
+
return theme.error;
|
|
72742
|
+
case "blocked":
|
|
72743
|
+
return theme.dim;
|
|
72744
|
+
case "skipped":
|
|
72745
|
+
return theme.dim;
|
|
72746
|
+
default:
|
|
72747
|
+
return focused ? theme.borderActive : theme.borderDim;
|
|
72748
|
+
}
|
|
72749
|
+
}
|
|
72750
|
+
function durationColor(status, theme) {
|
|
72751
|
+
switch (status) {
|
|
72752
|
+
case "running":
|
|
72753
|
+
return theme.warning;
|
|
72754
|
+
case "paused":
|
|
72755
|
+
return theme.warning;
|
|
72756
|
+
case "awaiting_input":
|
|
72757
|
+
return theme.info;
|
|
72758
|
+
case "completed":
|
|
72759
|
+
return theme.success;
|
|
72760
|
+
case "failed":
|
|
72761
|
+
return theme.error;
|
|
72762
|
+
default:
|
|
72763
|
+
return theme.dim;
|
|
72764
|
+
}
|
|
72765
|
+
}
|
|
72766
|
+
function blockedBadgeText(stage, stages, width) {
|
|
72767
|
+
const base = "↑ blocked";
|
|
72768
|
+
const blockedBy = stage.blockedByStageId;
|
|
72769
|
+
if (!blockedBy)
|
|
72770
|
+
return base;
|
|
72771
|
+
const upstream = stages?.find((s) => s.id === blockedBy)?.name ?? blockedBy;
|
|
72772
|
+
const withUpstream = `${base} by ${upstream}`;
|
|
72773
|
+
if (visibleWidth(withUpstream) <= width)
|
|
72774
|
+
return withUpstream;
|
|
72775
|
+
return base;
|
|
72776
|
+
}
|
|
72777
|
+
function durationText(stage) {
|
|
72778
|
+
const elapsed = elapsedStageMs(stage);
|
|
72779
|
+
return elapsed === undefined ? "—" : fmtDuration(elapsed);
|
|
72780
|
+
}
|
|
72781
|
+
function metaText(stage) {
|
|
72782
|
+
return stage.topologyState === "unavailable" ? "topology unavailable" : "";
|
|
72783
|
+
}
|
|
72784
|
+
function modelText(stage, innerWidth) {
|
|
72785
|
+
const model = stage.model;
|
|
72786
|
+
if (model === undefined || model === "")
|
|
72787
|
+
return "";
|
|
72788
|
+
const slash = model.lastIndexOf("/");
|
|
72789
|
+
const short = slash >= 0 ? model.slice(slash + 1) : model;
|
|
72790
|
+
const level = stage.thinkingLevel;
|
|
72791
|
+
const showLevel = level !== undefined && level !== "" && level !== "off";
|
|
72792
|
+
const suffix = showLevel ? ` · ${level}` : "";
|
|
72793
|
+
const full = `${short}${suffix}`;
|
|
72794
|
+
if (visibleWidth(full) <= innerWidth)
|
|
72795
|
+
return full;
|
|
72796
|
+
const modelSuffix = short.endsWith("-fast") ? "-fast" : "";
|
|
72797
|
+
const name = modelSuffix ? short.slice(0, -modelSuffix.length) : short;
|
|
72798
|
+
const room = Math.max(1, innerWidth - visibleWidth(modelSuffix + suffix));
|
|
72799
|
+
return `${truncateToWidth2(name, room, "…")}${modelSuffix}${suffix}`;
|
|
72800
|
+
}
|
|
72801
|
+
function workflowChildRunRows(stage, width) {
|
|
72802
|
+
const child = stage.workflowChild ?? stage.workflowChildRun;
|
|
72803
|
+
if (child === undefined)
|
|
72804
|
+
return [];
|
|
72805
|
+
return wrapIdentifierLines(child.runId, Math.max(1, width), "run ", "").map((row) => `${row.prefix}${row.chunk}`);
|
|
72806
|
+
}
|
|
72807
|
+
function workflowChildMetaText(stage) {
|
|
72808
|
+
const completed = stage.workflowChild;
|
|
72809
|
+
if (completed !== undefined) {
|
|
72810
|
+
const outputCount = completed.outputCount ?? Object.keys(completed.outputs).length;
|
|
72811
|
+
return outputCount === 1 ? "1 out" : `${outputCount} outs`;
|
|
72812
|
+
}
|
|
72813
|
+
if (stage.workflowChildRun !== undefined)
|
|
72814
|
+
return "live";
|
|
72815
|
+
return;
|
|
72816
|
+
}
|
|
72817
|
+
function joinCompactStatusMeta(status, meta, width) {
|
|
72818
|
+
const candidates = [`${status} · ${meta}`, `${status} ·${meta}`, `${status}· ${meta}`, `${status}·${meta}`];
|
|
72819
|
+
return candidates.find((candidate) => visibleWidth(candidate) <= width) ?? status;
|
|
72820
|
+
}
|
|
72821
|
+
function nodeCardHeight(stage, opts = {}) {
|
|
72822
|
+
const queuedRows = queuedBadgeCount(opts.queuedMessageCount) > 0 ? 1 : 0;
|
|
72823
|
+
const modelRows = stage.model !== undefined && stage.model !== "" ? 1 : 0;
|
|
72824
|
+
let bodyRows;
|
|
72825
|
+
if (stage.status === "awaiting_input") {
|
|
72826
|
+
bodyRows = 2 + modelRows + queuedRows;
|
|
72827
|
+
} else if (stage.workflowChild !== undefined || stage.workflowChildRun !== undefined) {
|
|
72828
|
+
const innerWidth = Math.max(2, (opts.width ?? NODE_W) - 2);
|
|
72829
|
+
bodyRows = workflowChildRunRows(stage, innerWidth).length + 1 + queuedRows;
|
|
72830
|
+
} else {
|
|
72831
|
+
bodyRows = 2 + modelRows + (metaText(stage) ? 1 : 0) + queuedRows;
|
|
72832
|
+
}
|
|
72833
|
+
return Math.max(NODE_H, bodyRows + 2);
|
|
72834
|
+
}
|
|
72835
|
+
function statusLabel(status) {
|
|
72836
|
+
switch (status) {
|
|
72837
|
+
case "awaiting_input":
|
|
72838
|
+
return "awaiting input";
|
|
72839
|
+
case "completed":
|
|
72840
|
+
return "complete";
|
|
72841
|
+
default:
|
|
72842
|
+
return status.replace(/_/g, " ");
|
|
72843
|
+
}
|
|
72844
|
+
}
|
|
72845
|
+
function truncate(s, maxWidth) {
|
|
72846
|
+
if (maxWidth <= 0)
|
|
72847
|
+
return "";
|
|
72848
|
+
if (visibleWidth(s) <= maxWidth)
|
|
72849
|
+
return s;
|
|
72850
|
+
return truncateToWidth2(s, maxWidth, "…");
|
|
72851
|
+
}
|
|
72852
|
+
function centreColored(content, width, fg, bg, opts = {}) {
|
|
72853
|
+
const safe = truncate(content, width);
|
|
72854
|
+
const safeWidth = visibleWidth(safe);
|
|
72855
|
+
const pad = Math.max(0, width - safeWidth);
|
|
72856
|
+
const left = Math.max(0, Math.floor(pad / 2));
|
|
72857
|
+
const right = Math.max(0, pad - left);
|
|
72858
|
+
const bold = opts.bold ? BOLD : "";
|
|
72859
|
+
return `${bg}${" ".repeat(left)}` + `${hexToAnsi(fg)}${bold}${safe}${RESET}` + `${bg}${" ".repeat(right)}`;
|
|
72860
|
+
}
|
|
72861
|
+
function buildTitleSlot(name, innerWidth, focused, theme, cardBg, compact = false) {
|
|
72862
|
+
const maxName = Math.max(2, compact ? innerWidth - 1 : innerWidth - 4);
|
|
72863
|
+
const safeName = stripTerminalSequences(truncate(name, maxName));
|
|
72864
|
+
if (focused) {
|
|
72865
|
+
const tabText = compact ? safeName : ` ${safeName} `;
|
|
72866
|
+
const styled = `${paint(tabText, theme.surface, {
|
|
72867
|
+
bg: theme.accent,
|
|
72868
|
+
bold: true
|
|
72869
|
+
})}${cardBg}`;
|
|
72870
|
+
return { slot: styled, visibleWidth: visibleWidth(tabText) };
|
|
72871
|
+
}
|
|
72872
|
+
const titleRaw = compact ? safeName : ` ${safeName} `;
|
|
72873
|
+
const styled = `${BOLD}${titleRaw}${RESET}${cardBg}`;
|
|
72874
|
+
return { slot: styled, visibleWidth: visibleWidth(titleRaw) };
|
|
72875
|
+
}
|
|
72876
|
+
function renderNodeCard(stage, opts) {
|
|
72877
|
+
const width = opts.width ?? NODE_W;
|
|
72878
|
+
const height = opts.height ?? nodeCardHeight(stage, opts);
|
|
72879
|
+
const focused = opts.focused ?? false;
|
|
72880
|
+
const phase = opts.pulsePhase ?? 0;
|
|
72881
|
+
const theme = opts.theme;
|
|
72882
|
+
const borderHex = pickBorder(stage.status, focused, phase, theme);
|
|
72883
|
+
const bc = hexToAnsi(borderHex);
|
|
72884
|
+
const bg = DEFAULT_BG;
|
|
72885
|
+
const innerWidth = Math.max(2, width - 2);
|
|
72886
|
+
const child = stage.workflowChild ?? stage.workflowChildRun;
|
|
72887
|
+
const { slot: titleSlot, visibleWidth: titleVisibleWidth } = buildTitleSlot(child === undefined ? stage.name : `↳ ${child.workflow}`, innerWidth, focused, theme, bg, child !== undefined);
|
|
72888
|
+
const titleStart = Math.max(1, Math.floor((innerWidth - titleVisibleWidth) / 2));
|
|
72889
|
+
const titleEnd = titleStart + titleVisibleWidth;
|
|
72890
|
+
const topMiddle = `${bc}${"─".repeat(titleStart)}` + `${titleSlot}${bc}` + `${"─".repeat(Math.max(0, innerWidth - titleEnd))}`;
|
|
72891
|
+
const top = `${bg}${bc}╭${topMiddle}╮${RESET}`;
|
|
72892
|
+
const bottom = `${bg}${bc}╰${"─".repeat(innerWidth)}╯${RESET}`;
|
|
72893
|
+
const bodyText = stage.nodeKind === "tool" ? "durable tool" : stage.status === "blocked" ? blockedBadgeText(stage, opts.stages, innerWidth) : durationText(stage);
|
|
72894
|
+
const bodyHex = durationColor(stage.status, theme);
|
|
72895
|
+
const statusText = `${statusIcon(stage.status)} ${stage.toolStatus ?? statusLabel(stage.status)}`;
|
|
72896
|
+
const queuedCount = queuedBadgeCount(opts.queuedMessageCount);
|
|
72897
|
+
const statusLine = `${bg}${bc}│${RESET}` + centreColored(statusText, innerWidth, bodyHex, bg, {
|
|
72898
|
+
bold: stage.status === "running" || stage.status === "awaiting_input"
|
|
72899
|
+
}) + `${bg}${bc}│${RESET}`;
|
|
72900
|
+
const durLine = `${bg}${bc}│${RESET}` + centreColored(bodyText, innerWidth, bodyHex, bg, {
|
|
72901
|
+
bold: stage.status === "blocked"
|
|
72902
|
+
}) + `${bg}${bc}│${RESET}`;
|
|
72903
|
+
const contentRows = Math.max(0, height - 2);
|
|
72904
|
+
const metaLine = `${bg}${bc}│${RESET}${centreColored(metaText(stage), innerWidth, theme.dim, bg)}${bg}${bc}│${RESET}`;
|
|
72905
|
+
const model = modelText(stage, innerWidth);
|
|
72906
|
+
const modelLine = `${bg}${bc}│${RESET}${centreColored(model, innerWidth, theme.textMuted, bg)}${bg}${bc}│${RESET}`;
|
|
72907
|
+
const childRunLines = workflowChildRunRows(stage, innerWidth).map((row) => `${bg}${bc}│${RESET}${centreColored(row, innerWidth, theme.dim, bg)}${bg}${bc}│${RESET}`);
|
|
72908
|
+
const childMeta = workflowChildMetaText(stage);
|
|
72909
|
+
const childSummary = childMeta === undefined ? undefined : joinCompactStatusMeta(statusText, childMeta, innerWidth);
|
|
72910
|
+
const childSummaryLine = childSummary === undefined ? undefined : `${bg}${bc}│${RESET}` + centreColored(childSummary, innerWidth, bodyHex, bg, {
|
|
72911
|
+
bold: stage.status === "running" || stage.status === "awaiting_input"
|
|
72912
|
+
}) + `${bg}${bc}│${RESET}`;
|
|
72913
|
+
const queuedLines = queuedCount > 0 ? [
|
|
72914
|
+
`${bg}${bc}│${RESET}` + centreColored(queuedBadgeText(queuedCount), innerWidth, theme.info, bg, { bold: true }) + `${bg}${bc}│${RESET}`
|
|
72915
|
+
] : [];
|
|
72916
|
+
const modelLines = model === "" ? [] : [modelLine];
|
|
72917
|
+
const interior = stage.status === "awaiting_input" ? [
|
|
72918
|
+
...modelLines,
|
|
72919
|
+
statusLine,
|
|
72920
|
+
...model === "" && queuedCount === 0 ? [
|
|
72921
|
+
`${bg}${bc}│${RESET}` + centreColored("waiting for response", innerWidth, theme.info, bg) + `${bg}${bc}│${RESET}`
|
|
72922
|
+
] : [],
|
|
72923
|
+
...queuedLines,
|
|
72924
|
+
`${bg}${bc}│${RESET}` + centreColored("↵ enter to respond", innerWidth, theme.dim, bg) + `${bg}${bc}│${RESET}`
|
|
72925
|
+
] : childSummaryLine === undefined ? [durLine, ...modelLines, statusLine, ...metaText(stage) ? [metaLine] : [], ...queuedLines] : [...childRunLines, childSummaryLine, ...queuedLines];
|
|
72926
|
+
while (interior.length < contentRows) {
|
|
72927
|
+
interior.push(`${bg}${bc}│${RESET}${bg}${" ".repeat(innerWidth)}${bg}${bc}│${RESET}`);
|
|
72928
|
+
}
|
|
72929
|
+
if (interior.length > contentRows)
|
|
72930
|
+
interior.length = contentRows;
|
|
72931
|
+
return [top, ...interior, bottom];
|
|
72932
|
+
}
|
|
72933
|
+
|
|
72696
72934
|
// dist/builtin/workflows/src/tui/prompt-card-select.ts
|
|
72697
72935
|
import { SelectList, truncateToWidth as truncateToWidth3 } from "@earendil-works/pi-tui";
|
|
72698
72936
|
function createPromptSelectList(state, theme, maxVisible = 5) {
|
|
@@ -73558,9 +73796,25 @@ class GraphViewState {
|
|
|
73558
73796
|
_needsAnimationTick() {
|
|
73559
73797
|
return this.promptState !== null || this.hasAnimatingStages;
|
|
73560
73798
|
}
|
|
73799
|
+
_nodeHeight(stage) {
|
|
73800
|
+
const baseHeight = nodeCardHeight(stage);
|
|
73801
|
+
if (!this.getStageQueuedMessageCount || nodeCardHeight(stage, { queuedMessageCount: 1 }) === baseHeight) {
|
|
73802
|
+
return baseHeight;
|
|
73803
|
+
}
|
|
73804
|
+
return nodeCardHeight(stage, { queuedMessageCount: this._stageQueuedMessageCount(stage) });
|
|
73805
|
+
}
|
|
73806
|
+
_refreshQueuedNodeHeights() {
|
|
73807
|
+
if (!this.getStageQueuedMessageCount)
|
|
73808
|
+
return;
|
|
73809
|
+
if (!this.cachedLayout.some((node) => (node.height ?? NODE_H) !== this._nodeHeight(node.stage)))
|
|
73810
|
+
return;
|
|
73811
|
+
this.lastBuiltSnapshotVersion = null;
|
|
73812
|
+
this._rebuildLayout();
|
|
73813
|
+
}
|
|
73561
73814
|
_rebuildLayout() {
|
|
73562
73815
|
const version = this.currentSnapshot?.version ?? null;
|
|
73563
73816
|
if (version !== null && version === this.lastBuiltSnapshotVersion) {
|
|
73817
|
+
this._refreshQueuedNodeHeights();
|
|
73564
73818
|
return;
|
|
73565
73819
|
}
|
|
73566
73820
|
const run = this._getCurrentRun();
|
|
@@ -73587,6 +73841,8 @@ class GraphViewState {
|
|
|
73587
73841
|
const next = graphStages[index];
|
|
73588
73842
|
if (!next || node.stage.id !== next.id || node.stage.nodeKind !== next.nodeKind)
|
|
73589
73843
|
return false;
|
|
73844
|
+
if ((node.height ?? NODE_H) !== this._nodeHeight(next))
|
|
73845
|
+
return false;
|
|
73590
73846
|
if (node.stage.parentIds.length !== next.parentIds.length)
|
|
73591
73847
|
return false;
|
|
73592
73848
|
return node.stage.parentIds.every((parentId, parentIndex) => parentId === next.parentIds[parentIndex]);
|
|
@@ -73602,7 +73858,10 @@ class GraphViewState {
|
|
|
73602
73858
|
this.lastBuiltSnapshotVersion = version;
|
|
73603
73859
|
return;
|
|
73604
73860
|
}
|
|
73605
|
-
const nextLayout = computeLayout(graphStages, {
|
|
73861
|
+
const nextLayout = computeLayout(graphStages, {
|
|
73862
|
+
orientation: "vertical",
|
|
73863
|
+
nodeHeight: (stage) => this._nodeHeight(stage)
|
|
73864
|
+
});
|
|
73606
73865
|
this.cachedLayout = nextLayout;
|
|
73607
73866
|
this.cachedDisplayStages = nextLayout.map((node) => node.stage);
|
|
73608
73867
|
this.cachedRenderGeometry = this._buildRenderGeometry(nextLayout);
|
|
@@ -73621,13 +73880,15 @@ class GraphViewState {
|
|
|
73621
73880
|
for (let index = 0;index < layout.length; index++) {
|
|
73622
73881
|
const node = layout[index];
|
|
73623
73882
|
canvasWidth = Math.max(canvasWidth, node.x + NODE_W);
|
|
73624
|
-
|
|
73883
|
+
const bottom = node.y + (node.height ?? NODE_H);
|
|
73884
|
+
totalRows = Math.max(totalRows, bottom);
|
|
73625
73885
|
nodeByStageId.set(node.stage.id, node);
|
|
73626
73886
|
const band = bandsByTop.get(node.y);
|
|
73627
|
-
if (band)
|
|
73887
|
+
if (band) {
|
|
73628
73888
|
band.nodeIndices.push(index);
|
|
73629
|
-
|
|
73630
|
-
|
|
73889
|
+
band.bottom = Math.max(band.bottom, bottom);
|
|
73890
|
+
} else
|
|
73891
|
+
bandsByTop.set(node.y, { top: node.y, bottom, nodeIndices: [index] });
|
|
73631
73892
|
}
|
|
73632
73893
|
const edges = [];
|
|
73633
73894
|
for (const node of layout) {
|
|
@@ -73640,9 +73901,10 @@ class GraphViewState {
|
|
|
73640
73901
|
edges.push({
|
|
73641
73902
|
parentX: parent.x,
|
|
73642
73903
|
parentY: parent.y,
|
|
73904
|
+
parentHeight: parent.height ?? NODE_H,
|
|
73643
73905
|
childX: node.x,
|
|
73644
73906
|
childY: node.y,
|
|
73645
|
-
top: parent.y + NODE_H,
|
|
73907
|
+
top: parent.y + (parent.height ?? NODE_H),
|
|
73646
73908
|
bottom: node.y,
|
|
73647
73909
|
left: Math.min(parentCol, childCol),
|
|
73648
73910
|
right: Math.max(parentCol, childCol) + 1
|
|
@@ -73978,10 +74240,10 @@ class GraphViewRenderHelpers extends GraphViewState {
|
|
|
73978
74240
|
}
|
|
73979
74241
|
this._clampGraphHorizontalScroll(totalCols, viewportCols);
|
|
73980
74242
|
}
|
|
73981
|
-
_plotEdge(canvas, px, py, cx, cy, color) {
|
|
74243
|
+
_plotEdge(canvas, px, py, cx, cy, color, parentHeight = NODE_H) {
|
|
73982
74244
|
const parentCol = px + Math.floor(NODE_W / 2);
|
|
73983
74245
|
const childCol = cx + Math.floor(NODE_W / 2);
|
|
73984
|
-
const parentExitRow = py +
|
|
74246
|
+
const parentExitRow = py + parentHeight;
|
|
73985
74247
|
const childEntryRow = cy - 1;
|
|
73986
74248
|
if (childEntryRow < parentExitRow)
|
|
73987
74249
|
return;
|
|
@@ -74040,214 +74302,6 @@ class GraphViewRenderHelpers extends GraphViewState {
|
|
|
74040
74302
|
}
|
|
74041
74303
|
}
|
|
74042
74304
|
|
|
74043
|
-
// dist/builtin/workflows/src/tui/node-card.ts
|
|
74044
|
-
import { stripTerminalSequences } from "@earendil-works/pi-tui";
|
|
74045
|
-
function pulseT(phase) {
|
|
74046
|
-
return (Math.sin(phase * Math.PI * 2 - Math.PI / 2) + 1) / 2;
|
|
74047
|
-
}
|
|
74048
|
-
function queuedBadgeCount(count) {
|
|
74049
|
-
if (typeof count !== "number" || !Number.isFinite(count))
|
|
74050
|
-
return 0;
|
|
74051
|
-
return Math.max(0, Math.trunc(count));
|
|
74052
|
-
}
|
|
74053
|
-
function queuedBadgeText(count) {
|
|
74054
|
-
return `✉ ${count} queued`;
|
|
74055
|
-
}
|
|
74056
|
-
function pickBorder(status, focused, phase, theme) {
|
|
74057
|
-
switch (status) {
|
|
74058
|
-
case "running":
|
|
74059
|
-
if (focused)
|
|
74060
|
-
return theme.warning;
|
|
74061
|
-
return lerpColor(theme.borderDim, theme.warning, pulseT(phase));
|
|
74062
|
-
case "paused":
|
|
74063
|
-
return theme.warning;
|
|
74064
|
-
case "awaiting_input":
|
|
74065
|
-
if (focused)
|
|
74066
|
-
return theme.info;
|
|
74067
|
-
return lerpColor(theme.borderDim, theme.info, pulseT(phase));
|
|
74068
|
-
case "completed":
|
|
74069
|
-
return theme.success;
|
|
74070
|
-
case "failed":
|
|
74071
|
-
return theme.error;
|
|
74072
|
-
case "blocked":
|
|
74073
|
-
return theme.dim;
|
|
74074
|
-
case "skipped":
|
|
74075
|
-
return theme.dim;
|
|
74076
|
-
default:
|
|
74077
|
-
return focused ? theme.borderActive : theme.borderDim;
|
|
74078
|
-
}
|
|
74079
|
-
}
|
|
74080
|
-
function durationColor(status, theme) {
|
|
74081
|
-
switch (status) {
|
|
74082
|
-
case "running":
|
|
74083
|
-
return theme.warning;
|
|
74084
|
-
case "paused":
|
|
74085
|
-
return theme.warning;
|
|
74086
|
-
case "awaiting_input":
|
|
74087
|
-
return theme.info;
|
|
74088
|
-
case "completed":
|
|
74089
|
-
return theme.success;
|
|
74090
|
-
case "failed":
|
|
74091
|
-
return theme.error;
|
|
74092
|
-
default:
|
|
74093
|
-
return theme.dim;
|
|
74094
|
-
}
|
|
74095
|
-
}
|
|
74096
|
-
function blockedBadgeText(stage, stages, width) {
|
|
74097
|
-
const base = "↑ blocked";
|
|
74098
|
-
const blockedBy = stage.blockedByStageId;
|
|
74099
|
-
if (!blockedBy)
|
|
74100
|
-
return base;
|
|
74101
|
-
const upstream = stages?.find((s) => s.id === blockedBy)?.name ?? blockedBy;
|
|
74102
|
-
const withUpstream = `${base} by ${upstream}`;
|
|
74103
|
-
if (visibleWidth(withUpstream) <= width)
|
|
74104
|
-
return withUpstream;
|
|
74105
|
-
return base;
|
|
74106
|
-
}
|
|
74107
|
-
function durationText(stage) {
|
|
74108
|
-
const elapsed = elapsedStageMs(stage);
|
|
74109
|
-
return elapsed === undefined ? "—" : fmtDuration(elapsed);
|
|
74110
|
-
}
|
|
74111
|
-
function metaText(stage) {
|
|
74112
|
-
if (stage.topologyState === "unavailable")
|
|
74113
|
-
return "topology unavailable";
|
|
74114
|
-
const deps = stage.parentIds.length;
|
|
74115
|
-
const dependencyText = deps === 0 ? "root" : deps === 1 ? "1 dep" : `${deps} deps`;
|
|
74116
|
-
return dependencyText;
|
|
74117
|
-
}
|
|
74118
|
-
function modelText(stage, innerWidth) {
|
|
74119
|
-
const model = stage.model;
|
|
74120
|
-
if (model === undefined || model === "")
|
|
74121
|
-
return "—";
|
|
74122
|
-
const slash = model.lastIndexOf("/");
|
|
74123
|
-
const short = slash >= 0 ? model.slice(slash + 1) : model;
|
|
74124
|
-
const level = stage.thinkingLevel;
|
|
74125
|
-
const showLevel = level !== undefined && level !== "" && level !== "off";
|
|
74126
|
-
const suffix = showLevel ? ` · ${level}` : "";
|
|
74127
|
-
const full = `${short}${suffix}`;
|
|
74128
|
-
if (visibleWidth(full) <= innerWidth)
|
|
74129
|
-
return full;
|
|
74130
|
-
const modelSuffix = short.endsWith("-fast") ? "-fast" : "";
|
|
74131
|
-
const name = modelSuffix ? short.slice(0, -modelSuffix.length) : short;
|
|
74132
|
-
const room = Math.max(1, innerWidth - visibleWidth(modelSuffix + suffix));
|
|
74133
|
-
return `${truncateToWidth2(name, room, "…")}${modelSuffix}${suffix}`;
|
|
74134
|
-
}
|
|
74135
|
-
function workflowChildRunRows(stage, width) {
|
|
74136
|
-
const child = stage.workflowChild ?? stage.workflowChildRun;
|
|
74137
|
-
if (child === undefined)
|
|
74138
|
-
return [];
|
|
74139
|
-
return wrapIdentifierLines(child.runId, Math.max(1, width), "run ", "").map((row) => `${row.prefix}${row.chunk}`);
|
|
74140
|
-
}
|
|
74141
|
-
function workflowChildMetaText(stage) {
|
|
74142
|
-
const completed = stage.workflowChild;
|
|
74143
|
-
if (completed !== undefined) {
|
|
74144
|
-
const outputCount = completed.outputCount ?? Object.keys(completed.outputs).length;
|
|
74145
|
-
return outputCount === 1 ? "1 out" : `${outputCount} outs`;
|
|
74146
|
-
}
|
|
74147
|
-
if (stage.workflowChildRun !== undefined)
|
|
74148
|
-
return "live";
|
|
74149
|
-
return;
|
|
74150
|
-
}
|
|
74151
|
-
function joinCompactStatusMeta(status, meta, width) {
|
|
74152
|
-
const candidates = [`${status} · ${meta}`, `${status} ·${meta}`, `${status}· ${meta}`, `${status}·${meta}`];
|
|
74153
|
-
return candidates.find((candidate) => visibleWidth(candidate) <= width) ?? meta;
|
|
74154
|
-
}
|
|
74155
|
-
function statusLabel(status) {
|
|
74156
|
-
switch (status) {
|
|
74157
|
-
case "awaiting_input":
|
|
74158
|
-
return "awaiting input";
|
|
74159
|
-
case "completed":
|
|
74160
|
-
return "complete";
|
|
74161
|
-
default:
|
|
74162
|
-
return status.replace(/_/g, " ");
|
|
74163
|
-
}
|
|
74164
|
-
}
|
|
74165
|
-
function truncate(s, maxWidth) {
|
|
74166
|
-
if (maxWidth <= 0)
|
|
74167
|
-
return "";
|
|
74168
|
-
if (visibleWidth(s) <= maxWidth)
|
|
74169
|
-
return s;
|
|
74170
|
-
return truncateToWidth2(s, maxWidth, "…");
|
|
74171
|
-
}
|
|
74172
|
-
function centreColored(content, width, fg, bg, opts = {}) {
|
|
74173
|
-
const safe = truncate(content, width);
|
|
74174
|
-
const safeWidth = visibleWidth(safe);
|
|
74175
|
-
const pad = Math.max(0, width - safeWidth);
|
|
74176
|
-
const left = Math.max(0, Math.floor(pad / 2));
|
|
74177
|
-
const right = Math.max(0, pad - left);
|
|
74178
|
-
const bold = opts.bold ? BOLD : "";
|
|
74179
|
-
return `${bg}${" ".repeat(left)}` + `${hexToAnsi(fg)}${bold}${safe}${RESET}` + `${bg}${" ".repeat(right)}`;
|
|
74180
|
-
}
|
|
74181
|
-
function buildTitleSlot(name, innerWidth, focused, theme, cardBg, compact = false) {
|
|
74182
|
-
const maxName = Math.max(2, compact ? innerWidth - 1 : innerWidth - 4);
|
|
74183
|
-
const safeName = stripTerminalSequences(truncate(name, maxName));
|
|
74184
|
-
if (focused) {
|
|
74185
|
-
const tabText = compact ? safeName : ` ${safeName} `;
|
|
74186
|
-
const styled = `${paint(tabText, theme.surface, {
|
|
74187
|
-
bg: theme.accent,
|
|
74188
|
-
bold: true
|
|
74189
|
-
})}${cardBg}`;
|
|
74190
|
-
return { slot: styled, visibleWidth: visibleWidth(tabText) };
|
|
74191
|
-
}
|
|
74192
|
-
const titleRaw = compact ? safeName : ` ${safeName} `;
|
|
74193
|
-
const styled = `${BOLD}${titleRaw}${RESET}${cardBg}`;
|
|
74194
|
-
return { slot: styled, visibleWidth: visibleWidth(titleRaw) };
|
|
74195
|
-
}
|
|
74196
|
-
function renderNodeCard(stage, opts) {
|
|
74197
|
-
const width = opts.width ?? NODE_W;
|
|
74198
|
-
const height = opts.height ?? NODE_H;
|
|
74199
|
-
const focused = opts.focused ?? false;
|
|
74200
|
-
const phase = opts.pulsePhase ?? 0;
|
|
74201
|
-
const theme = opts.theme;
|
|
74202
|
-
const borderHex = pickBorder(stage.status, focused, phase, theme);
|
|
74203
|
-
const bc = hexToAnsi(borderHex);
|
|
74204
|
-
const bg = DEFAULT_BG;
|
|
74205
|
-
const innerWidth = Math.max(2, width - 2);
|
|
74206
|
-
const child = stage.workflowChild ?? stage.workflowChildRun;
|
|
74207
|
-
const { slot: titleSlot, visibleWidth: titleVisibleWidth } = buildTitleSlot(child === undefined ? stage.name : `↳ ${child.workflow}`, innerWidth, focused, theme, bg, child !== undefined);
|
|
74208
|
-
const titleStart = Math.max(1, Math.floor((innerWidth - titleVisibleWidth) / 2));
|
|
74209
|
-
const titleEnd = titleStart + titleVisibleWidth;
|
|
74210
|
-
const topMiddle = `${bc}${"─".repeat(titleStart)}` + `${titleSlot}${bc}` + `${"─".repeat(Math.max(0, innerWidth - titleEnd))}`;
|
|
74211
|
-
const top = `${bg}${bc}╭${topMiddle}╮${RESET}`;
|
|
74212
|
-
const bottom = `${bg}${bc}╰${"─".repeat(innerWidth)}╯${RESET}`;
|
|
74213
|
-
const bodyText = stage.nodeKind === "tool" ? "durable tool" : stage.status === "blocked" ? blockedBadgeText(stage, opts.stages, innerWidth) : durationText(stage);
|
|
74214
|
-
const bodyHex = durationColor(stage.status, theme);
|
|
74215
|
-
const statusText = `${statusIcon(stage.status)} ${stage.toolStatus ?? statusLabel(stage.status)}`;
|
|
74216
|
-
const statusLine = `${bg}${bc}│${RESET}` + centreColored(statusText, innerWidth, bodyHex, bg, {
|
|
74217
|
-
bold: stage.status === "running" || stage.status === "awaiting_input"
|
|
74218
|
-
}) + `${bg}${bc}│${RESET}`;
|
|
74219
|
-
const durLine = `${bg}${bc}│${RESET}` + centreColored(bodyText, innerWidth, bodyHex, bg, {
|
|
74220
|
-
bold: stage.status === "blocked"
|
|
74221
|
-
}) + `${bg}${bc}│${RESET}`;
|
|
74222
|
-
const contentRows = Math.max(0, height - 2);
|
|
74223
|
-
const metaLine = `${bg}${bc}│${RESET}${centreColored(metaText(stage), innerWidth, theme.dim, bg)}${bg}${bc}│${RESET}`;
|
|
74224
|
-
const modelLine = `${bg}${bc}│${RESET}${centreColored(modelText(stage, innerWidth), innerWidth, theme.textMuted, bg)}${bg}${bc}│${RESET}`;
|
|
74225
|
-
const childRunLines = workflowChildRunRows(stage, innerWidth).map((row) => `${bg}${bc}│${RESET}${centreColored(row, innerWidth, theme.dim, bg)}${bg}${bc}│${RESET}`);
|
|
74226
|
-
const queuedCount = queuedBadgeCount(opts.queuedMessageCount);
|
|
74227
|
-
const childMeta = workflowChildMetaText(stage);
|
|
74228
|
-
const childSummary = childMeta === undefined ? undefined : joinCompactStatusMeta(statusText, queuedCount > 0 ? queuedBadgeText(queuedCount) : childMeta, innerWidth);
|
|
74229
|
-
const childSummaryLine = childSummary === undefined ? undefined : `${bg}${bc}│${RESET}` + centreColored(childSummary, innerWidth, bodyHex, bg, {
|
|
74230
|
-
bold: stage.status === "running" || stage.status === "awaiting_input"
|
|
74231
|
-
}) + `${bg}${bc}│${RESET}`;
|
|
74232
|
-
const interior = stage.status === "awaiting_input" ? [
|
|
74233
|
-
statusLine,
|
|
74234
|
-
`${bg}${bc}│${RESET}` + centreColored("waiting for response", innerWidth, theme.info, bg) + `${bg}${bc}│${RESET}`,
|
|
74235
|
-
`${bg}${bc}│${RESET}` + centreColored("↵ enter to respond", innerWidth, theme.dim, bg) + `${bg}${bc}│${RESET}`,
|
|
74236
|
-
modelLine
|
|
74237
|
-
] : childSummaryLine === undefined ? [durLine, statusLine, modelLine, metaLine] : [...childRunLines, childSummaryLine];
|
|
74238
|
-
const preferredBadgeRow = stage.status === "awaiting_input" ? 1 : childSummaryLine === undefined ? interior.length - 1 : -1;
|
|
74239
|
-
while (interior.length < contentRows) {
|
|
74240
|
-
interior.push(`${bg}${bc}│${RESET}${bg}${" ".repeat(innerWidth)}${bg}${bc}│${RESET}`);
|
|
74241
|
-
}
|
|
74242
|
-
if (interior.length > contentRows)
|
|
74243
|
-
interior.length = contentRows;
|
|
74244
|
-
if (queuedCount > 0 && interior.length > 0 && preferredBadgeRow >= 0) {
|
|
74245
|
-
const badgeRow = preferredBadgeRow < interior.length ? preferredBadgeRow : interior.length - 1;
|
|
74246
|
-
interior[badgeRow] = `${bg}${bc}│${RESET}` + centreColored(queuedBadgeText(queuedCount), innerWidth, theme.info, bg, { bold: true }) + `${bg}${bc}│${RESET}`;
|
|
74247
|
-
}
|
|
74248
|
-
return [top, ...interior, bottom];
|
|
74249
|
-
}
|
|
74250
|
-
|
|
74251
74305
|
// dist/builtin/workflows/src/tui/graph-view-graph-render.ts
|
|
74252
74306
|
class GraphViewGraphRenderer extends GraphViewRenderHelpers {
|
|
74253
74307
|
_renderGraph(width, viewportTop, viewportRows, renderRun) {
|
|
@@ -74292,7 +74346,7 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
|
|
|
74292
74346
|
if (edge.bottom <= safeTop || edge.top >= viewportBottom || edge.right <= viewportLeft || edge.left >= viewportRight) {
|
|
74293
74347
|
continue;
|
|
74294
74348
|
}
|
|
74295
|
-
this._plotEdge(edgeCanvas, edge.parentX, edge.parentY, edge.childX, edge.childY, edgeColor);
|
|
74349
|
+
this._plotEdge(edgeCanvas, edge.parentX, edge.parentY, edge.childX, edge.childY, edgeColor, edge.parentHeight);
|
|
74296
74350
|
}
|
|
74297
74351
|
const edgeLines = edgeCanvas.toLines();
|
|
74298
74352
|
const placements = new Map;
|
|
@@ -74306,7 +74360,7 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
|
|
|
74306
74360
|
continue;
|
|
74307
74361
|
const cardLines = renderNodeCard(node.stage, {
|
|
74308
74362
|
width: NODE_W,
|
|
74309
|
-
height: NODE_H,
|
|
74363
|
+
height: node.height ?? NODE_H,
|
|
74310
74364
|
focused: ni === this.focusedIndex,
|
|
74311
74365
|
pulsePhase,
|
|
74312
74366
|
theme: this.graphTheme,
|
|
@@ -74363,7 +74417,7 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
|
|
|
74363
74417
|
for (const index of band.nodeIndices) {
|
|
74364
74418
|
const node = this.cachedLayout[index];
|
|
74365
74419
|
const top = graphStartRow + node.y - viewportTop;
|
|
74366
|
-
const bottom = top + NODE_H;
|
|
74420
|
+
const bottom = top + (node.height ?? NODE_H);
|
|
74367
74421
|
const left = viewport.leftMargin + node.x - this.graphScrollColOffset;
|
|
74368
74422
|
const right = left + NODE_W;
|
|
74369
74423
|
const clippedTop = Math.max(visibleTop, top);
|
|
@@ -75071,6 +75125,7 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
|
|
|
75071
75125
|
render(width) {
|
|
75072
75126
|
if (this.mode === "widget")
|
|
75073
75127
|
return this._renderWidget(width);
|
|
75128
|
+
this._refreshQueuedNodeHeights();
|
|
75074
75129
|
return this._renderOverlay(width);
|
|
75075
75130
|
}
|
|
75076
75131
|
dispose() {
|
|
@@ -75183,8 +75238,8 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
|
|
|
75183
75238
|
let next = scrollView.scrollTop;
|
|
75184
75239
|
if (node.y < next)
|
|
75185
75240
|
next = node.y;
|
|
75186
|
-
else if (node.y + NODE_H > next + viewportRows)
|
|
75187
|
-
next = node.y + NODE_H - viewportRows;
|
|
75241
|
+
else if (node.y + (node.height ?? NODE_H) > next + viewportRows)
|
|
75242
|
+
next = node.y + (node.height ?? NODE_H) - viewportRows;
|
|
75188
75243
|
scrollView.scrollTo(next);
|
|
75189
75244
|
const graphInner = Math.max(1, width - 4);
|
|
75190
75245
|
const leftMargin = Math.max(2, this.cachedRenderGeometry.canvasWidth <= graphInner ? Math.floor((graphInner - this.cachedRenderGeometry.canvasWidth) / 2) : 2);
|
|
@@ -76420,6 +76475,7 @@ class StageUiBroker {
|
|
|
76420
76475
|
};
|
|
76421
76476
|
}
|
|
76422
76477
|
requestCustomUi(runId, stageId, factory, options, signal) {
|
|
76478
|
+
signal = options?.signal ? signal ? AbortSignal.any([signal, options.signal]) : options.signal : signal;
|
|
76423
76479
|
if (signal?.aborted) {
|
|
76424
76480
|
return Promise.reject(signal.reason ?? new Error("atomic-workflows: stage UI request aborted"));
|
|
76425
76481
|
}
|
|
@@ -82123,6 +82179,108 @@ function collectDefinitionName(tokens, localValues, workflowNames) {
|
|
|
82123
82179
|
}
|
|
82124
82180
|
return;
|
|
82125
82181
|
}
|
|
82182
|
+
function discoveryField(object) {
|
|
82183
|
+
if (object?.[0]?.value !== "{" || object.at(-1)?.value !== "}")
|
|
82184
|
+
return;
|
|
82185
|
+
let value2;
|
|
82186
|
+
for (const field of arrayElements(object)) {
|
|
82187
|
+
let key = field;
|
|
82188
|
+
while (["get", "set", "async", "*"].includes(key[0]?.value ?? ""))
|
|
82189
|
+
key = key.slice(1);
|
|
82190
|
+
if (key[0]?.value === "[" || key !== field && key[0]?.value === "possibleStageNames")
|
|
82191
|
+
return;
|
|
82192
|
+
if (field[0]?.value === ".") {
|
|
82193
|
+
if (value2 !== undefined)
|
|
82194
|
+
return;
|
|
82195
|
+
continue;
|
|
82196
|
+
}
|
|
82197
|
+
if (field[0]?.value !== "possibleStageNames")
|
|
82198
|
+
continue;
|
|
82199
|
+
if (value2 !== undefined || field[1]?.value !== ":")
|
|
82200
|
+
return;
|
|
82201
|
+
value2 = field.slice(2);
|
|
82202
|
+
}
|
|
82203
|
+
return value2;
|
|
82204
|
+
}
|
|
82205
|
+
function literalDiscoveryNames(value2) {
|
|
82206
|
+
if (value2?.[0]?.value !== "[" || value2.at(-1)?.value !== "]")
|
|
82207
|
+
return;
|
|
82208
|
+
const names = [];
|
|
82209
|
+
for (const element of arrayElements(value2)) {
|
|
82210
|
+
if (element.length !== 1 || element[0]?.kind !== "string")
|
|
82211
|
+
return;
|
|
82212
|
+
names.push(element[0].value);
|
|
82213
|
+
}
|
|
82214
|
+
return names.length > 0 ? names : undefined;
|
|
82215
|
+
}
|
|
82216
|
+
function discoveryHelpers(tokens) {
|
|
82217
|
+
const helpers = [];
|
|
82218
|
+
for (let index = 0;index < tokens.length; index += 1) {
|
|
82219
|
+
if (tokens[index]?.value !== "function" || tokens[index + 1]?.kind !== "ident")
|
|
82220
|
+
continue;
|
|
82221
|
+
let open = index + 2;
|
|
82222
|
+
if (tokens[open]?.value === "<")
|
|
82223
|
+
open = (matchBracket(tokens, open, "<", ">") ?? tokens.length) + 1;
|
|
82224
|
+
if (tokens[open]?.value !== "(")
|
|
82225
|
+
continue;
|
|
82226
|
+
const close = matchBracket(tokens, open, "(", ")");
|
|
82227
|
+
if (close === undefined)
|
|
82228
|
+
continue;
|
|
82229
|
+
let bodyOpen = close + 1;
|
|
82230
|
+
while (bodyOpen < tokens.length && tokens[bodyOpen]?.value !== "{")
|
|
82231
|
+
bodyOpen += 1;
|
|
82232
|
+
const bodyClose = matchBracket(tokens, bodyOpen, "{", "}");
|
|
82233
|
+
if (bodyClose === undefined)
|
|
82234
|
+
continue;
|
|
82235
|
+
const preceding = tokens[index - (tokens[index - 1]?.value === "async" ? 2 : 1)]?.value;
|
|
82236
|
+
helpers.push({
|
|
82237
|
+
name: tokens[index + 1].value,
|
|
82238
|
+
nameIndex: index + 1,
|
|
82239
|
+
params: splitTopLevelArguments({ method: "parallel", argsOpen: open }, tokens),
|
|
82240
|
+
bodyOpen,
|
|
82241
|
+
bodyClose,
|
|
82242
|
+
declaration: preceding === undefined || ["export", ";", "{", "}"].includes(preceding)
|
|
82243
|
+
});
|
|
82244
|
+
}
|
|
82245
|
+
return helpers;
|
|
82246
|
+
}
|
|
82247
|
+
function hasDiscoveryDestructuringWrite(tokens, parameter) {
|
|
82248
|
+
for (let index = 0;index < tokens.length; index += 1) {
|
|
82249
|
+
const open = tokens[index]?.value;
|
|
82250
|
+
if (open !== "[" && open !== "{")
|
|
82251
|
+
continue;
|
|
82252
|
+
const close = matchBracket(tokens, index, open, open === "[" ? "]" : "}");
|
|
82253
|
+
if (close === undefined || !["=", "of", "in"].includes(tokens[close + 1]?.value ?? ""))
|
|
82254
|
+
continue;
|
|
82255
|
+
if (tokens.slice(index + 1, close).some((token) => token.kind === "ident" && token.value === parameter))
|
|
82256
|
+
return true;
|
|
82257
|
+
}
|
|
82258
|
+
return false;
|
|
82259
|
+
}
|
|
82260
|
+
function discoveryCalls(tokens, name, declaration) {
|
|
82261
|
+
const calls = [];
|
|
82262
|
+
for (let index = 0;index < tokens.length; index += 1) {
|
|
82263
|
+
if (tokens[index]?.value === "import") {
|
|
82264
|
+
while (index < tokens.length && tokens[index]?.kind !== "string")
|
|
82265
|
+
index += 1;
|
|
82266
|
+
continue;
|
|
82267
|
+
}
|
|
82268
|
+
if (tokens[index]?.value === "export" && tokens[index + 1]?.value === "{") {
|
|
82269
|
+
const close = matchBracket(tokens, index + 1, "{", "}") ?? tokens.length;
|
|
82270
|
+
const exported = tokens.slice(index + 2, close);
|
|
82271
|
+
if (exported.some((token, offset) => token.value === name && (declaration === undefined || exported[offset + 1]?.value === "as")))
|
|
82272
|
+
return;
|
|
82273
|
+
index = close;
|
|
82274
|
+
continue;
|
|
82275
|
+
}
|
|
82276
|
+
if (tokens[index]?.kind !== "ident" || tokens[index]?.value !== name || index === declaration)
|
|
82277
|
+
continue;
|
|
82278
|
+
if (tokens[index + 1]?.value !== "(" || [".", "?.", "function"].includes(tokens[index - 1]?.value ?? ""))
|
|
82279
|
+
return;
|
|
82280
|
+
calls.push(index + 1);
|
|
82281
|
+
}
|
|
82282
|
+
return calls;
|
|
82283
|
+
}
|
|
82126
82284
|
|
|
82127
82285
|
class PossibleStagesScanner {
|
|
82128
82286
|
stages = new Set;
|
|
@@ -82131,6 +82289,7 @@ class PossibleStagesScanner {
|
|
|
82131
82289
|
maxDepth;
|
|
82132
82290
|
units = new Map;
|
|
82133
82291
|
aliasPool = new Set;
|
|
82292
|
+
closure = [];
|
|
82134
82293
|
constructor(maxDepth) {
|
|
82135
82294
|
this.maxDepth = maxDepth;
|
|
82136
82295
|
}
|
|
@@ -82166,11 +82325,17 @@ class PossibleStagesScanner {
|
|
|
82166
82325
|
this.aliasPool.add(alias);
|
|
82167
82326
|
}
|
|
82168
82327
|
}
|
|
82169
|
-
|
|
82170
|
-
|
|
82171
|
-
|
|
82172
|
-
|
|
82173
|
-
|
|
82328
|
+
const previousClosure = this.closure;
|
|
82329
|
+
this.closure = ordered;
|
|
82330
|
+
try {
|
|
82331
|
+
for (const path of ordered) {
|
|
82332
|
+
const unit = this.units.get(path);
|
|
82333
|
+
if (unit === undefined)
|
|
82334
|
+
continue;
|
|
82335
|
+
this.scanUnit(unit, path, boundaryPrefix, depth, ancestorStack);
|
|
82336
|
+
}
|
|
82337
|
+
} finally {
|
|
82338
|
+
this.closure = previousClosure;
|
|
82174
82339
|
}
|
|
82175
82340
|
}
|
|
82176
82341
|
unitFor(path) {
|
|
@@ -82284,7 +82449,127 @@ class PossibleStagesScanner {
|
|
|
82284
82449
|
}
|
|
82285
82450
|
return resolveRelativeSpecifier(specifier, importingFile);
|
|
82286
82451
|
}
|
|
82452
|
+
hasDataOnlyDiscoveryOptions(argument) {
|
|
82453
|
+
if (argument?.[0]?.value !== "{" || argument.at(-1)?.value !== "}")
|
|
82454
|
+
return false;
|
|
82455
|
+
return arrayElements(argument).every((field) => (field[0]?.kind === "ident" || field[0]?.kind === "string") && field[0].value !== "__proto__" && field[1]?.value === ":");
|
|
82456
|
+
}
|
|
82457
|
+
discoveryNames(call, unit, path) {
|
|
82458
|
+
if (call.method !== "parallel")
|
|
82459
|
+
return;
|
|
82460
|
+
const value2 = discoveryField(splitTopLevelArguments(call, unit.tokens)[1]);
|
|
82461
|
+
const literal = literalDiscoveryNames(value2);
|
|
82462
|
+
if (literal !== undefined)
|
|
82463
|
+
return literal;
|
|
82464
|
+
if (value2?.length !== 3 || value2[0]?.kind !== "ident" || value2[1]?.value !== "." || value2[2]?.value !== "possibleStageNames")
|
|
82465
|
+
return;
|
|
82466
|
+
const owner = discoveryHelpers(unit.tokens).filter((helper) => helper.bodyOpen < call.argsOpen && helper.bodyClose > call.argsOpen).at(-1);
|
|
82467
|
+
if (owner === undefined || !owner.declaration)
|
|
82468
|
+
return;
|
|
82469
|
+
const parameter = owner.params.findIndex((param) => param[0]?.value === value2[0]?.value);
|
|
82470
|
+
if (parameter < 0)
|
|
82471
|
+
return;
|
|
82472
|
+
for (const param of owner.params) {
|
|
82473
|
+
if (param[0]?.kind !== "ident")
|
|
82474
|
+
return;
|
|
82475
|
+
const assignment = param.findIndex((token) => token.value === "=");
|
|
82476
|
+
if (assignment < 0)
|
|
82477
|
+
continue;
|
|
82478
|
+
const initial = param.slice(assignment + 1);
|
|
82479
|
+
const emptyObject = initial.length === 2 && initial[0]?.value === "{" && initial[1]?.value === "}";
|
|
82480
|
+
const scalar = initial.length === 1 && (initial[0]?.kind === "string" || ["true", "false", "null", "undefined"].includes(initial[0]?.value ?? ""));
|
|
82481
|
+
if (!emptyObject && !scalar)
|
|
82482
|
+
return;
|
|
82483
|
+
}
|
|
82484
|
+
const body = unit.tokens.slice(owner.bodyOpen, owner.bodyClose);
|
|
82485
|
+
if (body.some((token) => token.kind === "ident" && token.value === "arguments"))
|
|
82486
|
+
return;
|
|
82487
|
+
if (hasDiscoveryDestructuringWrite(body, value2[0].value))
|
|
82488
|
+
return;
|
|
82489
|
+
const forwarded = new Set;
|
|
82490
|
+
const spreadOptions = new Set;
|
|
82491
|
+
for (let index = 0;index < body.length; index += 1) {
|
|
82492
|
+
const parallel = matchCtxCall(body, index, this.aliasPool);
|
|
82493
|
+
if (parallel?.method !== "parallel")
|
|
82494
|
+
continue;
|
|
82495
|
+
const parallelOptions = splitTopLevelArguments(parallel, body)[1];
|
|
82496
|
+
const field = discoveryField(parallelOptions);
|
|
82497
|
+
if (parallelOptions?.[0]?.value === "{") {
|
|
82498
|
+
for (const entry of arrayElements(parallelOptions)) {
|
|
82499
|
+
if (entry.length === 4 && entry.slice(0, 3).every((token) => token.value === "."))
|
|
82500
|
+
spreadOptions.add(entry[3]);
|
|
82501
|
+
}
|
|
82502
|
+
}
|
|
82503
|
+
if (field?.length === 3 && field[0]?.value === value2[0].value && field[1]?.value === "." && field[2]?.value === "possibleStageNames")
|
|
82504
|
+
forwarded.add(field[0]);
|
|
82505
|
+
}
|
|
82506
|
+
for (let index = 0;index < body.length; index += 1) {
|
|
82507
|
+
if (body[index]?.value !== value2[0]?.value)
|
|
82508
|
+
continue;
|
|
82509
|
+
if (body[index + 2]?.value === "possibleStageNames" && !forwarded.has(body[index]))
|
|
82510
|
+
return;
|
|
82511
|
+
const destructured = body[index - 2]?.value === "}" && body[index - 1]?.value === "=" && body[index + 1]?.value === ";";
|
|
82512
|
+
if (destructured) {
|
|
82513
|
+
let matched = false;
|
|
82514
|
+
for (let open = 0;open < index - 2; open += 1) {
|
|
82515
|
+
if (body[open]?.value !== "{" || matchBracket(body, open, "{", "}") !== index - 2)
|
|
82516
|
+
continue;
|
|
82517
|
+
if (body[open - 1]?.value !== "const")
|
|
82518
|
+
return;
|
|
82519
|
+
matched = true;
|
|
82520
|
+
for (const entry of arrayElements(body.slice(open, index - 1))) {
|
|
82521
|
+
if (entry.length === 1 && entry[0]?.kind === "ident" && entry[0].value !== "possibleStageNames")
|
|
82522
|
+
continue;
|
|
82523
|
+
if (entry.length !== 4 || !entry.slice(0, 3).every((token) => token.value === ".") || entry[3]?.kind !== "ident")
|
|
82524
|
+
return;
|
|
82525
|
+
const rest = entry[3];
|
|
82526
|
+
for (let use = 0;use < body.length; use += 1) {
|
|
82527
|
+
const token = body[use];
|
|
82528
|
+
if (token?.kind !== "ident" || token.value !== rest.value || token === rest)
|
|
82529
|
+
continue;
|
|
82530
|
+
if (spreadOptions.has(token))
|
|
82531
|
+
continue;
|
|
82532
|
+
if (body[use - 3]?.value === "const" && body[use - 2]?.kind === "ident" && body[use - 1]?.value === "=" && body[use + 1]?.value === "." && body[use + 2]?.value === "concurrency" && body[use + 3]?.value === ";")
|
|
82533
|
+
continue;
|
|
82534
|
+
return;
|
|
82535
|
+
}
|
|
82536
|
+
}
|
|
82537
|
+
}
|
|
82538
|
+
if (!matched)
|
|
82539
|
+
return;
|
|
82540
|
+
}
|
|
82541
|
+
if (!destructured && !forwarded.has(body[index]))
|
|
82542
|
+
return;
|
|
82543
|
+
}
|
|
82544
|
+
const names = [];
|
|
82545
|
+
for (const callerPath of this.closure) {
|
|
82546
|
+
const caller = this.units.get(callerPath);
|
|
82547
|
+
if (caller === undefined)
|
|
82548
|
+
continue;
|
|
82549
|
+
if ([...caller.imports.values()].some((binding) => binding.importedName === undefined && resolveRelativeSpecifier(binding.specifier, callerPath) === path))
|
|
82550
|
+
return;
|
|
82551
|
+
const references = callerPath === path ? [owner.name] : [...caller.imports].filter(([, binding]) => binding.importedName === owner.name && resolveRelativeSpecifier(binding.specifier, callerPath) === path).map(([local]) => local);
|
|
82552
|
+
for (const reference of references) {
|
|
82553
|
+
const calls = discoveryCalls(caller.tokens, reference, callerPath === path ? owner.nameIndex : undefined);
|
|
82554
|
+
if (calls === undefined)
|
|
82555
|
+
return;
|
|
82556
|
+
for (const argsOpen of calls) {
|
|
82557
|
+
const argument = splitTopLevelArguments({ method: "parallel", argsOpen }, caller.tokens)[parameter];
|
|
82558
|
+
if (!this.hasDataOnlyDiscoveryOptions(argument))
|
|
82559
|
+
return;
|
|
82560
|
+
const declared = literalDiscoveryNames(discoveryField(argument));
|
|
82561
|
+
if (declared === undefined)
|
|
82562
|
+
return;
|
|
82563
|
+
names.push(...declared);
|
|
82564
|
+
}
|
|
82565
|
+
}
|
|
82566
|
+
}
|
|
82567
|
+
return names.length > 0 || this.closure[0] !== path ? names : undefined;
|
|
82568
|
+
}
|
|
82287
82569
|
stepNamesForStepsCall(call, unit, path) {
|
|
82570
|
+
const declared = this.discoveryNames(call, unit, path);
|
|
82571
|
+
if (declared !== undefined)
|
|
82572
|
+
return declared;
|
|
82288
82573
|
const first = firstArgumentTokens(call, unit.tokens);
|
|
82289
82574
|
if (first === undefined || first.length === 0)
|
|
82290
82575
|
return [];
|
|
@@ -90858,7 +91143,8 @@ async function warm_first_fan_out(ctx, steps, prefixKeyOf, options = {}) {
|
|
|
90858
91143
|
const warmResults = await ctx.parallel(warmSteps, {
|
|
90859
91144
|
...parallelOptions,
|
|
90860
91145
|
concurrency: boundedConcurrency(warmSteps.length, warmConcurrency ?? DEFAULT_WARM_CONCURRENCY, inheritedConcurrency),
|
|
90861
|
-
failFast: false
|
|
91146
|
+
failFast: false,
|
|
91147
|
+
possibleStageNames: options.possibleStageNames
|
|
90862
91148
|
});
|
|
90863
91149
|
for (const [resultIndex, result] of warmResults.entries()) {
|
|
90864
91150
|
const originalIndex = warmIndices[resultIndex];
|
|
@@ -90873,7 +91159,8 @@ async function warm_first_fan_out(ctx, steps, prefixKeyOf, options = {}) {
|
|
|
90873
91159
|
const restSteps = restIndices.map((index) => steps[index]);
|
|
90874
91160
|
const restResults = await ctx.parallel(restSteps, {
|
|
90875
91161
|
...parallelOptions,
|
|
90876
|
-
concurrency: boundedConcurrency(restSteps.length, undefined, inheritedConcurrency)
|
|
91162
|
+
concurrency: boundedConcurrency(restSteps.length, undefined, inheritedConcurrency),
|
|
91163
|
+
possibleStageNames: options.possibleStageNames
|
|
90877
91164
|
});
|
|
90878
91165
|
for (const [resultIndex, result] of restResults.entries()) {
|
|
90879
91166
|
const originalIndex = restIndices[resultIndex];
|
|
@@ -91082,7 +91369,7 @@ async function runAdversarialVerification(ctx) {
|
|
|
91082
91369
|
const runWave = async (pending, reaskWave) => {
|
|
91083
91370
|
if (pending.length === 0)
|
|
91084
91371
|
return { valid: [], invalid: [], results: [] };
|
|
91085
|
-
const reports = await warm_first_fan_out(ctx, pending.map((cell) => scoreStep(cell, reaskWave, scoringHead, criteriaPath)), () => scoringHead, { concurrency: Math.min(pending.length, 4), failFast: false });
|
|
91372
|
+
const reports = await warm_first_fan_out(ctx, pending.map((cell) => scoreStep(cell, reaskWave, scoringHead, criteriaPath)), () => scoringHead, { concurrency: Math.min(pending.length, 4), failFast: false, possibleStageNames: ["verifier-*-*-*", "verifier-*-*-*-reask-*"] });
|
|
91086
91373
|
const byName = new Map;
|
|
91087
91374
|
for (const report of reports) {
|
|
91088
91375
|
const name = report.name ?? report.stageName;
|
|
@@ -96470,7 +96757,7 @@ async function runTournament(ctx) {
|
|
|
96470
96757
|
if (stages.length === 0)
|
|
96471
96758
|
return { preferences: [], results: [] };
|
|
96472
96759
|
executed += stages.length;
|
|
96473
|
-
const results = await warm_first_fan_out(ctx, stages.map((stage) => stage.step), (_step, index) => `${stages[index].slot1}:${stages[index].slot2}`, { concurrency: maxConcurrency, failFast: false });
|
|
96760
|
+
const results = await warm_first_fan_out(ctx, stages.map((stage) => stage.step), (_step, index) => `${stages[index].slot1}:${stages[index].slot2}`, { concurrency: maxConcurrency, failFast: false, possibleStageNames: ["judge-*-*-*-r*"] });
|
|
96474
96761
|
const phaseResults = [...results];
|
|
96475
96762
|
for (const stage of stages) {
|
|
96476
96763
|
let report = judgeReport(resultFor(results, stage.name)?.structured);
|
|
@@ -104255,21 +104542,17 @@ function throwFinalizationError(error) {
|
|
|
104255
104542
|
function createTrackedStageCaller(input) {
|
|
104256
104543
|
const { runtime } = input;
|
|
104257
104544
|
const readinessGateEnabled = runtime.opts.confirmStageReadiness !== undefined || runtime.opts.usePromptNodesForUi === true;
|
|
104258
|
-
const confirmReadiness = async () => {
|
|
104259
|
-
|
|
104260
|
-
|
|
104261
|
-
|
|
104262
|
-
|
|
104263
|
-
|
|
104264
|
-
|
|
104265
|
-
|
|
104266
|
-
|
|
104267
|
-
|
|
104268
|
-
|
|
104269
|
-
return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, runtime.signal);
|
|
104270
|
-
} catch {
|
|
104271
|
-
return { action: "advance" };
|
|
104272
|
-
}
|
|
104545
|
+
const confirmReadiness = async (signal) => {
|
|
104546
|
+
if (runtime.opts.confirmStageReadiness !== undefined) {
|
|
104547
|
+
const ready = await raceAbort(runtime.opts.confirmStageReadiness({
|
|
104548
|
+
runId: runtime.runId,
|
|
104549
|
+
stageId: runtime.stageId,
|
|
104550
|
+
stageName: runtime.name,
|
|
104551
|
+
signal
|
|
104552
|
+
}), signal);
|
|
104553
|
+
return ready ? { action: "advance" } : { action: "stay" };
|
|
104554
|
+
}
|
|
104555
|
+
return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, signal);
|
|
104273
104556
|
};
|
|
104274
104557
|
const suppressReadinessForCurrentTurn = () => {
|
|
104275
104558
|
runtime.state.askUserQuestionObservedThisTurn = false;
|
|
@@ -104423,9 +104706,35 @@ function createTrackedStageCaller(input) {
|
|
|
104423
104706
|
});
|
|
104424
104707
|
try {
|
|
104425
104708
|
while (runtime.state.askUserQuestionObservedThisTurn || repeatReadinessAfterChatTurn) {
|
|
104426
|
-
|
|
104709
|
+
runtime.signal.throwIfAborted();
|
|
104710
|
+
if (runtime.stageSnapshot.status === "paused" || runtime.stageSnapshot.status === "blocked") {
|
|
104711
|
+
await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
|
|
104712
|
+
continue;
|
|
104713
|
+
}
|
|
104714
|
+
const controller = new AbortController;
|
|
104715
|
+
runtime.state.readinessController = controller;
|
|
104716
|
+
let decision;
|
|
104717
|
+
try {
|
|
104718
|
+
decision = await confirmReadiness(AbortSignal.any([runtime.signal, controller.signal]));
|
|
104719
|
+
if (decision.action === "advance" || decision.message !== undefined) {
|
|
104720
|
+
await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
|
|
104721
|
+
}
|
|
104722
|
+
runtime.signal.throwIfAborted();
|
|
104723
|
+
if (controller.signal.aborted) {
|
|
104724
|
+
await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
|
|
104725
|
+
continue;
|
|
104726
|
+
}
|
|
104727
|
+
} catch (error) {
|
|
104728
|
+
runtime.signal.throwIfAborted();
|
|
104729
|
+
if (controller.signal.aborted) {
|
|
104730
|
+
await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
|
|
104731
|
+
continue;
|
|
104732
|
+
}
|
|
104733
|
+
throw error;
|
|
104734
|
+
}
|
|
104427
104735
|
if (decision.action === "advance")
|
|
104428
104736
|
break;
|
|
104737
|
+
delete runtime.state.readinessController;
|
|
104429
104738
|
if (runtime.signal.aborted)
|
|
104430
104739
|
break;
|
|
104431
104740
|
runtime.state.askUserQuestionObservedThisTurn = false;
|
|
@@ -104568,9 +104877,17 @@ function createTrackedStageCaller(input) {
|
|
|
104568
104877
|
const failure = runtime.classifyExecutorFailure(durableCheckpointError.error);
|
|
104569
104878
|
applyTerminalStageState = () => applyFailureToStage(runtime.stageSnapshot, failure);
|
|
104570
104879
|
}
|
|
104571
|
-
if (!runtime.state.stageFinalized)
|
|
104572
|
-
applyTerminalStageState?.();
|
|
104573
104880
|
try {
|
|
104881
|
+
if (terminalStateIsSuccess && runtime.state.readinessController !== undefined) {
|
|
104882
|
+
let pauseVersion;
|
|
104883
|
+
do {
|
|
104884
|
+
pauseVersion = runtime.state.readinessPauseVersion;
|
|
104885
|
+
await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
|
|
104886
|
+
} while (pauseVersion !== runtime.state.readinessPauseVersion);
|
|
104887
|
+
runtime.signal.throwIfAborted();
|
|
104888
|
+
}
|
|
104889
|
+
if (!runtime.state.stageFinalized)
|
|
104890
|
+
applyTerminalStageState?.();
|
|
104574
104891
|
await runtime.finalizeStageSnapshot();
|
|
104575
104892
|
} catch (err) {
|
|
104576
104893
|
finalizationError ??= { thrown: true, error: err };
|
|
@@ -104588,6 +104905,9 @@ function createTrackedStageCaller(input) {
|
|
|
104588
104905
|
input.limiter.release();
|
|
104589
104906
|
if (finalizationError !== undefined)
|
|
104590
104907
|
throwFinalizationError(finalizationError.error);
|
|
104908
|
+
delete runtime.state.readinessController;
|
|
104909
|
+
if (terminalStateIsSuccess && readinessGateEnabled)
|
|
104910
|
+
runtime.signal.throwIfAborted();
|
|
104591
104911
|
}
|
|
104592
104912
|
};
|
|
104593
104913
|
}
|
|
@@ -104908,12 +105228,26 @@ function createStageControlHandle(runtime) {
|
|
|
104908
105228
|
async pause() {
|
|
104909
105229
|
runtime.throwIfStageMutationBlocked();
|
|
104910
105230
|
const statusBeforePause = runtime.stageSnapshot.status;
|
|
105231
|
+
let readinessPauseVersion;
|
|
105232
|
+
if (runtime.state.readinessController !== undefined) {
|
|
105233
|
+
runtime.scheduler.ensureReleaseBarrier(runtime.stageId);
|
|
105234
|
+
readinessPauseVersion = (runtime.state.readinessPauseVersion ?? 0) + 1;
|
|
105235
|
+
runtime.state.readinessPauseVersion = readinessPauseVersion;
|
|
105236
|
+
}
|
|
104911
105237
|
if (statusBeforePause === "pending" || statusBeforePause === "running" || runtime.innerCtx.isStreaming) {
|
|
104912
|
-
|
|
105238
|
+
try {
|
|
105239
|
+
await runtime.innerCtx.__requestPause();
|
|
105240
|
+
} catch (error) {
|
|
105241
|
+
if (readinessPauseVersion !== undefined && runtime.state.readinessPauseVersion === readinessPauseVersion && runtime.stageSnapshot.status !== "paused" && runtime.stageSnapshot.status !== "blocked" && !runtime.scheduler.hasCascadePauseOwners(runtime.stageId)) {
|
|
105242
|
+
runtime.scheduler.releaseStageBarrier(runtime.stageId);
|
|
105243
|
+
}
|
|
105244
|
+
throw error;
|
|
105245
|
+
}
|
|
104913
105246
|
}
|
|
104914
105247
|
const changed = runtime.activeStore.recordStagePaused(runtime.runId, runtime.stageId);
|
|
104915
105248
|
if (changed) {
|
|
104916
105249
|
runtime.scheduler.ensureReleaseBarrier(runtime.stageId);
|
|
105250
|
+
runtime.state.readinessController?.abort(new Error("atomic-workflows: readiness paused"));
|
|
104917
105251
|
await runtime.scheduler.cascadePauseFrom(runtime.stageId);
|
|
104918
105252
|
const run = runtime.activeStore.runs().find((candidate) => candidate.id === runtime.runId);
|
|
104919
105253
|
const stillActive = run?.stages.some((stage) => stage.status === "running" && stage.id !== runtime.stageId) ?? false;
|
|
@@ -117179,7 +117513,7 @@ var DEFAULT_PROMPT_GUIDANCE = [
|
|
|
117179
117513
|
- After creating and reloading a newly authored custom workflow, close the loop by stating the folder containing the workflow file just written, for example \`.atomic/workflows/\`, in this shape: \`Custom workflow created. You can inspect its code at: <workflow-folder-path>\`. Do this only for newly created custom workflows, never builtin or pre-existing workflows.
|
|
117180
117514
|
- Keep a small, readable workflow in one entry file and write it for human maintainers. Keep the graph and control flow visible in the top-level workflow entry file, use stage names that state each stage's responsibility, and make its inputs, outputs, evidence, and success contract explicit. A developer reading the entry file from top to bottom should be able to identify the graph, branches, gates, artifacts, and stop conditions. Avoid both monolithic prompt blobs and gratuitous fragmentation. Do not split short one-use prompts, create one file per stage, add wrapper-only modules, hide the graph across files, or use line counts alone as a module boundary.
|
|
117181
117515
|
- When a meaningful source boundary improves clarity, reuse, ownership, or testability, keep the graph and control flow in the top-level workflow entry file and extract cohesive concerns such as long or reused prompt builders, shared TypeBox schemas and workflow-specific types, model-policy constants shared by several stages, deterministic helpers with their own testable behavior, or reusable child workflow definitions into a subdirectory below the top-level discovery directory — either one owned by a single workflow or a shared support directory. Project and user discovery scans only top-level \`.ts\`/\`.js\`/\`.mjs\`/\`.cjs\` files in the workflow directory, so those support modules are not scanned as extra top-level workflow candidates; use \`.js\` import extensions from TypeScript source.
|
|
117182
|
-
- Evaluate Atomic extension hooks when a workflow needs fine-grained, cross-cutting tool or session event control. Workflow TypeScript owns the inspectable DAG, stages, handoffs, durable \`ctx.tool\` side effects, and gates; extension hooks own cross-cutting session and model-tool policy such as \`tool_call\` interception, input mutation, or blocking, \`tool_result\` transformation, context and provider hooks, lifecycle observation, or reusable custom tools. Use hooks only when cross-stage or cross-workflow event control is materially clearer than embedding the policy in each stage; do not prescribe a companion extension for ordinary workflow logic. Consult \`packages/coding-agent/docs/extensions.md#events\` for the authoritative hook contracts.
|
|
117516
|
+
- Evaluate Atomic extension hooks when a workflow needs fine-grained, cross-cutting tool or session event control. Workflow TypeScript owns the inspectable DAG, stages, handoffs, durable \`ctx.tool\` side effects, and gates; extension hooks own cross-cutting session and model-tool policy such as \`tool_call\` interception, input mutation, or blocking, \`tool_result\` transformation, context and provider hooks, lifecycle observation, or reusable custom tools. Use hooks only when cross-stage or cross-workflow event control is materially clearer than embedding the policy in each stage; do not prescribe a companion extension for ordinary workflow logic. Consult \`packages/coding-agent/docs/extensions/events.md#events\` for the authoritative hook contracts.
|
|
117183
117517
|
- When a workflow depends on a companion extension, make the dependency explicit, package and document it with the workflow, include any extension-provided custom tools in stage \`tools\` allowlists, and document hook-driven behavior so the workflow remains inspectable.
|
|
117184
117518
|
- When creating or editing a workflow that pins an explicit stage \`model\` or \`fallbackModels\`, consult \`packages/coding-agent/docs/models/model-selection.md\` for role-based recommendations and \`packages/coding-agent/docs/models/evals.md\` for the measured per-evaluation scores behind them (its task-type picker maps each stage type to the eval that measures it), treating benchmark thinking levels as measurement configurations rather than universal workflow defaults, then call \`workflow({ action: "models" })\` to see the models actually present in the user's configured catalog. Use only the catalog's returned \`fullId\` values as model strings, and append a thinking suffix only when that exact level appears in the entry's \`availableThinkingLevels\`; apply the stage role and failure-cost policy independently to the primary and every fallback; treat an absent or empty \`availableThinkingLevels\` as no suffix support rather than inferring one. If a guide-recommended model for the role is unavailable, try another guide-recommended model that is present in the catalog. If the selected model does not support the role's level, choose another catalog model that does or leave the stage unpinned rather than inventing or silently promoting a level. An explicit user request for a level overrides the role default, but never fabricate an unsupported catalog level. If no recommendation intersects with the catalog, leave the stage unpinned rather than inventing a substitute, and mention the limitation, asking the user only if the workflow requires an explicit model choice. If the catalog is empty, continue with unpinned stages, state that no configured models were returned, and do not fabricate model IDs. Do not inspect or infer credentials, environment variables, auth files, token validity, entitlements, or the reason a model is absent; \`isCurrent\` marks the active selection, not a quality recommendation.
|
|
117185
117519
|
- Consult docs/workflows/reliable-design.md and its starter patterns (Classify-and-act, Fan-out-and-synthesize, Adversarial verification, Generate-and-filter, Tournament, Loop until done, and Stacked implementation slices) when designing a stage graph.
|