@bastani/atomic 0.9.18-alpha.2 → 0.9.18-alpha.4
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/dist/builtin/intercom/CHANGELOG.md +8 -0
- package/dist/builtin/intercom/README.md +3 -3
- package/dist/builtin/intercom/broker/broker.ts +156 -12
- package/dist/builtin/intercom/broker/client.ts +89 -49
- package/dist/builtin/intercom/broker/pending-question-index.ts +10 -0
- package/dist/builtin/intercom/broker/send-handler.ts +32 -17
- package/dist/builtin/intercom/index.bundle.mjs +153 -50
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/skills/intercom/SKILL.md +1 -1
- package/dist/builtin/intercom/types.ts +30 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +18 -0
- package/dist/builtin/workflows/README.md +11 -2
- package/dist/builtin/workflows/builtin/{chunk-ngffz3y8.js → chunk-fghhy2a5.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-6v0yv8tj.js → chunk-h3r2vkzc.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-brerg33r.js → chunk-n58a7v26.js} +0 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +258 -49
- package/dist/builtin/workflows/src/index.js +35 -9
- package/docs/intercom.md +7 -5
- package/docs/models/artificial-analysis-index.md +2 -1
- package/docs/models/model-selection.md +19 -18
- package/docs/models/pareto-efficiency.md +36 -29
- package/docs/workflows.md +18 -9
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
|
@@ -36322,7 +36322,6 @@ function compactStage(stage) {
|
|
|
36322
36322
|
inputRequest,
|
|
36323
36323
|
notices,
|
|
36324
36324
|
mcpScope: _mcpScope,
|
|
36325
|
-
pendingStageDeliveryAvailable: _pendingStageDeliveryAvailable,
|
|
36326
36325
|
attemptedModels: _attemptedModels,
|
|
36327
36326
|
modelAttempts: _modelAttempts,
|
|
36328
36327
|
result: _result,
|
|
@@ -38144,6 +38143,31 @@ function effectiveWidth(width) {
|
|
|
38144
38143
|
return chatWidth(width);
|
|
38145
38144
|
}
|
|
38146
38145
|
|
|
38146
|
+
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
38147
|
+
function pendingStageTarget(runId, stage) {
|
|
38148
|
+
return "workflowGraphTarget" in stage ? stage.workflowGraphTarget : { runId, stageId: stage.id };
|
|
38149
|
+
}
|
|
38150
|
+
function pendingWorkflowStageStatus(run, stage, resolveOwningRunStatus) {
|
|
38151
|
+
if (stage.status !== "pending")
|
|
38152
|
+
return;
|
|
38153
|
+
const identity = pendingStageTarget(run.id, stage);
|
|
38154
|
+
const owningRunStatus = identity.runId === run.id ? run.status : resolveOwningRunStatus?.(identity.runId);
|
|
38155
|
+
const pendingStageDeliveryAvailable = owningRunStatus !== undefined && owningRunStatus !== "crashed" && !isTerminalRunStatus(owningRunStatus) && stage.pendingStageDeliveryAvailable === true;
|
|
38156
|
+
return {
|
|
38157
|
+
stageId: identity.stageId,
|
|
38158
|
+
name: stage.name,
|
|
38159
|
+
lifecycle: "pending",
|
|
38160
|
+
pendingStageDeliveryAvailable,
|
|
38161
|
+
...pendingStageDeliveryAvailable ? { target: `${identity.runId}:${identity.stageId}` } : {}
|
|
38162
|
+
};
|
|
38163
|
+
}
|
|
38164
|
+
function pendingWorkflowStageStatuses(run, resolveOwningRunStatus) {
|
|
38165
|
+
return run.stages.flatMap((stage) => {
|
|
38166
|
+
const pending = pendingWorkflowStageStatus(run, stage, resolveOwningRunStatus);
|
|
38167
|
+
return pending === undefined ? [] : [pending];
|
|
38168
|
+
});
|
|
38169
|
+
}
|
|
38170
|
+
|
|
38147
38171
|
// dist/builtin/workflows/src/tui/status-helpers.ts
|
|
38148
38172
|
function statusColor(status, theme) {
|
|
38149
38173
|
switch (status) {
|
|
@@ -38222,10 +38246,10 @@ function renderRunDetail(detail, opts = {}) {
|
|
|
38222
38246
|
const now = opts.now ?? Date.now();
|
|
38223
38247
|
const width = Math.max(32, opts.width ?? 80);
|
|
38224
38248
|
if (opts.theme === undefined)
|
|
38225
|
-
return renderPlain(detail, now, width);
|
|
38226
|
-
return renderThemed(detail, now, opts.theme, width);
|
|
38249
|
+
return renderPlain(detail, now, width, opts.owningRunStatus);
|
|
38250
|
+
return renderThemed(detail, now, opts.theme, width, opts.owningRunStatus);
|
|
38227
38251
|
}
|
|
38228
|
-
function renderPlain(detail, now, width) {
|
|
38252
|
+
function renderPlain(detail, now, width, resolveOwningRunStatus) {
|
|
38229
38253
|
const out = [];
|
|
38230
38254
|
const stateBadge = stateLabel(detail);
|
|
38231
38255
|
out.push(...renderIdentifierRows2(detail.runId, width - 2));
|
|
@@ -38244,7 +38268,7 @@ function renderPlain(detail, now, width) {
|
|
|
38244
38268
|
out.push(" (no stages recorded yet) ");
|
|
38245
38269
|
else
|
|
38246
38270
|
for (const stage of detail.stages)
|
|
38247
|
-
out.push(...renderStageRowsPlain(stage, now, width - 4));
|
|
38271
|
+
out.push(...renderStageRowsPlain(detail.runId, detail.status, stage, now, width - 4, resolveOwningRunStatus));
|
|
38248
38272
|
out.push("");
|
|
38249
38273
|
}
|
|
38250
38274
|
if (tools.length > 0) {
|
|
@@ -38268,7 +38292,7 @@ function renderPlain(detail, now, width) {
|
|
|
38268
38292
|
width
|
|
38269
38293
|
});
|
|
38270
38294
|
}
|
|
38271
|
-
function renderThemed(detail, now, theme, width) {
|
|
38295
|
+
function renderThemed(detail, now, theme, width, resolveOwningRunStatus) {
|
|
38272
38296
|
const out = [];
|
|
38273
38297
|
const muted = hexToAnsi(theme.textMuted);
|
|
38274
38298
|
const dim = hexToAnsi(theme.dim);
|
|
@@ -38290,7 +38314,7 @@ function renderThemed(detail, now, theme, width) {
|
|
|
38290
38314
|
out.push(` ${dim}(no stages recorded yet)${RESET} `);
|
|
38291
38315
|
else
|
|
38292
38316
|
for (const stage of detail.stages)
|
|
38293
|
-
out.push(...renderStageRowsThemed(stage, now, theme, width - 4));
|
|
38317
|
+
out.push(...renderStageRowsThemed(detail.runId, detail.status, stage, now, theme, width - 4, resolveOwningRunStatus));
|
|
38294
38318
|
out.push("");
|
|
38295
38319
|
}
|
|
38296
38320
|
if (tools.length > 0) {
|
|
@@ -38383,16 +38407,37 @@ function stageLineThemed(stage, now, theme, width) {
|
|
|
38383
38407
|
const durSeg = dur ? `${dim}${dur}${RESET}` : "";
|
|
38384
38408
|
return truncateToWidth(`${iconFg}${icon}${RESET} ${text}${namePad}${RESET} ${stateFg}${statePad}${RESET}${activitySeg}${durSeg}`, width, "…");
|
|
38385
38409
|
}
|
|
38386
|
-
function
|
|
38387
|
-
const
|
|
38410
|
+
function pendingStageRows(runId, runStatus, stage, width, theme, resolveOwningRunStatus) {
|
|
38411
|
+
const pending = pendingWorkflowStageStatus({ id: runId, status: runStatus }, stage, resolveOwningRunStatus);
|
|
38412
|
+
if (pending === undefined)
|
|
38413
|
+
return [];
|
|
38414
|
+
const value2 = pending.target ?? `${pending.stageId} · delivery unavailable`;
|
|
38415
|
+
const label = pending.target === undefined ? "pending id" : "pending target";
|
|
38416
|
+
const firstPrefix = ` ${pad(label, 16)}`;
|
|
38417
|
+
const continuationPrefix = " ".repeat(19);
|
|
38418
|
+
const wrapped = wrapIdentifierLines(value2, Math.max(1, width - 1), firstPrefix, continuationPrefix);
|
|
38419
|
+
if (theme === undefined)
|
|
38420
|
+
return wrapped.map(({ prefix, chunk }) => `${prefix}${chunk} `);
|
|
38421
|
+
const muted = hexToAnsi(theme.textMuted);
|
|
38422
|
+
const text = hexToAnsi(theme.text);
|
|
38423
|
+
return wrapped.map(({ prefix, chunk }, index) => index === 0 ? ` ${muted}${pad(label, 16)}${RESET}${text}${chunk}${RESET} ` : `${prefix}${text}${chunk}${RESET} `);
|
|
38424
|
+
}
|
|
38425
|
+
function renderStageRowsPlain(runId, runStatus, stage, now, width, resolveOwningRunStatus) {
|
|
38426
|
+
const rows = [
|
|
38427
|
+
` ${stageLinePlain(stage, now, Math.max(1, width - 2))} `,
|
|
38428
|
+
...pendingStageRows(runId, runStatus, stage, width, undefined, resolveOwningRunStatus)
|
|
38429
|
+
];
|
|
38388
38430
|
if (stage.error) {
|
|
38389
38431
|
rows.push(` error ${truncateToWidth(stage.error.split(`
|
|
38390
38432
|
`)[0] ?? "", Math.max(1, width - 10), "…")} `);
|
|
38391
38433
|
}
|
|
38392
38434
|
return rows;
|
|
38393
38435
|
}
|
|
38394
|
-
function renderStageRowsThemed(stage, now, theme, width) {
|
|
38395
|
-
const rows = [
|
|
38436
|
+
function renderStageRowsThemed(runId, runStatus, stage, now, theme, width, resolveOwningRunStatus) {
|
|
38437
|
+
const rows = [
|
|
38438
|
+
` ${stageLineThemed(stage, now, theme, Math.max(1, width - 2))} `,
|
|
38439
|
+
...pendingStageRows(runId, runStatus, stage, width, theme, resolveOwningRunStatus)
|
|
38440
|
+
];
|
|
38396
38441
|
if (stage.error) {
|
|
38397
38442
|
const errFg = hexToAnsi(theme.error);
|
|
38398
38443
|
rows.push(` ${hexToAnsi(theme.textMuted)}error${RESET} ${errFg}${truncateToWidth(stage.error.split(`
|
|
@@ -38708,7 +38753,7 @@ function renderStatusList(runs, opts = {}) {
|
|
|
38708
38753
|
for (let i = 0;i < sorted.length; i++) {
|
|
38709
38754
|
if (i > 0)
|
|
38710
38755
|
body.push("");
|
|
38711
|
-
body.push(...renderRunEntry(sorted[i], now, cardWidth, opts.theme, opts.allRuns ?? runs, opts.indicatorStatuses));
|
|
38756
|
+
body.push(...renderRunEntry(sorted[i], now, cardWidth, opts.theme, opts.allRuns ?? runs, opts.indicatorStatuses, opts.owningRunStatus));
|
|
38712
38757
|
}
|
|
38713
38758
|
}
|
|
38714
38759
|
if (opts.showDetailHint !== false && sorted.length > 0) {
|
|
@@ -38723,7 +38768,7 @@ function renderStatusList(runs, opts = {}) {
|
|
|
38723
38768
|
width
|
|
38724
38769
|
});
|
|
38725
38770
|
}
|
|
38726
|
-
function renderRunEntry(run, now, width, theme, allRuns, indicatorStatuses) {
|
|
38771
|
+
function renderRunEntry(run, now, width, theme, allRuns, indicatorStatuses, resolveOwningRunStatus) {
|
|
38727
38772
|
const bodyWidth = effectiveWidth2(width);
|
|
38728
38773
|
const interior = Math.max(8, bodyWidth - 4);
|
|
38729
38774
|
const indicatorStatus = indicatorStatuses?.[run.id] ?? runIndicatorStatus(run, allRuns);
|
|
@@ -38762,7 +38807,56 @@ function renderRunEntry(run, now, width, theme, allRuns, indicatorStatuses) {
|
|
|
38762
38807
|
const modeSeg = theme ? `${muted}${mode}${reset}` : mode;
|
|
38763
38808
|
const metaSeg = theme ? `${dim}${meta}${reset}` : meta;
|
|
38764
38809
|
const metaLine = ` ${modeSeg} ${strip}${" ".repeat(gap)}${metaSeg} `;
|
|
38765
|
-
return [...identityRows, identity, metaLine];
|
|
38810
|
+
return [...identityRows, identity, metaLine, ...pendingStageLines(run, interior, theme, resolveOwningRunStatus)];
|
|
38811
|
+
}
|
|
38812
|
+
var MAX_PENDING_STAGE_ROWS = 3;
|
|
38813
|
+
function pendingStageIdentityLines(stage, width, suffix = "") {
|
|
38814
|
+
const full = ` pending: ${stage.name} (${stage.stageId})${suffix}`;
|
|
38815
|
+
if (visibleWidth(full) <= width)
|
|
38816
|
+
return [full];
|
|
38817
|
+
const labelledPrefix = " pending: ";
|
|
38818
|
+
const prefix = visibleWidth(labelledPrefix) < width ? labelledPrefix : width > 3 ? " " : "";
|
|
38819
|
+
const continuation = width > 3 ? " " : "";
|
|
38820
|
+
const rows = wrapIdentifierLines(stage.stageId, width, prefix, continuation).map(({ prefix: rowPrefix, chunk }) => `${rowPrefix}${chunk}`);
|
|
38821
|
+
if (suffix.length === 0)
|
|
38822
|
+
return rows;
|
|
38823
|
+
const last = rows.at(-1);
|
|
38824
|
+
if (visibleWidth(`${last}${suffix}`) <= width)
|
|
38825
|
+
rows[rows.length - 1] = `${last}${suffix}`;
|
|
38826
|
+
else
|
|
38827
|
+
rows.push(`${continuation}${suffix.trim()}`);
|
|
38828
|
+
return rows;
|
|
38829
|
+
}
|
|
38830
|
+
function pendingStageLines(run, width, theme, resolveOwningRunStatus) {
|
|
38831
|
+
const stages = pendingWorkflowStageStatuses(run, resolveOwningRunStatus);
|
|
38832
|
+
const visible = stages.slice(0, MAX_PENDING_STAGE_ROWS).flatMap((stage) => {
|
|
38833
|
+
const prefix = ` pending: ${stage.name} (${stage.stageId})`;
|
|
38834
|
+
if (stage.target === undefined) {
|
|
38835
|
+
const unavailable = `${prefix} · delivery unavailable`;
|
|
38836
|
+
if (visibleWidth(unavailable) <= width)
|
|
38837
|
+
return [pendingStageLine(unavailable, width, theme)];
|
|
38838
|
+
return [
|
|
38839
|
+
...pendingStageIdentityLines(stage, width).map((line) => pendingStageLine(line, width, theme)),
|
|
38840
|
+
pendingStageLine(" delivery unavailable", width, theme)
|
|
38841
|
+
];
|
|
38842
|
+
}
|
|
38843
|
+
const inline = `${prefix} → ${stage.target}`;
|
|
38844
|
+
if (visibleWidth(inline) <= width)
|
|
38845
|
+
return [pendingStageLine(inline, width, theme)];
|
|
38846
|
+
const labelRows = pendingStageIdentityLines(stage, width, " →").map((line) => pendingStageLine(line, width, theme));
|
|
38847
|
+
const targetRows = wrapIdentifierLines(stage.target, width, " ", " ").map(({ prefix: prefix2, chunk }) => pendingStageLine(`${prefix2}${chunk}`, width, theme));
|
|
38848
|
+
return [...labelRows, ...targetRows];
|
|
38849
|
+
});
|
|
38850
|
+
if (stages.length > MAX_PENDING_STAGE_ROWS) {
|
|
38851
|
+
const omitted = stages.length - MAX_PENDING_STAGE_ROWS;
|
|
38852
|
+
const line = truncateToWidth(` … ${omitted} more pending stage${omitted === 1 ? "" : "s"}`, width, ELLIPSIS);
|
|
38853
|
+
visible.push(theme === undefined ? line : `${hexToAnsi(theme.dim)}${line}${RESET}`);
|
|
38854
|
+
}
|
|
38855
|
+
return visible;
|
|
38856
|
+
}
|
|
38857
|
+
function pendingStageLine(line, width, theme) {
|
|
38858
|
+
const visible = truncateToWidth(line, width, ELLIPSIS);
|
|
38859
|
+
return theme === undefined ? visible : `${hexToAnsi(theme.textMuted)}${visible}${RESET}`;
|
|
38766
38860
|
}
|
|
38767
38861
|
function runAccent(run, theme, indicatorStatus) {
|
|
38768
38862
|
if (!theme)
|
|
@@ -39188,7 +39282,12 @@ function renderChatSurfacePlainText(payload, options = {}) {
|
|
|
39188
39282
|
`);
|
|
39189
39283
|
}
|
|
39190
39284
|
case "detail": {
|
|
39191
|
-
const rendered = renderRunDetail(payload.detail, {
|
|
39285
|
+
const rendered = renderRunDetail(payload.detail, {
|
|
39286
|
+
width,
|
|
39287
|
+
now,
|
|
39288
|
+
...themed,
|
|
39289
|
+
owningRunStatus: (runId) => payload.owningRunStatuses?.[runId]
|
|
39290
|
+
});
|
|
39192
39291
|
const lines = [
|
|
39193
39292
|
rendered,
|
|
39194
39293
|
`run id: ${payload.detail.runId}`,
|
|
@@ -39269,7 +39368,12 @@ function renderPayload(payload, theme, width, now) {
|
|
|
39269
39368
|
case "list":
|
|
39270
39369
|
return renderWorkflowList(payload.entries, { theme, width });
|
|
39271
39370
|
case "detail":
|
|
39272
|
-
return renderRunDetail(payload.detail, {
|
|
39371
|
+
return renderRunDetail(payload.detail, {
|
|
39372
|
+
theme,
|
|
39373
|
+
width,
|
|
39374
|
+
now,
|
|
39375
|
+
owningRunStatus: (runId) => payload.owningRunStatuses?.[runId]
|
|
39376
|
+
});
|
|
39273
39377
|
}
|
|
39274
39378
|
}
|
|
39275
39379
|
|
|
@@ -48234,7 +48338,30 @@ function activeToolLabel(run) {
|
|
|
48234
48338
|
const details = nodes.map((node) => `${node.name} · ${node.status}`).join(", ");
|
|
48235
48339
|
return nodes.length === 1 ? details : `${nodes.length} tools · ${details}`;
|
|
48236
48340
|
}
|
|
48237
|
-
|
|
48341
|
+
var MAX_PENDING_WIDGET_ITEMS = 2;
|
|
48342
|
+
function pendingStageLabel(run, width = Number.POSITIVE_INFINITY) {
|
|
48343
|
+
const stages = pendingWorkflowStageStatuses(run);
|
|
48344
|
+
if (stages.length === 0)
|
|
48345
|
+
return;
|
|
48346
|
+
const maxItems = Math.min(MAX_PENDING_WIDGET_ITEMS, stages.length);
|
|
48347
|
+
for (let count = maxItems;count >= 1; count--) {
|
|
48348
|
+
let combinations = [[]];
|
|
48349
|
+
for (const stage of stages.slice(0, count)) {
|
|
48350
|
+
const exact = stage.target === undefined ? `${stage.name} (${stage.stageId}) · unavailable` : `${stage.name} (${stage.stageId}) → ${stage.target}`;
|
|
48351
|
+
const variants = stage.target === undefined ? [exact] : [exact, `${stage.name} · stage ${stage.stageId}`];
|
|
48352
|
+
combinations = combinations.flatMap((labels) => variants.map((variant) => [...labels, variant]));
|
|
48353
|
+
}
|
|
48354
|
+
for (const labels of combinations) {
|
|
48355
|
+
const omitted = stages.length - count;
|
|
48356
|
+
const visible = omitted > 0 ? [...labels, `… ${omitted} more`] : labels;
|
|
48357
|
+
const label = `pending: ${visible.join(", ")}`;
|
|
48358
|
+
if (visibleWidth(label) <= width)
|
|
48359
|
+
return label;
|
|
48360
|
+
}
|
|
48361
|
+
}
|
|
48362
|
+
return;
|
|
48363
|
+
}
|
|
48364
|
+
function metaLine(run, now, width = Number.POSITIVE_INFINITY) {
|
|
48238
48365
|
if (run.endedAt !== undefined) {
|
|
48239
48366
|
return elapsedLabel(run, now);
|
|
48240
48367
|
}
|
|
@@ -48242,17 +48369,21 @@ function metaLine(run, now) {
|
|
|
48242
48369
|
return "quit · resumable via /workflow resume";
|
|
48243
48370
|
if (effectiveRunStatus(run) === "blocked")
|
|
48244
48371
|
return "blocked · resumable via /workflow resume";
|
|
48245
|
-
const
|
|
48372
|
+
const prefix = [modeLabel(run)];
|
|
48246
48373
|
const prog = progressLabel(run);
|
|
48247
48374
|
if (prog)
|
|
48248
|
-
|
|
48375
|
+
prefix.push(prog);
|
|
48376
|
+
const suffix = [];
|
|
48249
48377
|
const tools = activeToolLabel(run);
|
|
48250
48378
|
if (tools)
|
|
48251
|
-
|
|
48379
|
+
suffix.push(tools);
|
|
48252
48380
|
const elapsed = elapsedLabel(run, now);
|
|
48253
48381
|
if (elapsed)
|
|
48254
|
-
|
|
48255
|
-
|
|
48382
|
+
suffix.push(elapsed);
|
|
48383
|
+
const otherParts = [...prefix, ...suffix];
|
|
48384
|
+
const pendingWidth = Math.max(0, width - otherParts.reduce((total, part) => total + visibleWidth(part), 0) - otherParts.length * 3);
|
|
48385
|
+
const pending = pendingStageLabel(run, pendingWidth);
|
|
48386
|
+
return [...prefix, ...pending === undefined ? [] : [pending], ...suffix].join(" · ");
|
|
48256
48387
|
}
|
|
48257
48388
|
function countBadges(counts, theme) {
|
|
48258
48389
|
const badges = [];
|
|
@@ -48290,8 +48421,12 @@ function formatTitleBadges(badges, theme, themed) {
|
|
|
48290
48421
|
const fallbackFg = hexToAnsi(theme.border);
|
|
48291
48422
|
return badges.map((b) => `${b.fg ? hexToAnsi(b.fg) : fallbackFg}${b.text}${RESET}${fallbackFg}`).join(" ");
|
|
48292
48423
|
}
|
|
48293
|
-
function
|
|
48294
|
-
const
|
|
48424
|
+
function runMetaWidth(run, width) {
|
|
48425
|
+
const inner = Math.max(2, Math.max(32, width) - 2);
|
|
48426
|
+
return Math.max(0, inner - visibleWidth(` ${run.name} · `));
|
|
48427
|
+
}
|
|
48428
|
+
function themedRunLines(run, now, theme, allRuns, width) {
|
|
48429
|
+
const meta = metaLine(run, now, runMetaWidth(run, width));
|
|
48295
48430
|
const metaColor = effectiveRunStatus(run) === "running" ? theme.textMuted : theme.dim;
|
|
48296
48431
|
return renderRunIdentityRows({
|
|
48297
48432
|
runId: run.id,
|
|
@@ -48303,11 +48438,11 @@ function themedRunLines(run, now, theme, allRuns) {
|
|
|
48303
48438
|
theme
|
|
48304
48439
|
});
|
|
48305
48440
|
}
|
|
48306
|
-
function plainRunLines(run, now, allRuns) {
|
|
48441
|
+
function plainRunLines(run, now, allRuns, width) {
|
|
48307
48442
|
return renderRunIdentityRows({
|
|
48308
48443
|
runId: run.id,
|
|
48309
48444
|
name: run.name,
|
|
48310
|
-
meta: metaLine(run, now),
|
|
48445
|
+
meta: metaLine(run, now, runMetaWidth(run, width)),
|
|
48311
48446
|
glyph: statusGlyph2(run, allRuns)
|
|
48312
48447
|
});
|
|
48313
48448
|
}
|
|
@@ -48362,7 +48497,7 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now()) {
|
|
|
48362
48497
|
const body = [];
|
|
48363
48498
|
for (let i = 0;i < display.length; i++) {
|
|
48364
48499
|
const run = display[i];
|
|
48365
|
-
const runLines = themed ? themedRunLines(run, now, graphTheme, snap.runs) : plainRunLines(run, now, snap.runs);
|
|
48500
|
+
const runLines = themed ? themedRunLines(run, now, graphTheme, snap.runs, width) : plainRunLines(run, now, snap.runs, width);
|
|
48366
48501
|
body.push(...runLines);
|
|
48367
48502
|
if (i < display.length - 1)
|
|
48368
48503
|
body.push("");
|
|
@@ -49341,6 +49476,7 @@ function encodeCheckpoint(checkpoint) {
|
|
|
49341
49476
|
version: s.topology.version,
|
|
49342
49477
|
stageId: s.topology.stageId,
|
|
49343
49478
|
parentIds: [...s.topology.parentIds],
|
|
49479
|
+
...s.topology.intercomGroup !== undefined ? { intercomGroup: s.topology.intercomGroup } : {},
|
|
49344
49480
|
...s.topology.sourceOrder !== undefined ? { sourceOrder: s.topology.sourceOrder } : {},
|
|
49345
49481
|
...s.topology.occurrenceKey !== undefined ? { occurrenceKey: s.topology.occurrenceKey } : {},
|
|
49346
49482
|
...s.topology.status !== undefined ? { status: s.topology.status } : {},
|
|
@@ -49473,7 +49609,7 @@ function stageTopology(value2) {
|
|
|
49473
49609
|
if (typeof value2 !== "object" || value2 === null || Array.isArray(value2))
|
|
49474
49610
|
return;
|
|
49475
49611
|
const record = value2;
|
|
49476
|
-
if (record.version !== DURABLE_STAGE_TOPOLOGY_VERSION || typeof record.stageId !== "string" || !isStringArray(record.parentIds) || !isOptionalSourceOrder(record.sourceOrder) || record.occurrenceKey !== undefined && typeof record.occurrenceKey !== "string" || record.status !== undefined && !isStageLifecycleStatus(record.status))
|
|
49612
|
+
if (record.version !== DURABLE_STAGE_TOPOLOGY_VERSION || typeof record.stageId !== "string" || !isStringArray(record.parentIds) || !isOptionalSourceOrder(record.sourceOrder) || record.intercomGroup !== undefined && typeof record.intercomGroup !== "string" || record.occurrenceKey !== undefined && typeof record.occurrenceKey !== "string" || record.status !== undefined && !isStageLifecycleStatus(record.status))
|
|
49477
49613
|
return;
|
|
49478
49614
|
const run = stageRunTopology(record.run);
|
|
49479
49615
|
if (record.run !== undefined && run === undefined)
|
|
@@ -49485,6 +49621,7 @@ function stageTopology(value2) {
|
|
|
49485
49621
|
version: DURABLE_STAGE_TOPOLOGY_VERSION,
|
|
49486
49622
|
stageId: record.stageId,
|
|
49487
49623
|
parentIds: record.parentIds,
|
|
49624
|
+
...typeof record.intercomGroup === "string" ? { intercomGroup: record.intercomGroup } : {},
|
|
49488
49625
|
...typeof record.sourceOrder === "number" ? { sourceOrder: record.sourceOrder } : {},
|
|
49489
49626
|
...typeof record.occurrenceKey === "string" ? { occurrenceKey: record.occurrenceKey } : {},
|
|
49490
49627
|
...isStageLifecycleStatus(record.status) ? { status: record.status } : {},
|
|
@@ -54052,6 +54189,7 @@ function durableStageCheckpointMetadata(stage, run, sourceOrder) {
|
|
|
54052
54189
|
version: DURABLE_STAGE_TOPOLOGY_VERSION,
|
|
54053
54190
|
stageId: stage.id,
|
|
54054
54191
|
parentIds: [...stage.parentIds],
|
|
54192
|
+
...stage.intercomGroup !== undefined ? { intercomGroup: stage.intercomGroup } : {},
|
|
54055
54193
|
...stage.executionOrder !== undefined ? { order: stage.executionOrder } : {},
|
|
54056
54194
|
...sourceOrder !== undefined && sourceOrder >= 0 ? { sourceOrder } : {},
|
|
54057
54195
|
...stage.promptFootprint !== undefined ? { occurrenceKey: stage.id } : {},
|
|
@@ -54784,11 +54922,13 @@ function createDurableStagePrimitive(input) {
|
|
|
54784
54922
|
const isMidSessionResume = session?.sessionFile !== undefined;
|
|
54785
54923
|
const topology = activeStageTopology(input.backend, input.workflowId, replayKey);
|
|
54786
54924
|
const durableStageId = topology?.stageId ?? pendingStageIdForReplay(input.backend, input.workflowId, replayKey, name);
|
|
54925
|
+
const durableIntercomGroup = topology?.intercomGroup ?? input.durableIntercomGroup?.(replayKey, durableStageId);
|
|
54787
54926
|
const liveOptions = {
|
|
54788
54927
|
...options ?? {},
|
|
54789
54928
|
durableReplayKey: replayKey,
|
|
54790
54929
|
...durableStageId !== undefined ? { durableStageId } : {},
|
|
54791
54930
|
...topology !== undefined ? { durableParentIds: [...topology.parentIds] } : {},
|
|
54931
|
+
...durableIntercomGroup !== undefined ? { durableIntercomGroup } : {},
|
|
54792
54932
|
...isMidSessionResume ? {
|
|
54793
54933
|
resumeFromSessionFile: session.sessionFile,
|
|
54794
54934
|
durableAccumulatedDurationMs: session.durationMs ?? 0
|
|
@@ -54817,6 +54957,7 @@ function createDurableTaskPrimitive(input) {
|
|
|
54817
54957
|
}
|
|
54818
54958
|
const session = input.backend.getStageSession(input.workflowId, replayKey);
|
|
54819
54959
|
const topology = activeStageTopology(input.backend, input.workflowId, replayKey);
|
|
54960
|
+
const durableIntercomGroup = topology?.intercomGroup ?? input.durableIntercomGroup?.(replayKey, topology?.stageId);
|
|
54820
54961
|
const taskOptions = {
|
|
54821
54962
|
...options,
|
|
54822
54963
|
durableReplayKey: replayKey,
|
|
@@ -54824,6 +54965,7 @@ function createDurableTaskPrimitive(input) {
|
|
|
54824
54965
|
durableStageId: topology.stageId,
|
|
54825
54966
|
durableParentIds: [...topology.parentIds]
|
|
54826
54967
|
} : {},
|
|
54968
|
+
...durableIntercomGroup !== undefined ? { durableIntercomGroup } : {},
|
|
54827
54969
|
...session?.sessionFile !== undefined ? {
|
|
54828
54970
|
resumeFromSessionFile: session.sessionFile,
|
|
54829
54971
|
durableAccumulatedDurationMs: session.durationMs ?? 0
|
|
@@ -55486,6 +55628,7 @@ function appendStageStart(api, payload) {
|
|
|
55486
55628
|
name: payload.name,
|
|
55487
55629
|
parentIds: [...payload.parentIds],
|
|
55488
55630
|
...payload.model !== undefined ? { model: payload.model } : {},
|
|
55631
|
+
...payload.intercomGroup !== undefined ? { intercomGroup: payload.intercomGroup } : {},
|
|
55489
55632
|
...payload.pendingStageDeliveryAvailable !== undefined ? { pendingStageDeliveryAvailable: payload.pendingStageDeliveryAvailable } : {},
|
|
55490
55633
|
...payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {},
|
|
55491
55634
|
...payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {},
|
|
@@ -56030,6 +56173,7 @@ function installCompactionHook(api, store2) {
|
|
|
56030
56173
|
stageId: stage.id,
|
|
56031
56174
|
name: stage.name,
|
|
56032
56175
|
parentIds: [...stage.parentIds],
|
|
56176
|
+
intercomGroup: stage.intercomGroup,
|
|
56033
56177
|
pendingStageDeliveryAvailable: stage.pendingStageDeliveryAvailable,
|
|
56034
56178
|
ts: stage.startedAt ?? now
|
|
56035
56179
|
});
|
|
@@ -57157,7 +57301,9 @@ function fallbackRunDetailFromResult(workflowName, inputs, result) {
|
|
|
57157
57301
|
function emitTerminalRunDetailSurface(pi, workflowName, inputs, result) {
|
|
57158
57302
|
const inspected = inspectRun(result.runId);
|
|
57159
57303
|
const detail = inspected.ok ? inspected.detail : fallbackRunDetailFromResult(workflowName, inputs, result);
|
|
57160
|
-
|
|
57304
|
+
const owningRunStatuses = Object.fromEntries(store.graphSnapshot().runs.map((run) => [run.id, run.status]));
|
|
57305
|
+
const owningRunStatus = (runId) => owningRunStatuses[runId];
|
|
57306
|
+
emitChatSurface(pi, { kind: "detail", detail, owningRunStatuses }, { content: renderRunDetail(detail, { width: 100, owningRunStatus }) });
|
|
57161
57307
|
}
|
|
57162
57308
|
function formatWorkflowResourceLoadWarning(error) {
|
|
57163
57309
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -69037,18 +69183,28 @@ function resolveStageGroup(stageOptions, workflowGroup) {
|
|
|
69037
69183
|
const group = stageOptions.group;
|
|
69038
69184
|
if (group === undefined)
|
|
69039
69185
|
return workflowGroup;
|
|
69040
|
-
|
|
69041
|
-
|
|
69042
|
-
|
|
69043
|
-
|
|
69186
|
+
const authored = group === true ? randomUUID5() : group.trim();
|
|
69187
|
+
if (authored.length === 0)
|
|
69188
|
+
return;
|
|
69189
|
+
if (workflowGroup === undefined || authored === DEFAULT_INTERCOM_GROUP)
|
|
69190
|
+
return authored;
|
|
69191
|
+
const owner2 = normalizeGroup(workflowGroup);
|
|
69192
|
+
if (authored === owner2 || authored.startsWith(`${owner2}/`))
|
|
69193
|
+
return authored;
|
|
69194
|
+
return `${owner2}/${authored}`;
|
|
69195
|
+
}
|
|
69196
|
+
function workflowInvocationOwnsGroup(workflowGroup, candidate) {
|
|
69197
|
+
if (workflowGroup === undefined || candidate === undefined)
|
|
69198
|
+
return false;
|
|
69199
|
+
const owner2 = normalizeGroup(workflowGroup);
|
|
69200
|
+
const group = normalizeGroup(candidate);
|
|
69201
|
+
return group === owner2 || group.startsWith(`${owner2}/`);
|
|
69044
69202
|
}
|
|
69045
69203
|
function stageHasIntercomAccess(_stageOptions) {
|
|
69046
69204
|
return true;
|
|
69047
69205
|
}
|
|
69048
69206
|
function stageCanUseWorkflowPendingStageRoute(stageOptions, workflowGroup) {
|
|
69049
|
-
|
|
69050
|
-
return false;
|
|
69051
|
-
return normalizeGroup(resolveStageGroup(stageOptions, workflowGroup)) === normalizeGroup(workflowGroup);
|
|
69207
|
+
return stageHasIntercomAccess(stageOptions) && workflowInvocationOwnsGroup(workflowGroup, resolveStageGroup(stageOptions, workflowGroup));
|
|
69052
69208
|
}
|
|
69053
69209
|
|
|
69054
69210
|
// dist/builtin/workflows/src/shared/budget-meter.ts
|
|
@@ -73200,6 +73356,7 @@ function stripWorkflowOnlyOptions(options, defaultSessionDir, meta2, pendingStag
|
|
|
73200
73356
|
durableReplayKey: _durableReplayKey,
|
|
73201
73357
|
durableAccumulatedDurationMs: _durableAccumulatedDurationMs,
|
|
73202
73358
|
durableStageId: _durableStageId,
|
|
73359
|
+
durableIntercomGroup: _durableIntercomGroup,
|
|
73203
73360
|
durableParentIds: _durableParentIds,
|
|
73204
73361
|
sessionDir,
|
|
73205
73362
|
gitWorktreeDir: _gitWorktreeDir,
|
|
@@ -75322,15 +75479,18 @@ function createWorkflowStageFactory(input) {
|
|
|
75322
75479
|
const replaySource = replayDecision.kind === "replay" ? replayDecision.source : undefined;
|
|
75323
75480
|
const executeReplaySource = replayDecision.kind === "execute" ? replayDecision.source : undefined;
|
|
75324
75481
|
const shouldReplay = replaySource !== undefined;
|
|
75325
|
-
const
|
|
75482
|
+
const replayStageOptions = executeReplaySource?.sessionFile === undefined ? options : {
|
|
75326
75483
|
...options ?? {},
|
|
75327
75484
|
context: options?.context ?? "fork",
|
|
75328
75485
|
forkFromSessionFile: options?.forkFromSessionFile ?? executeReplaySource.sessionFile
|
|
75329
75486
|
};
|
|
75487
|
+
const intercomGroup = options?.durableIntercomGroup ?? resolveStageGroup(replayStageOptions, input.workflowIntercomGroup);
|
|
75488
|
+
const stageOptionsForContext = replayStageOptions?.group === undefined || intercomGroup === undefined ? replayStageOptions : { ...replayStageOptions, group: intercomGroup };
|
|
75330
75489
|
const pendingStageDeliveryAvailable = stageCanUseWorkflowPendingStageRoute(stageOptionsForContext, input.workflowIntercomGroup);
|
|
75331
75490
|
const stageSnapshot = {
|
|
75332
75491
|
id: stageId,
|
|
75333
75492
|
name,
|
|
75493
|
+
...intercomGroup === undefined ? {} : { intercomGroup },
|
|
75334
75494
|
replayKey,
|
|
75335
75495
|
status: shouldReplay ? "completed" : "pending",
|
|
75336
75496
|
parentIds: Object.freeze(parentIds),
|
|
@@ -75529,6 +75689,7 @@ function createWorkflowStageFactory(input) {
|
|
|
75529
75689
|
name,
|
|
75530
75690
|
parentIds: stageSnapshot.parentIds,
|
|
75531
75691
|
...stageReplayFields(stageSnapshot),
|
|
75692
|
+
...intercomGroup === undefined ? {} : { intercomGroup },
|
|
75532
75693
|
pendingStageDeliveryAvailable,
|
|
75533
75694
|
ts: stageSnapshot.startedAt ?? Date.now()
|
|
75534
75695
|
});
|
|
@@ -76210,11 +76371,16 @@ async function run(def, inputs, opts = {}) {
|
|
|
76210
76371
|
completedStageReplayKeys,
|
|
76211
76372
|
sourceToReplayedNodeIds: sourceToContinuationNodeIds
|
|
76212
76373
|
});
|
|
76374
|
+
const durableIntercomGroup = (replayKey, stageId) => {
|
|
76375
|
+
const stages = activeStore.runs().find((candidate) => candidate.id === runId)?.stages ?? [];
|
|
76376
|
+
return stages.find((stage) => stageId !== undefined && stage.id === stageId || stage.replayKey === replayKey)?.intercomGroup;
|
|
76377
|
+
};
|
|
76213
76378
|
let observedTaskTailQuit;
|
|
76214
76379
|
const durableTask = createDurableTaskPrimitive({
|
|
76215
76380
|
workflowId: runId,
|
|
76216
76381
|
backend: durableBackend,
|
|
76217
76382
|
nextReplayKey: (stageName3) => stageReplayKeyGenerator(stageName3),
|
|
76383
|
+
durableIntercomGroup,
|
|
76218
76384
|
task: taskRunners.task,
|
|
76219
76385
|
recordCachedTask: cachedStage.record,
|
|
76220
76386
|
signal: ownController.signal,
|
|
@@ -76263,6 +76429,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
76263
76429
|
workflowId: runId,
|
|
76264
76430
|
backend: durableBackend,
|
|
76265
76431
|
nextReplayKey: (stageName3) => stageReplayKeyGenerator(stageName3),
|
|
76432
|
+
durableIntercomGroup,
|
|
76266
76433
|
recordCachedStage: cachedStage.record,
|
|
76267
76434
|
stage: (name, options, replayKey) => {
|
|
76268
76435
|
const stage = runtime.stage(name, options);
|
|
@@ -79172,7 +79339,15 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
79172
79339
|
pi.events?.emit?.(PENDING_STAGE_ROUTE_EVENT, {
|
|
79173
79340
|
runId: run2.id,
|
|
79174
79341
|
group: workflowInvocationIntercomGroup(rootRunId),
|
|
79175
|
-
capability: workflowPendingStageRouteCapability(activeStore, run2.id)
|
|
79342
|
+
capability: workflowPendingStageRouteCapability(activeStore, run2.id),
|
|
79343
|
+
stages: run2.stages.filter((stage) => stage.pendingStageDeliveryAvailable === true && (stage.status === "pending" || stage.status === "running" || stage.status === "awaiting_input" || stage.status === "paused" || stage.status === "blocked")).map((stage) => ({
|
|
79344
|
+
stageId: stage.id,
|
|
79345
|
+
stageName: stage.name,
|
|
79346
|
+
target: `${run2.id}:${stage.id}`,
|
|
79347
|
+
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
79348
|
+
routeEligible: true,
|
|
79349
|
+
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
79350
|
+
}))
|
|
79176
79351
|
});
|
|
79177
79352
|
}
|
|
79178
79353
|
sweepPromise = sweepPromise.then(() => settleUndeliverablePendingStageMessages(activeStore, notifyUndeliverable)).then(() => {
|
|
@@ -79268,7 +79443,8 @@ async function queueAndPersist(activeStore, event, runGroup, pendingStageDeliver
|
|
|
79268
79443
|
const backend = durableBackendForRun(rootBackend, activeStore.runs(), event.runId);
|
|
79269
79444
|
if (backend === undefined)
|
|
79270
79445
|
return { outcome: "refused", reason: "Session not found" };
|
|
79271
|
-
const
|
|
79446
|
+
const senderGroup = event.from.groups?.includes(runGroup) === true ? runGroup : event.from.group;
|
|
79447
|
+
const result = await activeStore.queueStageMessage(request, senderGroup, runGroup, backend);
|
|
79272
79448
|
if (result === undefined)
|
|
79273
79449
|
return { outcome: "refused", reason: "Session not found" };
|
|
79274
79450
|
if (!result.ok) {
|
|
@@ -81642,7 +81818,8 @@ Available: ${formatAvailableWorkflowNames(deps.runtimeProxy.registry.names())}`)
|
|
|
81642
81818
|
const inspected = inspectRun(resolved.runId, { toolControlRegistry });
|
|
81643
81819
|
if (!inspected.ok)
|
|
81644
81820
|
return fail(`Run not found: ${target}`);
|
|
81645
|
-
|
|
81821
|
+
const owningRunStatuses = Object.fromEntries(store.graphSnapshot().runs.map((run2) => [run2.id, run2.status]));
|
|
81822
|
+
emitChatSurface(pi, { kind: "detail", detail: inspected.detail, owningRunStatuses });
|
|
81646
81823
|
return;
|
|
81647
81824
|
}
|
|
81648
81825
|
const capturedRuns = store.graphSnapshot().runs;
|
|
@@ -81861,6 +82038,7 @@ function summarizeRunSnapshot(run2, now = Date.now(), options) {
|
|
|
81861
82038
|
name: stage.name,
|
|
81862
82039
|
status: stage.status
|
|
81863
82040
|
})),
|
|
82041
|
+
pendingStages: pendingWorkflowStageStatuses(run2, options?.owningRunStatus),
|
|
81864
82042
|
tools: (run2.toolNodes ?? []).map((tool) => {
|
|
81865
82043
|
const owner2 = tool;
|
|
81866
82044
|
return {
|
|
@@ -82056,6 +82234,7 @@ function compactWorkflowToolMessage(result) {
|
|
|
82056
82234
|
return `${result.action}:${target ? ` ${target}` : ""} ${result.status} — ${result.message}`;
|
|
82057
82235
|
}
|
|
82058
82236
|
var STATUS_MESSAGE_CHAR_LIMIT = 120;
|
|
82237
|
+
var STATUS_PENDING_STAGE_LIMIT = 10;
|
|
82059
82238
|
function truncateStatusText(text) {
|
|
82060
82239
|
const flattened = text.replace(/\s+/g, " ").trim();
|
|
82061
82240
|
return flattened.length > STATUS_MESSAGE_CHAR_LIMIT ? `${flattened.slice(0, STATUS_MESSAGE_CHAR_LIMIT - 1)}…` : flattened;
|
|
@@ -82093,6 +82272,9 @@ function statusAwaitingInputLine(entry) {
|
|
|
82093
82272
|
const message = entry.message !== undefined ? ` — "${truncateStatusText(entry.message)}"` : "";
|
|
82094
82273
|
return ` awaiting input: ${target}${prompt}${message}`;
|
|
82095
82274
|
}
|
|
82275
|
+
function statusPendingStageLine(stage) {
|
|
82276
|
+
return ` pending stage: ${stage.name} (${stage.stageId}) lifecycle=${stage.lifecycle} pendingStageDeliveryAvailable=${stage.pendingStageDeliveryAvailable} Intercom target=${stage.target ?? "unavailable"}`;
|
|
82277
|
+
}
|
|
82096
82278
|
function statusRunIcon(run2, snapshot, allRuns) {
|
|
82097
82279
|
if (snapshot === undefined)
|
|
82098
82280
|
return statusIcon(run2.status);
|
|
@@ -82127,8 +82309,15 @@ function renderStatusToolContent(result) {
|
|
|
82127
82309
|
lines.push(` runId: ${run2.runId}`);
|
|
82128
82310
|
for (const entry of run2.awaitingInput)
|
|
82129
82311
|
lines.push(statusAwaitingInputLine(entry));
|
|
82312
|
+
for (const stage of run2.pendingStages.slice(0, STATUS_PENDING_STAGE_LIMIT)) {
|
|
82313
|
+
lines.push(statusPendingStageLine(stage));
|
|
82314
|
+
}
|
|
82315
|
+
if (run2.pendingStages.length > STATUS_PENDING_STAGE_LIMIT) {
|
|
82316
|
+
const omitted = run2.pendingStages.length - STATUS_PENDING_STAGE_LIMIT;
|
|
82317
|
+
lines.push(` … ${omitted} more pending stage${omitted === 1 ? "" : "s"}; use status with runId`);
|
|
82318
|
+
}
|
|
82130
82319
|
});
|
|
82131
|
-
lines.push("hint: status with runId returns full run detail; workflow answer answers pending prompts using runId/stageId/promptId; workflow resume controls paused runs; pause/interrupt/quit also accept runId. Ordinary Intercom handles free-form workflow-stage communication at <runId>:<stageKey>: live delivery is immediate
|
|
82320
|
+
lines.push("hint: status with runId returns full run detail; workflow answer answers pending prompts using runId/stageId/promptId; workflow resume controls paused runs; pause/interrupt/quit also accept runId. Ordinary Intercom handles free-form workflow-stage communication at <runId>:<stageKey>: live stage delivery is immediate; a known pending stage `send` queues before its first model turn; `ask` requires a live reply-capable stage.");
|
|
82132
82321
|
return lines.join(`
|
|
82133
82322
|
`);
|
|
82134
82323
|
}
|
|
@@ -83119,11 +83308,23 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
83119
83308
|
const durable = await awaitRequest(getRuntime().inspectDurableWorkflow(target));
|
|
83120
83309
|
return durable.kind === "found" ? { action: "statusDetail", runId: target, detail: durable.detail } : { action: "statusDetail", runId: target, error: durable.message };
|
|
83121
83310
|
}
|
|
83122
|
-
const
|
|
83123
|
-
|
|
83311
|
+
const inspected = inspectRun(resolved.runId, { toolControlRegistry });
|
|
83312
|
+
if (!inspected.ok) {
|
|
83313
|
+
return { action: "statusDetail", runId: target, error: `run not found: ${target}` };
|
|
83314
|
+
}
|
|
83315
|
+
const detailResult = {
|
|
83316
|
+
action: "statusDetail",
|
|
83317
|
+
runId: inspected.runId,
|
|
83318
|
+
detail: inspected.detail
|
|
83319
|
+
};
|
|
83320
|
+
setWorkflowStatusRenderRuns(detailResult, store.graphSnapshot().runs);
|
|
83321
|
+
return detailResult;
|
|
83124
83322
|
}
|
|
83323
|
+
const capturedRuns = store.graphSnapshot().runs;
|
|
83324
|
+
const statusByRunId = new Map(capturedRuns.map((run2) => [run2.id, run2.status]));
|
|
83125
83325
|
const listing = buildWorkflowStatusListing(topLevelExpandedSnapshots(), args.statusFilter ?? "all", Date.now(), {
|
|
83126
|
-
toolControlRegistry
|
|
83326
|
+
toolControlRegistry,
|
|
83327
|
+
owningRunStatus: (owningRunId) => statusByRunId.get(owningRunId)
|
|
83127
83328
|
});
|
|
83128
83329
|
const result = {
|
|
83129
83330
|
action: "status",
|
|
@@ -83131,7 +83332,7 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
83131
83332
|
runs: listing.runs,
|
|
83132
83333
|
snapshots: listing.snapshots
|
|
83133
83334
|
};
|
|
83134
|
-
setWorkflowStatusRenderRuns(result,
|
|
83335
|
+
setWorkflowStatusRenderRuns(result, capturedRuns);
|
|
83135
83336
|
return result;
|
|
83136
83337
|
}
|
|
83137
83338
|
case "stages":
|
|
@@ -83306,11 +83507,14 @@ function renderResult(result, opts) {
|
|
|
83306
83507
|
}
|
|
83307
83508
|
case "status": {
|
|
83308
83509
|
const r = result;
|
|
83510
|
+
const allRuns = opts?.allRuns ?? getWorkflowStatusRenderRuns(r) ?? r.snapshots;
|
|
83511
|
+
const statusByRunId = new Map(allRuns.map((run2) => [run2.id, run2.status]));
|
|
83309
83512
|
return renderStatusList(r.snapshots, {
|
|
83310
83513
|
theme: themed ? deriveGraphTheme({}) : undefined,
|
|
83311
83514
|
width: opts?.width,
|
|
83312
83515
|
now: opts?.now,
|
|
83313
|
-
allRuns
|
|
83516
|
+
allRuns,
|
|
83517
|
+
owningRunStatus: (runId) => statusByRunId.get(runId)
|
|
83314
83518
|
});
|
|
83315
83519
|
}
|
|
83316
83520
|
case "statusDetail": {
|
|
@@ -83319,10 +83523,13 @@ function renderResult(result, opts) {
|
|
|
83319
83523
|
return renderNotice("WORKFLOW STATUS", `id=${r2.runId}: ${r2.error}`, opts, themed);
|
|
83320
83524
|
}
|
|
83321
83525
|
const r = result;
|
|
83526
|
+
const allRuns = opts?.allRuns ?? getWorkflowStatusRenderRuns(r);
|
|
83527
|
+
const statusByRunId = new Map(allRuns?.map((run2) => [run2.id, run2.status]) ?? []);
|
|
83322
83528
|
return renderRunDetail(r.detail, {
|
|
83323
83529
|
theme: themed ? deriveGraphTheme({}) : undefined,
|
|
83324
83530
|
width: opts?.width,
|
|
83325
|
-
now: opts?.now
|
|
83531
|
+
now: opts?.now,
|
|
83532
|
+
owningRunStatus: (runId) => statusByRunId.get(runId)
|
|
83326
83533
|
});
|
|
83327
83534
|
}
|
|
83328
83535
|
case "inputs": {
|
|
@@ -83493,8 +83700,10 @@ var DEFAULT_PROMPT_GUIDANCE = [
|
|
|
83493
83700
|
`**Workflow authoring and handoffs**:
|
|
83494
83701
|
- When a user asks to create or edit a workflow, clarify only unresolved requirements that materially affect its purpose, inputs, stages, handoffs, validation, success criteria, or starter pattern. Read the workflow docs/examples, implement the TypeScript definition with normal coding tools, reload it, and run representative test inputs before presenting it. Use the create-spec skill when it adds value; it is not mandatory when context is already sufficient.
|
|
83495
83702
|
- 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.
|
|
83496
|
-
- Keep a small, readable workflow in one entry file. 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.
|
|
83703
|
+
- 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.
|
|
83497
83704
|
- 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.
|
|
83705
|
+
- 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.
|
|
83706
|
+
- 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.
|
|
83498
83707
|
- 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, 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.
|
|
83499
83708
|
- Consult docs/workflows.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.
|
|
83500
83709
|
- Treat workflow composition as a first-class authoring option. Before duplicating stages, inspect reusable workflow modules and builtin exports; import their definitions and invoke them with \`ctx.workflow(...)\`, mapping typed inputs and consuming only declared outputs. Nested workflows can themselves import children, so combine small reusable graphs into a richer parent while respecting \`maxDepth\`.
|
|
@@ -83505,7 +83714,7 @@ var DEFAULT_PROMPT_GUIDANCE = [
|
|
|
83505
83714
|
- Cyclic workflow graphs are unsupported. Workflow authors and coding agents MUST NOT create self-edges or dependency edges from the current frontier to an existing ancestor. Every materialized execution topology must remain a DAG. Redesign or stop before launch if a cycle cannot be removed.
|
|
83506
83715
|
- Bounded loops must create distinct tracked work for every iteration; never reopen an ancestor below its downstream work. Stacked implementation slices are unrolled, not looped: each slice gets a fresh child boundary and distinct tracked nodes, and no slice may add an edge back to the current frontier, itself, or an ancestor. If a retained session receives follow-up without new dependency work, keep it as non-topological activity metadata rather than adding a back-edge. Before launch, sketch nodes and dependencies for every branch and loop and reject any proposed parent edge to the node itself or an ancestor.
|
|
83507
83716
|
- Treat dynamic graph validation during execution, replay, and DBOS hydration as the authoritative cycle boundary. If runtime topology code changes, require incremental edge checks and DBOS hydration validation; prompt guidance and TypeScript types cannot replace those runtime checks.
|
|
83508
|
-
- Every workflow invocation
|
|
83717
|
+
- Every workflow invocation receives the stable control group \`workflow:<rootRunId>\`. Stages inherit it unless an intentional explicit group is authored. Named groups and \`group: true\` become invocation-owned subgroups under \`workflow:<rootRunId>/...\`, so repeated names cannot collide across runs. The invocation context may list and exactly send/ask live stages in its owned subgroups and queue send to known pending stages; this authority is directional and does not let subgroup siblings see or reach each other. Pending ask remains unsupported. \`group: "default"\` is the explicit non-owned shared-group escape and does not receive pending invocation routing. Do not mint root group names manually.
|
|
83509
83718
|
- Prefer \`ctx.tool(name, args, fn)\` for workflow-owned TypeScript operations with side effects, such as filesystem writes, network mutations, and external API actions. It creates a tracked, non-attachable durable graph node before invoking \`fn\`; it may be used before, between, after, or without model stages. A completed \`ctx.tool\` call is durably checkpointed with its serializable result, so resume replays that result without rerunning \`fn\`. For checks that may fail during a bounded repair loop, opt into \`failureMode: "return"\`, branch on the typed outcome, and pass only the needed error fields to the repair stage or artifact yourself; Atomic does not inject failure evidence into later prompts. Retries do not bound a hung callback, so every \`ctx.tool\` callback that starts a child process or performs network I/O MUST set an explicit positive finite \`timeoutMs\` and forward the supplied \`signal\` to cancellable work. A timeout applies per attempt, aborts that attempt's signal, and gives retries a fresh deadline and signal. Cancellation and storage faults still throw. Keep pure computation and side-effect-free transformations as ordinary TypeScript. Do not wrap agent-stage internals or every function call indiscriminately; this rule applies to side effects orchestrated directly by the workflow definition.
|
|
83510
83719
|
- Pass large stage context through files/artifacts and \`reads\` with an explicit \`Read the file at <path>...\` prompt rather than large \`previous\` payloads or injected session history.
|
|
83511
83720
|
- Wrap critical stage-prompt content in \`<keepContext>\` / \`</keepContext>\`. Tagged content survives compression verbatim regardless of the compression ratio, and every line of the span including the tag lines is protected. A long-running stage will be compacted, and compaction ranks lines individually: an objective is verbose and restated while the constraint that narrows it is usually one line, so the constraint is the cheaper deletion and what survives reads as broader permission than intended. Tag role constraints that bound a stage to part of the work, acceptance criteria and immutable contracts, explicit prohibitions, and identifiers a stage must not lose such as a target branch, worktree path, or run ID. Do not tag bulk context: protected lines count against the keep target rather than raising it, so a large protected span makes the surrounding transcript compress harder — tag the constraint, not the material it applies to.
|