@bastani/atomic 0.9.14-alpha.2 → 0.9.14-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.
Files changed (79) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  4. package/dist/builtin/mcp/package.json +2 -2
  5. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  6. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  7. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  8. package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
  9. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  10. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
  11. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  12. package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
  13. package/dist/builtin/subagents/agents/debugger.md +1 -1
  14. package/dist/builtin/subagents/agents/worker.md +1 -1
  15. package/dist/builtin/subagents/package.json +1 -1
  16. package/dist/builtin/web-access/CHANGELOG.md +16 -0
  17. package/dist/builtin/web-access/README.md +3 -6
  18. package/dist/builtin/web-access/index.ts +1 -2
  19. package/dist/builtin/web-access/package.json +2 -2
  20. package/dist/builtin/web-access/web-search-config.ts +2 -8
  21. package/dist/builtin/web-access/web-search-tool.ts +2 -7
  22. package/dist/builtin/web-access/web-search-workflow.ts +10 -0
  23. package/dist/builtin/workflows/CHANGELOG.md +18 -0
  24. package/dist/builtin/workflows/README.md +1 -1
  25. package/dist/builtin/workflows/builtin/goal-models.ts +4 -2
  26. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +2 -1
  27. package/dist/builtin/workflows/builtin/ralph-models.ts +10 -5
  28. package/dist/builtin/workflows/package.json +1 -1
  29. package/dist/builtin/workflows/src/extension/index.bundle.mjs +125 -66
  30. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +32 -4
  31. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -9
  32. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +27 -20
  33. package/dist/builtin/workflows/src/runs/foreground/executor.ts +4 -0
  34. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +6 -1
  35. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +6 -1
  36. package/dist/builtin/workflows/src/tui/graph-theme.ts +11 -0
  37. package/dist/builtin/workflows/src/tui/graph-view-render.ts +19 -10
  38. package/dist/builtin/workflows/src/tui/stage-chat-view-custom-ui.ts +7 -8
  39. package/dist/builtin/workflows/src/tui/tool-detail.ts +45 -26
  40. package/dist/core/tools/ask-user-question/ask-user-question.d.ts +3 -1
  41. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  42. package/dist/core/tools/ask-user-question/ask-user-question.js +2 -1
  43. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  44. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts +1 -0
  45. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts.map +1 -1
  46. package/dist/core/tools/ask-user-question/state/build-questionnaire.js +1 -0
  47. package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -1
  48. package/dist/core/tools/ask-user-question/state/key-router.d.ts.map +1 -1
  49. package/dist/core/tools/ask-user-question/state/key-router.js +3 -1
  50. package/dist/core/tools/ask-user-question/state/key-router.js.map +1 -1
  51. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +3 -0
  52. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
  53. package/dist/core/tools/ask-user-question/state/questionnaire-session.js +3 -0
  54. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
  55. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts +1 -0
  56. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -1
  57. package/dist/core/tools/ask-user-question/state/state-reducer.js +3 -1
  58. package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -1
  59. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts +2 -0
  60. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts.map +1 -1
  61. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js +1 -0
  62. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js.map +1 -1
  63. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts +3 -0
  64. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -1
  65. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +2 -1
  66. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -1
  67. package/dist/core/tools/edit-batch.d.ts +33 -0
  68. package/dist/core/tools/edit-batch.d.ts.map +1 -0
  69. package/dist/core/tools/edit-batch.js +89 -0
  70. package/dist/core/tools/edit-batch.js.map +1 -0
  71. package/dist/core/tools/edit.d.ts +1 -1
  72. package/dist/core/tools/edit.d.ts.map +1 -1
  73. package/dist/core/tools/edit.js +98 -42
  74. package/dist/core/tools/edit.js.map +1 -1
  75. package/docs/providers.md +1 -1
  76. package/docs/tools.md +1 -1
  77. package/docs/workflows.md +4 -4
  78. package/npm-shrinkwrap.json +65 -50
  79. package/package.json +5 -5
@@ -38912,7 +38912,8 @@ var MOCHA = {
38912
38912
  yellow: "#f9e2af",
38913
38913
  red: "#f38ba8",
38914
38914
  mauve: "#cba6f7",
38915
- sky: "#89dceb"
38915
+ sky: "#89dceb",
38916
+ lavender: "#b4befe"
38916
38917
  };
38917
38918
  function deriveGraphTheme(theme = {}) {
38918
38919
  return {
@@ -38929,6 +38930,8 @@ function deriveGraphTheme(theme = {}) {
38929
38930
  text: theme.text ?? MOCHA.text,
38930
38931
  textMuted: theme.textMuted ?? MOCHA.subtext0,
38931
38932
  dim: theme.dim ?? MOCHA.overlay1,
38933
+ toolTitle: theme.toolTitle ?? MOCHA.lavender,
38934
+ toolOutput: theme.toolOutput ?? MOCHA.text,
38932
38935
  accent: theme.accent ?? MOCHA.blue,
38933
38936
  mauve: theme.mauve ?? MOCHA.mauve,
38934
38937
  success: theme.success ?? MOCHA.green,
@@ -39002,6 +39005,8 @@ function deriveGraphThemeFromPiTheme(theme) {
39002
39005
  text: fgHex(t, "text") ?? fgHex(t, "customMessageText"),
39003
39006
  textMuted: fgHex(t, "muted"),
39004
39007
  dim: fgHex(t, "dim"),
39008
+ toolTitle: fgHex(t, "toolTitle"),
39009
+ toolOutput: fgHex(t, "toolOutput") ?? fgHex(t, "text") ?? fgHex(t, "customMessageText"),
39005
39010
  accent,
39006
39011
  success: fgHex(t, "success"),
39007
39012
  warning: fgHex(t, "warning"),
@@ -43801,7 +43806,12 @@ function renderSwitcher(stages, state, opts) {
43801
43806
  var TOOL_DETAIL_VALUE_LIMIT = TOOL_PAYLOAD_VALUE_LIMIT;
43802
43807
  var COLLAPSED_ARGS_LIMIT = 240;
43803
43808
  var COLLAPSED_RESULT_LINES = 10;
43804
- var BODY_INDENT = " ";
43809
+ var BOX_PAD = 1;
43810
+ function boxMetrics(width) {
43811
+ const safeWidth = Math.max(1, Math.floor(width));
43812
+ const inset = safeWidth >= BOX_PAD * 2 + 1 ? BOX_PAD : 0;
43813
+ return { pad: " ".repeat(inset), inner: Math.max(1, safeWidth - inset * 2) };
43814
+ }
43805
43815
  function statusColor2(status, theme) {
43806
43816
  switch (status) {
43807
43817
  case "running":
@@ -43842,14 +43852,26 @@ function styledStatus(status, theme) {
43842
43852
  return theme === undefined ? glyph : `${hexToAnsi(statusColor2(status, theme))}${glyph}${RESET}`;
43843
43853
  }
43844
43854
  function styledTitle(text, theme) {
43845
- return theme === undefined ? text : `${hexToAnsi(theme.text)}${BOLD}${text}${RESET}`;
43855
+ return theme === undefined ? text : `${hexToAnsi(theme.toolTitle)}${BOLD}${text}${RESET}`;
43856
+ }
43857
+ function styledOutput(text, theme) {
43858
+ return theme === undefined ? text : `${hexToAnsi(theme.toolOutput)}${text}${RESET}`;
43846
43859
  }
43847
43860
  function styledMuted(text, theme) {
43848
43861
  return theme === undefined ? text : `${hexToAnsi(theme.textMuted)}${text}${RESET}`;
43849
43862
  }
43863
+ function styledDim(text, theme) {
43864
+ return theme === undefined ? text : `${hexToAnsi(theme.dim)}${text}${RESET}`;
43865
+ }
43850
43866
  function styledError(text, theme) {
43851
43867
  return theme === undefined ? text : `${hexToAnsi(theme.error)}${text}${RESET}`;
43852
43868
  }
43869
+ function expandHintLine(earlier, expandKey, pad2, theme) {
43870
+ const lead = `... (${earlier} earlier lines`;
43871
+ if (expandKey.length === 0)
43872
+ return `${pad2}${styledMuted(`${lead})`, theme)}`;
43873
+ return `${pad2}${styledMuted(`${lead}, `, theme)}${styledDim(expandKey, theme)}${styledMuted(" Expand)", theme)}`;
43874
+ }
43853
43875
  function toolBackground(status, theme) {
43854
43876
  switch (status) {
43855
43877
  case "completed":
@@ -43993,70 +44015,70 @@ function paintRow(content, width, theme, status) {
43993
44015
  return `${background}${repainted}${background}${" ".repeat(padding)}${RESET}`;
43994
44016
  }
43995
44017
  function messageHeaderRows(tool, width, theme, expanded) {
43996
- const safeWidth = Math.max(1, Math.floor(width));
44018
+ const { pad: pad2, inner } = boxMetrics(width);
43997
44019
  const name = sanitizeToolTitleText(tool.name);
43998
44020
  const glyph = headerGlyph(tool.status);
43999
44021
  const glyphSuffix = glyph === undefined ? "" : ` ${glyph}`;
44000
44022
  const args = tool.args === undefined ? "" : boundedSerializedValue(tool.args, expanded ? TOOL_DETAIL_VALUE_LIMIT : COLLAPSED_ARGS_LIMIT);
44001
44023
  const withArgs = `$ ${name}${args ? ` ${args}` : ""}${glyphSuffix}`;
44002
- const plain = !expanded && visibleWidth(withArgs) > safeWidth ? `$ ${name}${glyphSuffix}` : withArgs;
44024
+ const plain = !expanded && visibleWidth(withArgs) > inner ? `$ ${name}${glyphSuffix}` : withArgs;
44003
44025
  const titleEnd = `$ ${name}`;
44004
- const continuationIndent = BODY_INDENT;
44005
- const continuationWidth = Math.max(1, safeWidth - visibleWidth(continuationIndent));
44006
- return wrapFieldValue(plain, safeWidth, continuationWidth).map((chunk, index, chunks) => {
44007
- const prefix = index === 0 ? "" : continuationIndent;
44026
+ return wrapFieldValue(plain, inner, inner).map((chunk, index, chunks) => {
44008
44027
  if (index !== 0 || !chunk.startsWith(titleEnd))
44009
- return `${prefix}${styledMuted(chunk, theme)}`;
44028
+ return `${pad2}${styledMuted(chunk, theme)}`;
44010
44029
  const remainder = chunk.slice(titleEnd.length);
44011
44030
  const hasStatus = glyphSuffix.length > 0 && index === chunks.length - 1 && remainder.endsWith(glyphSuffix);
44012
44031
  const summary = hasStatus ? remainder.slice(0, -glyphSuffix.length) : remainder;
44013
44032
  const suffix = hasStatus ? ` ${styledStatus(tool.status, theme)}` : "";
44014
- return `${styledTitle(titleEnd, theme)}${summary.trim().length > 0 ? styledMuted(summary, theme) : ""}${suffix}`;
44033
+ const title = styledTitle(titleEnd, theme);
44034
+ const rest = summary.trim().length > 0 ? styledMuted(summary, theme) : "";
44035
+ return `${pad2}${title}${rest}${suffix}`;
44015
44036
  });
44016
44037
  }
44017
44038
  function bodyRows(text, error, width, theme) {
44018
- const contentWidth = Math.max(1, width - visibleWidth(BODY_INDENT));
44019
- return wrapFieldValue(text, contentWidth).map((line) => {
44020
- const styled = error ? styledError(line, theme) : styledMuted(line, theme);
44021
- return `${BODY_INDENT}${styled}`;
44039
+ const { pad: pad2, inner } = boxMetrics(width);
44040
+ return wrapFieldValue(text, inner).map((line) => {
44041
+ const styled = error ? styledError(line, theme) : styledOutput(line, theme);
44042
+ return `${pad2}${styled}`;
44022
44043
  });
44023
44044
  }
44024
44045
  function footerText(tool, elapsed) {
44025
44046
  if (elapsed === undefined)
44026
44047
  return;
44027
44048
  const label = tool.status === "running" ? "Elapsed" : "Took";
44028
- const duration = elapsed < 1000 ? `${Math.round(elapsed)}ms` : fmtDuration(elapsed);
44029
44049
  const markers = [
44030
44050
  tool.status === "cached" ? "cached" : undefined,
44031
44051
  tool.replayed === true ? "replayed" : undefined
44032
44052
  ].filter((marker) => marker !== undefined);
44033
- return `${label} ${duration}${markers.length > 0 ? ` · ${markers.join(" · ")}` : ""}`;
44053
+ return `${label} ${fmtDuration(elapsed)}${markers.length > 0 ? ` · ${markers.join(" · ")}` : ""}`;
44034
44054
  }
44035
44055
  function renderMessageLines(tool, width, theme, expanded, expandKey, now) {
44036
44056
  const safeWidth = Math.max(1, Math.floor(width));
44057
+ const { pad: pad2, inner } = boxMetrics(safeWidth);
44037
44058
  const result = resultText(tool, TOOL_DETAIL_VALUE_LIMIT);
44038
44059
  const rows = messageHeaderRows(tool, safeWidth, theme, expanded);
44060
+ rows.push("");
44039
44061
  const wrappedBody = bodyRows(result.text, result.error, safeWidth, theme);
44040
44062
  if (expanded) {
44041
44063
  rows.push(...wrappedBody);
44042
44064
  if (tool.source !== undefined && tool.source.length > 0) {
44043
- const sourceWidth = Math.max(1, safeWidth - visibleWidth(BODY_INDENT));
44044
- rows.push(...wrapFieldValue(boundedToolText(sanitizeToolDisplayText(tool.source)), sourceWidth).map((line) => `${BODY_INDENT}${styledMuted(line, theme)}`));
44065
+ rows.push(...wrapFieldValue(boundedToolText(sanitizeToolDisplayText(tool.source)), inner).map((line) => `${pad2}${styledMuted(line, theme)}`));
44045
44066
  }
44046
44067
  } else {
44047
44068
  const earlier = Math.max(0, wrappedBody.length - COLLAPSED_RESULT_LINES);
44048
44069
  if (earlier > 0) {
44049
- const hint = expandKey.length > 0 ? `... (${earlier} earlier lines, ${expandKey} Expand)` : `... (${earlier} earlier lines)`;
44050
- rows.push(` ${styledMuted(hint, theme)}`);
44070
+ rows.push(expandHintLine(earlier, expandKey, pad2, theme));
44051
44071
  }
44052
44072
  rows.push(...wrappedBody.slice(-COLLAPSED_RESULT_LINES));
44053
44073
  }
44054
44074
  const footer = footerText(tool, durationMs(tool, now));
44055
44075
  if (footer !== undefined) {
44056
44076
  rows.push("");
44057
- rows.push(styledMuted(footer, theme));
44077
+ rows.push(`${pad2}${styledMuted(footer, theme)}`);
44058
44078
  }
44059
- return rows.map((row) => paintRow(row, safeWidth, theme, tool.status));
44079
+ const painted = rows.map((row) => paintRow(row, safeWidth, theme, tool.status));
44080
+ const padRow = paintRow("", safeWidth, theme, tool.status);
44081
+ return [padRow, ...painted, padRow];
44060
44082
  }
44061
44083
  function renderToolDetail(tool, opts = {}) {
44062
44084
  const width = Math.max(1, Math.floor(opts.width ?? 80));
@@ -44078,6 +44100,10 @@ function stripLayoutWrapper(line) {
44078
44100
  const end = endsWithWrapper ? line.length - LAYOUT_OSC_RESET.length : line.length;
44079
44101
  return line.slice(start, Math.max(start, end));
44080
44102
  }
44103
+ var TOOL_DETAIL_VIEWPORT_PAD = 1;
44104
+ function toolDetailViewportPad(rows) {
44105
+ return rows >= TOOL_DETAIL_VIEWPORT_PAD * 2 + 1 ? TOOL_DETAIL_VIEWPORT_PAD : 0;
44106
+ }
44081
44107
 
44082
44108
  class GraphViewRenderer extends GraphViewGraphRenderer {
44083
44109
  graphLayout;
@@ -44169,14 +44195,13 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
44169
44195
  const cached = this.detailFrame;
44170
44196
  if (cached !== null && cached.width === safeWidth)
44171
44197
  return cached;
44172
- const blockWidth = Math.max(1, safeWidth - 1);
44173
44198
  const frame = {
44174
44199
  width: safeWidth,
44175
- blockWidth,
44176
- leftPad: safeWidth > 1 ? 1 : 0,
44200
+ blockWidth: safeWidth,
44201
+ leftPad: 0,
44177
44202
  lines: renderToolDetailLines(node, {
44178
44203
  theme: this.graphTheme,
44179
- width: blockWidth,
44204
+ width: safeWidth,
44180
44205
  expanded: this.toolDetailExpanded,
44181
44206
  expandKey: toolExpandKey(isKeybindingsLike(this.piKeybindings) ? this.piKeybindings : undefined)
44182
44207
  })
@@ -44187,7 +44212,8 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
44187
44212
  _graphBodyContentHeight(width, viewportRows) {
44188
44213
  const rows = Math.max(0, Math.floor(viewportRows));
44189
44214
  if (this.toolDetail !== null) {
44190
- return Math.max(rows, this._toolDetailFrame(this.toolDetail, width).lines.length);
44215
+ const pad2 = toolDetailViewportPad(rows);
44216
+ return Math.max(rows, this._toolDetailFrame(this.toolDetail, width).lines.length + pad2 * 2);
44191
44217
  }
44192
44218
  if (!this._currentRenderRun() || this.cachedRenderGeometry.totalRows <= 0)
44193
44219
  return rows;
@@ -44245,7 +44271,10 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
44245
44271
  _renderBody(width, top, rows, _contentRows) {
44246
44272
  if (this.toolDetail !== null) {
44247
44273
  const detail = this._toolDetailFrame(this.toolDetail, width);
44248
- return detail.lines.slice(top, top + rows).map((line) => this._canvasRow(`${" ".repeat(detail.leftPad)}${line}`, width));
44274
+ const pad2 = toolDetailViewportPad(rows);
44275
+ const inner = Math.max(0, rows - pad2 * 2);
44276
+ const painted = detail.lines.slice(top, top + inner).map((line) => this._canvasRow(`${" ".repeat(detail.leftPad)}${line}`, width));
44277
+ return [...Array.from({ length: pad2 }, () => ""), ...painted, ...Array.from({ length: pad2 }, () => "")];
44249
44278
  }
44250
44279
  const run = this._currentRenderRun();
44251
44280
  const raw = run ? this._renderGraph(width, top, rows, run) : this._renderEmptyBody(width, rows);
@@ -45560,11 +45589,6 @@ async function showCustomUi(ctx, request) {
45560
45589
  ctx.stageUiBroker.reject(request, new Error("atomic-workflows: stage custom UI cannot mount without attached TUI host"));
45561
45590
  return;
45562
45591
  }
45563
- if (request.options?.overlay === true) {
45564
- ctx.mountingRequestId = null;
45565
- ctx.stageUiBroker.reject(request, new Error("atomic-workflows: ctx.ui.custom overlay mode is unavailable in the workflow graph viewer"));
45566
- return;
45567
- }
45568
45592
  try {
45569
45593
  const mounted = await mountStageCustomUi(request, ctx.piTui, ctx.piTheme, ctx.piKeybindings, ctx.stageUiBroker, () => {
45570
45594
  if (ctx.mountedCustomUi?.request.id !== request.id)
@@ -56020,7 +56044,8 @@ var orchestratorModelConfig = {
56020
56044
  "openai/gpt-5.5:xhigh",
56021
56045
  "anthropic/claude-opus-4-8:high",
56022
56046
  "github-copilot/claude-opus-4.8:high",
56023
- "xai/grok-4.6:high",
56047
+ "xai/grok-4.6:xhigh",
56048
+ "github-copilot/grok-4.6:xhigh",
56024
56049
  "zai/glm-5.3:high",
56025
56050
  "zai-coding-cn/glm-5.3:high",
56026
56051
  "openrouter/anthropic/claude-opus-5:high",
@@ -56051,7 +56076,8 @@ var reviewerModelConfig = {
56051
56076
  "openai/gpt-5.5:xhigh",
56052
56077
  "anthropic/claude-opus-4-8:high",
56053
56078
  "github-copilot/claude-opus-4.8:high",
56054
- "xai/grok-4.6:high",
56079
+ "xai/grok-4.6:xhigh",
56080
+ "github-copilot/grok-4.6:xhigh",
56055
56081
  "zai/glm-5.3:high",
56056
56082
  "zai-coding-cn/glm-5.3:high",
56057
56083
  "openrouter/anthropic/claude-opus-5:high",
@@ -58079,7 +58105,8 @@ async function runOpenClaudeDesignWorkflow(ctx) {
58079
58105
  "openai-codex/gpt-5.6-sol:xhigh",
58080
58106
  "github-copilot/gpt-5.6-sol:xhigh",
58081
58107
  "openai/gpt-5.6-sol:xhigh",
58082
- "xai/grok-4.6:high",
58108
+ "xai/grok-4.6:xhigh",
58109
+ "github-copilot/grok-4.6:xhigh",
58083
58110
  "zai/glm-5.3:high",
58084
58111
  "zai-coding-cn/glm-5.3:high",
58085
58112
  "openrouter/anthropic/claude-opus-5:high",
@@ -59016,7 +59043,8 @@ var promptEngineerModelConfig = {
59016
59043
  "openai/gpt-5.5:xhigh",
59017
59044
  "anthropic/claude-opus-4-8:high",
59018
59045
  "github-copilot/claude-opus-4.8:high",
59019
- "xai/grok-4.6:high",
59046
+ "xai/grok-4.6:xhigh",
59047
+ "github-copilot/grok-4.6:xhigh",
59020
59048
  "zai/glm-5.3:high",
59021
59049
  "zai-coding-cn/glm-5.3:high",
59022
59050
  "openrouter/anthropic/claude-opus-5:high",
@@ -59047,7 +59075,8 @@ var researchModelConfig = {
59047
59075
  "openai/gpt-5.5:xhigh",
59048
59076
  "anthropic/claude-opus-4-8:high",
59049
59077
  "github-copilot/claude-opus-4.8:high",
59050
- "xai/grok-4.6:high",
59078
+ "xai/grok-4.6:xhigh",
59079
+ "github-copilot/grok-4.6:xhigh",
59051
59080
  "zai/glm-5.3:high",
59052
59081
  "zai-coding-cn/glm-5.3:high",
59053
59082
  "openrouter/anthropic/claude-opus-5:high",
@@ -59078,7 +59107,8 @@ var orchestratorModelConfig2 = {
59078
59107
  "openai/gpt-5.5:xhigh",
59079
59108
  "anthropic/claude-opus-4-8:high",
59080
59109
  "github-copilot/claude-opus-4.8:high",
59081
- "xai/grok-4.6:high",
59110
+ "xai/grok-4.6:xhigh",
59111
+ "github-copilot/grok-4.6:xhigh",
59082
59112
  "zai/glm-5.3:high",
59083
59113
  "zai-coding-cn/glm-5.3:high",
59084
59114
  "openrouter/anthropic/claude-opus-5:high",
@@ -59109,7 +59139,8 @@ var reviewerAModelConfig = {
59109
59139
  "openai/gpt-5.5:xhigh",
59110
59140
  "anthropic/claude-opus-4-8:high",
59111
59141
  "github-copilot/claude-opus-4.8:high",
59112
- "xai/grok-4.6:high",
59142
+ "xai/grok-4.6:xhigh",
59143
+ "github-copilot/grok-4.6:xhigh",
59113
59144
  "zai/glm-5.3:high",
59114
59145
  "zai-coding-cn/glm-5.3:high",
59115
59146
  "openrouter/anthropic/claude-opus-5:high",
@@ -59141,7 +59172,8 @@ var reviewerBModelConfig = {
59141
59172
  "openai/gpt-5.5:xhigh",
59142
59173
  "anthropic/claude-opus-4-8:high",
59143
59174
  "github-copilot/claude-opus-4.8:high",
59144
- "xai/grok-4.6:high",
59175
+ "xai/grok-4.6:xhigh",
59176
+ "github-copilot/grok-4.6:xhigh",
59145
59177
  "zai/glm-5.3:high",
59146
59178
  "zai-coding-cn/glm-5.3:high",
59147
59179
  "openrouter/openai/gpt-5.6-sol:xhigh",
@@ -60826,6 +60858,7 @@ function askUserQuestionToolEvent(event) {
60826
60858
  return;
60827
60859
  }
60828
60860
  var READINESS_GATE_ADVANCE_LABEL = "I'm ready to move on to the next workflow stage.";
60861
+ var READINESS_GATE_CHAT_MESSAGE = "The user would like to chat more about this";
60829
60862
  var READINESS_GATE_ADVANCE_NORMALIZED = READINESS_GATE_ADVANCE_LABEL.trim().toLowerCase();
60830
60863
  var READINESS_GATE_QUESTION_PARAMS = {
60831
60864
  questions: [
@@ -60870,6 +60903,34 @@ function toolResultHasChatAnswer(result) {
60870
60903
  return false;
60871
60904
  return answers.some((a) => a !== null && typeof a === "object" && a.kind === "chat");
60872
60905
  }
60906
+ function firstReadinessAnswer(result) {
60907
+ if (result === null || typeof result !== "object")
60908
+ return;
60909
+ const details = result.details;
60910
+ if (details === null || typeof details !== "object")
60911
+ return;
60912
+ const answers = details.answers;
60913
+ if (!Array.isArray(answers))
60914
+ return;
60915
+ const first = answers[0];
60916
+ return first !== null && typeof first === "object" ? first : undefined;
60917
+ }
60918
+ function readinessStayMessage(result) {
60919
+ const first = firstReadinessAnswer(result);
60920
+ if (first === undefined)
60921
+ return;
60922
+ if (first.kind === "chat")
60923
+ return READINESS_GATE_CHAT_MESSAGE;
60924
+ if (first.kind !== "custom" || typeof first.answer !== "string")
60925
+ return;
60926
+ return first.answer.trim().length > 0 ? first.answer : undefined;
60927
+ }
60928
+ function interpretReadinessResult(result) {
60929
+ if (readinessResultMeansAdvance(result))
60930
+ return { action: "advance" };
60931
+ const message = readinessStayMessage(result);
60932
+ return message !== undefined ? { action: "stay", message } : { action: "stay" };
60933
+ }
60873
60934
  function shouldInjectResumeContinuation(state) {
60874
60935
  if (state.reason === false || state.aborted)
60875
60936
  return false;
@@ -60878,14 +60939,14 @@ function shouldInjectResumeContinuation(state) {
60878
60939
  var cachedReadinessGateTool;
60879
60940
  function readinessGateTool() {
60880
60941
  if (cachedReadinessGateTool === undefined) {
60881
- cachedReadinessGateTool = createAskUserQuestionToolDefinition();
60942
+ cachedReadinessGateTool = createAskUserQuestionToolDefinition({ chatAsOption: true });
60882
60943
  }
60883
60944
  return cachedReadinessGateTool;
60884
60945
  }
60885
60946
  async function askReadinessViaStageBroker(runId, stageId, signal) {
60886
60947
  const execute = readinessGateTool().execute;
60887
60948
  if (execute === undefined)
60888
- return "advance";
60949
+ return { action: "advance" };
60889
60950
  const gateContext = {
60890
60951
  hasUI: true,
60891
60952
  ui: {
@@ -60898,7 +60959,7 @@ async function askReadinessViaStageBroker(runId, stageId, signal) {
60898
60959
  stageUiBroker.provideStagePrompt(runId, stageId, gateAdapter);
60899
60960
  try {
60900
60961
  const result = await execute(gatePromptId, READINESS_GATE_QUESTION_PARAMS, signal, undefined, gateContext);
60901
- return readinessResultMeansAdvance(result) ? "advance" : "stay";
60962
+ return interpretReadinessResult(result);
60902
60963
  } finally {
60903
60964
  stageUiBroker.clearStagePrompt(runId, stageId);
60904
60965
  }
@@ -64990,12 +65051,6 @@ function buildPromptNodeUiAdapter(input) {
64990
65051
  throw err;
64991
65052
  }
64992
65053
  if (isCustom) {
64993
- if (descriptor.options?.overlay === true) {
64994
- const error = new Error("atomic-workflows: ctx.ui.custom overlay mode is unavailable in the workflow graph viewer");
64995
- applyFailureToStage(stageSnapshot, input.classifyExecutorFailure(error));
64996
- await finalizePromptStage("failed");
64997
- throw error;
64998
- }
64999
65054
  const mergedSignal = mergeHilSignals(input.signal, descriptor.options?.signal);
65000
65055
  try {
65001
65056
  if (mergedSignal.signal.aborted)
@@ -68041,11 +68096,11 @@ function createTrackedStageCaller(input) {
68041
68096
  stageName: runtime.name,
68042
68097
  signal: runtime.signal
68043
68098
  });
68044
- return ready ? "advance" : "stay";
68099
+ return ready ? { action: "advance" } : { action: "stay" };
68045
68100
  }
68046
68101
  return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, runtime.signal);
68047
68102
  } catch {
68048
- return "advance";
68103
+ return { action: "advance" };
68049
68104
  }
68050
68105
  };
68051
68106
  const suppressReadinessForCurrentTurn = () => {
@@ -68187,25 +68242,29 @@ function createTrackedStageCaller(input) {
68187
68242
  try {
68188
68243
  while (runtime.state.askUserQuestionObservedThisTurn || repeatReadinessAfterChatTurn) {
68189
68244
  const decision = await confirmReadiness();
68190
- if (decision === "advance")
68245
+ if (decision.action === "advance")
68191
68246
  break;
68192
68247
  if (runtime.signal.aborted)
68193
68248
  break;
68194
68249
  runtime.state.askUserQuestionObservedThisTurn = false;
68195
68250
  runtime.state.chatAnswerObservedThisTurn = false;
68196
- runtime.state.waitingForStageChatTurn = true;
68197
- try {
68198
- await runtime.raceStageSessionHeartbeat(raceAbort(new Promise((resolve11) => {
68199
- resolveNextTurnEnd = resolve11;
68200
- runtime.state.wakeWaitingForStageChatTurn = resolve11;
68201
- }), runtime.signal));
68202
- } finally {
68203
- runtime.state.wakeWaitingForStageChatTurn = undefined;
68204
- runtime.state.waitingForStageChatTurn = false;
68251
+ if (decision.message !== undefined) {
68252
+ result = await runtime.raceStageSessionHeartbeat(raceAbort(runtime.innerCtx.prompt(decision.message), runtime.signal));
68253
+ } else {
68254
+ runtime.state.waitingForStageChatTurn = true;
68255
+ try {
68256
+ await runtime.raceStageSessionHeartbeat(raceAbort(new Promise((resolve11) => {
68257
+ resolveNextTurnEnd = resolve11;
68258
+ runtime.state.wakeWaitingForStageChatTurn = resolve11;
68259
+ }), runtime.signal));
68260
+ } finally {
68261
+ runtime.state.wakeWaitingForStageChatTurn = undefined;
68262
+ runtime.state.waitingForStageChatTurn = false;
68263
+ }
68264
+ if (runtime.signal.aborted)
68265
+ break;
68266
+ result = runtime.innerCtx.__getLastAssistantText() ?? result;
68205
68267
  }
68206
- if (runtime.signal.aborted)
68207
- break;
68208
- result = runtime.innerCtx.__getLastAssistantText() ?? result;
68209
68268
  const continuationDrain = await drainResumeContinuations(result);
68210
68269
  result = continuationDrain.result;
68211
68270
  repeatReadinessAfterChatTurn ||= continuationDrain.chatAnswerObserved;
@@ -262,6 +262,8 @@ export function askUserQuestionToolEvent(event: unknown): AskUserQuestionToolEve
262
262
 
263
263
  export const READINESS_GATE_ADVANCE_LABEL = "I'm ready to move on to the next workflow stage.";
264
264
 
265
+ export const READINESS_GATE_CHAT_MESSAGE = "The user would like to chat more about this";
266
+
265
267
  const READINESS_GATE_ADVANCE_NORMALIZED = READINESS_GATE_ADVANCE_LABEL.trim().toLowerCase();
266
268
 
267
269
  export const READINESS_GATE_QUESTION_PARAMS = {
@@ -313,6 +315,32 @@ export function toolResultHasChatAnswer(result: unknown): boolean {
313
315
  return answers.some((a) => a !== null && typeof a === "object" && (a as Record<string, unknown>).kind === "chat");
314
316
  }
315
317
 
318
+ export type ReadinessDecision = { readonly action: "advance" } | { readonly action: "stay"; readonly message?: string };
319
+
320
+ function firstReadinessAnswer(result: unknown): Record<string, unknown> | undefined {
321
+ if (result === null || typeof result !== "object") return undefined;
322
+ const details = (result as Record<string, unknown>).details;
323
+ if (details === null || typeof details !== "object") return undefined;
324
+ const answers = (details as Record<string, unknown>).answers;
325
+ if (!Array.isArray(answers)) return undefined;
326
+ const first = answers[0];
327
+ return first !== null && typeof first === "object" ? (first as Record<string, unknown>) : undefined;
328
+ }
329
+
330
+ export function readinessStayMessage(result: unknown): string | undefined {
331
+ const first = firstReadinessAnswer(result);
332
+ if (first === undefined) return undefined;
333
+ if (first.kind === "chat") return READINESS_GATE_CHAT_MESSAGE;
334
+ if (first.kind !== "custom" || typeof first.answer !== "string") return undefined;
335
+ return first.answer.trim().length > 0 ? first.answer : undefined;
336
+ }
337
+
338
+ export function interpretReadinessResult(result: unknown): ReadinessDecision {
339
+ if (readinessResultMeansAdvance(result)) return { action: "advance" };
340
+ const message = readinessStayMessage(result);
341
+ return message !== undefined ? { action: "stay", message } : { action: "stay" };
342
+ }
343
+
316
344
  export { RESUME_CONTINUATION_PROMPT } from "../../shared/resume-continuation.js";
317
345
 
318
346
  export function shouldInjectResumeContinuation(state: {
@@ -327,7 +355,7 @@ export function shouldInjectResumeContinuation(state: {
327
355
  let cachedReadinessGateTool: ReturnType<typeof createAskUserQuestionToolDefinition> | undefined;
328
356
  function readinessGateTool(): ReturnType<typeof createAskUserQuestionToolDefinition> {
329
357
  if (cachedReadinessGateTool === undefined) {
330
- cachedReadinessGateTool = createAskUserQuestionToolDefinition();
358
+ cachedReadinessGateTool = createAskUserQuestionToolDefinition({ chatAsOption: true });
331
359
  }
332
360
  return cachedReadinessGateTool;
333
361
  }
@@ -336,9 +364,9 @@ export async function askReadinessViaStageBroker(
336
364
  runId: string,
337
365
  stageId: string,
338
366
  signal: AbortSignal,
339
- ): Promise<"advance" | "stay"> {
367
+ ): Promise<ReadinessDecision> {
340
368
  const execute = readinessGateTool().execute;
341
- if (execute === undefined) return "advance";
369
+ if (execute === undefined) return { action: "advance" };
342
370
  const gateContext = {
343
371
  hasUI: true,
344
372
  ui: {
@@ -368,7 +396,7 @@ export async function askReadinessViaStageBroker(
368
396
  undefined,
369
397
  gateContext as unknown as Parameters<typeof execute>[4],
370
398
  );
371
- return readinessResultMeansAdvance(result) ? "advance" : "stay";
399
+ return interpretReadinessResult(result);
372
400
  } finally {
373
401
  stageUiBroker.clearStagePrompt(runId, stageId);
374
402
  }
@@ -243,15 +243,9 @@ export function buildPromptNodeUiAdapter(input: {
243
243
  }
244
244
 
245
245
  if (isCustom) {
246
- if (descriptor.options?.overlay === true) {
247
- const error = new Error(
248
- "atomic-workflows: ctx.ui.custom overlay mode is unavailable in the workflow graph viewer",
249
- );
250
- applyFailureToStage(stageSnapshot, input.classifyExecutorFailure(error));
251
- await finalizePromptStage("failed");
252
- throw error;
253
- }
254
-
246
+ // `overlay: true` is a placement hint the attached stage-chat host
247
+ // honours by mounting on its ordinary custom-UI slot, so a workflow
248
+ // asking for an overlay is served rather than failed here.
255
249
  const mergedSignal = mergeHilSignals(input.signal, descriptor.options?.signal);
256
250
  try {
257
251
  if (mergedSignal.signal.aborted) throw hilAbortError(mergedSignal.signal);
@@ -6,6 +6,7 @@ import { hasExplicitFastModeCandidate } from "./executor-direct-helpers.js";
6
6
  import {
7
7
  askReadinessViaStageBroker,
8
8
  RESUME_CONTINUATION_PROMPT,
9
+ type ReadinessDecision,
9
10
  shouldInjectResumeContinuation,
10
11
  } from "./executor-hil.js";
11
12
  import { applyFailureToStage } from "./executor-lifecycle.js";
@@ -45,7 +46,7 @@ export function createTrackedStageCaller(input: {
45
46
  const { runtime } = input;
46
47
  const readinessGateEnabled =
47
48
  runtime.opts.confirmStageReadiness !== undefined || runtime.opts.usePromptNodesForUi === true;
48
- const confirmReadiness = async (): Promise<"advance" | "stay"> => {
49
+ const confirmReadiness = async (): Promise<ReadinessDecision> => {
49
50
  try {
50
51
  if (runtime.opts.confirmStageReadiness !== undefined) {
51
52
  const ready = await runtime.opts.confirmStageReadiness({
@@ -54,11 +55,11 @@ export function createTrackedStageCaller(input: {
54
55
  stageName: runtime.name,
55
56
  signal: runtime.signal,
56
57
  });
57
- return ready ? "advance" : "stay";
58
+ return ready ? { action: "advance" } : { action: "stay" };
58
59
  }
59
60
  return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, runtime.signal);
60
61
  } catch {
61
- return "advance";
62
+ return { action: "advance" };
62
63
  }
63
64
  };
64
65
 
@@ -230,27 +231,33 @@ export function createTrackedStageCaller(input: {
230
231
  try {
231
232
  while (runtime.state.askUserQuestionObservedThisTurn || repeatReadinessAfterChatTurn) {
232
233
  const decision = await confirmReadiness();
233
- if (decision === "advance") break;
234
+ if (decision.action === "advance") break;
234
235
  if (runtime.signal.aborted) break;
235
236
  runtime.state.askUserQuestionObservedThisTurn = false;
236
237
  runtime.state.chatAnswerObservedThisTurn = false;
237
- runtime.state.waitingForStageChatTurn = true;
238
- try {
239
- await runtime.raceStageSessionHeartbeat(
240
- raceAbort(
241
- new Promise<void>((resolve) => {
242
- resolveNextTurnEnd = resolve;
243
- runtime.state.wakeWaitingForStageChatTurn = resolve;
244
- }),
245
- runtime.signal,
246
- ),
247
- );
248
- } finally {
249
- runtime.state.wakeWaitingForStageChatTurn = undefined;
250
- runtime.state.waitingForStageChatTurn = false;
238
+ if (decision.message !== undefined) {
239
+ result = (await runtime.raceStageSessionHeartbeat(
240
+ raceAbort(runtime.innerCtx.prompt(decision.message), runtime.signal),
241
+ )) as T;
242
+ } else {
243
+ runtime.state.waitingForStageChatTurn = true;
244
+ try {
245
+ await runtime.raceStageSessionHeartbeat(
246
+ raceAbort(
247
+ new Promise<void>((resolve) => {
248
+ resolveNextTurnEnd = resolve;
249
+ runtime.state.wakeWaitingForStageChatTurn = resolve;
250
+ }),
251
+ runtime.signal,
252
+ ),
253
+ );
254
+ } finally {
255
+ runtime.state.wakeWaitingForStageChatTurn = undefined;
256
+ runtime.state.waitingForStageChatTurn = false;
257
+ }
258
+ if (runtime.signal.aborted) break;
259
+ result = (runtime.innerCtx.__getLastAssistantText() ?? result) as T;
251
260
  }
252
- if (runtime.signal.aborted) break;
253
- result = (runtime.innerCtx.__getLastAssistantText() ?? result) as T;
254
261
  const continuationDrain = await drainResumeContinuations(result);
255
262
  result = continuationDrain.result;
256
263
  repeatReadinessAfterChatTurn ||= continuationDrain.chatAnswerObserved;
@@ -7,12 +7,16 @@
7
7
  */
8
8
 
9
9
  export { raceAbort } from "./executor-abort.js";
10
+ export type { ReadinessDecision } from "./executor-hil.js";
10
11
  export {
11
12
  askReadinessViaStageBroker,
13
+ interpretReadinessResult,
12
14
  READINESS_GATE_ADVANCE_LABEL,
15
+ READINESS_GATE_CHAT_MESSAGE,
13
16
  READINESS_GATE_QUESTION_PARAMS,
14
17
  RESUME_CONTINUATION_PROMPT,
15
18
  readinessResultMeansAdvance,
19
+ readinessStayMessage,
16
20
  shouldInjectResumeContinuation,
17
21
  toolResultHasChatAnswer,
18
22
  } from "./executor-hil.js";
@@ -13,7 +13,12 @@ export type WorkflowCustomUiOverlayOptions = OverlayOptions;
13
13
  export type WorkflowCustomUiOverlayHandle = OverlayHandle;
14
14
  export type WorkflowCustomUiFactory<T> = (tui: TUI, theme: Theme, keybindings: KeybindingsManager, done: (value: T) => void) => WorkflowCustomUiComponent | Promise<WorkflowCustomUiComponent>;
15
15
  export interface WorkflowCustomUiOptions {
16
- /** Render as a nested overlay. Workflow graph hosts may reject this when unsupported. */
16
+ /**
17
+ * Ask the host to render as an overlay. Workflow graph hosts accept this: the
18
+ * attached stage chat mounts the widget on its ordinary custom-UI slot, which
19
+ * already keeps the stage transcript visible behind it, instead of opening a
20
+ * nested overlay above the graph chrome.
21
+ */
17
22
  readonly overlay?: boolean;
18
23
  /** AbortSignal to programmatically dismiss the custom UI. */
19
24
  readonly signal?: AbortSignal;
@@ -49,7 +49,12 @@ export type WorkflowCustomUiFactory<T> = (
49
49
  ) => WorkflowCustomUiComponent | Promise<WorkflowCustomUiComponent>;
50
50
 
51
51
  export interface WorkflowCustomUiOptions {
52
- /** Render as a nested overlay. Workflow graph hosts may reject this when unsupported. */
52
+ /**
53
+ * Ask the host to render as an overlay. Workflow graph hosts accept this: the
54
+ * attached stage chat mounts the widget on its ordinary custom-UI slot, which
55
+ * already keeps the stage transcript visible behind it, instead of opening a
56
+ * nested overlay above the graph chrome.
57
+ */
53
58
  readonly overlay?: boolean;
54
59
  /** AbortSignal to programmatically dismiss the custom UI. */
55
60
  readonly signal?: AbortSignal;