@bastani/atomic 0.9.16-alpha.7 → 0.9.16-alpha.9

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 (226) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +4 -4
  4. package/dist/builtin/intercom/broker/broker.ts +617 -22
  5. package/dist/builtin/intercom/broker/client-message-validation.ts +9 -0
  6. package/dist/builtin/intercom/broker/client.ts +200 -10
  7. package/dist/builtin/intercom/broker/pending-send-registry.ts +4 -0
  8. package/dist/builtin/intercom/broker/send-handler.ts +90 -36
  9. package/dist/builtin/intercom/broker/send-signature.ts +20 -8
  10. package/dist/builtin/intercom/group.ts +85 -0
  11. package/dist/builtin/intercom/index.bundle.mjs +746 -55
  12. package/dist/builtin/intercom/package.json +1 -1
  13. package/dist/builtin/intercom/session-target.ts +54 -0
  14. package/dist/builtin/intercom/skills/intercom/SKILL.md +18 -3
  15. package/dist/builtin/intercom/source-ownership.ts +31 -0
  16. package/dist/builtin/intercom/types.ts +115 -0
  17. package/dist/builtin/mcp/index.bundle.mjs +175 -37
  18. package/dist/builtin/mcp/package.json +1 -1
  19. package/dist/builtin/subagents/package.json +1 -1
  20. package/dist/builtin/subagents/src/extension/index.bundle.mjs +239 -53
  21. package/dist/builtin/web-access/index.bundle.mjs +175 -37
  22. package/dist/builtin/web-access/package.json +1 -1
  23. package/dist/builtin/workflows/CHANGELOG.md +15 -0
  24. package/dist/builtin/workflows/README.md +40 -37
  25. package/dist/builtin/workflows/builtin/adversarial-verification.js +13 -0
  26. package/dist/builtin/workflows/builtin/{shared-prompts.ts → chunk-0x6e303p.js} +133 -154
  27. package/dist/builtin/workflows/builtin/chunk-17zk6ffd.js +69794 -0
  28. package/dist/builtin/workflows/builtin/chunk-29wrp38a.js +199 -0
  29. package/dist/builtin/workflows/builtin/chunk-2dqb5s2q.js +602 -0
  30. package/dist/builtin/workflows/builtin/chunk-4febxsv4.js +264 -0
  31. package/dist/builtin/workflows/builtin/chunk-5wgwscd0.js +4 -0
  32. package/dist/builtin/workflows/builtin/chunk-6fqs7c01.js +155 -0
  33. package/dist/builtin/workflows/builtin/chunk-7430zyas.js +126 -0
  34. package/dist/builtin/workflows/builtin/chunk-7at6dnkr.js +33 -0
  35. package/dist/builtin/workflows/builtin/chunk-82ha8p41.js +175 -0
  36. package/dist/builtin/workflows/builtin/chunk-8v8wmb7z.js +529 -0
  37. package/dist/builtin/workflows/builtin/chunk-bfkmzv9h.js +156 -0
  38. package/dist/builtin/workflows/builtin/chunk-c53y8bdh.js +345 -0
  39. package/dist/builtin/workflows/builtin/chunk-cg9tmks0.js +206 -0
  40. package/dist/builtin/workflows/builtin/chunk-h5e65g7g.js +1080 -0
  41. package/dist/builtin/workflows/builtin/chunk-hzzn6adg.js +221 -0
  42. package/dist/builtin/workflows/builtin/chunk-nqr34qp3.js +1061 -0
  43. package/dist/builtin/workflows/builtin/chunk-qe6bfpbd.js +1207 -0
  44. package/dist/builtin/workflows/builtin/chunk-qwzvgxnq.js +404 -0
  45. package/dist/builtin/workflows/builtin/chunk-qx2ptjs3.js +215 -0
  46. package/dist/builtin/workflows/builtin/chunk-rbnj9621.js +2447 -0
  47. package/dist/builtin/workflows/builtin/chunk-wpckd35c.js +12 -0
  48. package/dist/builtin/workflows/builtin/chunk-x2ghn0je.js +4110 -0
  49. package/dist/builtin/workflows/builtin/classify-and-act.js +12 -0
  50. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +10 -0
  51. package/dist/builtin/workflows/builtin/generate-and-filter.js +12 -0
  52. package/dist/builtin/workflows/builtin/goal.js +16 -0
  53. package/dist/builtin/workflows/builtin/index.js +49 -0
  54. package/dist/builtin/workflows/builtin/loop-until-done.js +12 -0
  55. package/dist/builtin/workflows/builtin/open-claude-design.js +11 -0
  56. package/dist/builtin/workflows/builtin/ralph.js +16 -0
  57. package/dist/builtin/workflows/builtin/steering-context.d.ts +6 -0
  58. package/dist/builtin/workflows/builtin/steering-context.js +7 -0
  59. package/dist/builtin/workflows/builtin/tournament.js +13 -0
  60. package/dist/builtin/workflows/package.json +10 -7
  61. package/dist/builtin/workflows/src/authoring/typebox-defaults.d.ts +41 -0
  62. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1294 -430
  63. package/dist/builtin/workflows/src/{index.bundle.mjs → index.js} +1022 -429
  64. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +403 -0
  65. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +327 -0
  66. package/dist/builtin/workflows/src/shared/budget.d.ts +67 -0
  67. package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +60 -0
  68. package/dist/builtin/workflows/src/shared/workflow-heartbeat-contract.d.ts +21 -0
  69. package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
  70. package/dist/core/agent-session-custom-message-commit.js +12 -5
  71. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  72. package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
  73. package/dist/core/agent-session-persistent-custom-messages.js +2 -0
  74. package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
  75. package/dist/core/agent-session.d.ts.map +1 -1
  76. package/dist/core/agent-session.js +2 -1
  77. package/dist/core/agent-session.js.map +1 -1
  78. package/dist/core/auth-storage.d.ts +2 -0
  79. package/dist/core/auth-storage.d.ts.map +1 -1
  80. package/dist/core/auth-storage.js +4 -0
  81. package/dist/core/auth-storage.js.map +1 -1
  82. package/dist/core/builtin-install-layout.d.ts +1 -1
  83. package/dist/core/builtin-install-layout.d.ts.map +1 -1
  84. package/dist/core/builtin-install-layout.js +1 -1
  85. package/dist/core/builtin-install-layout.js.map +1 -1
  86. package/dist/core/codex-fast-mode.d.ts +10 -7
  87. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  88. package/dist/core/codex-fast-mode.js +31 -13
  89. package/dist/core/codex-fast-mode.js.map +1 -1
  90. package/dist/core/extensions/agent-events.d.ts +15 -0
  91. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  92. package/dist/core/extensions/agent-events.js.map +1 -1
  93. package/dist/core/extensions/api-types.d.ts +3 -1
  94. package/dist/core/extensions/api-types.d.ts.map +1 -1
  95. package/dist/core/extensions/api-types.js.map +1 -1
  96. package/dist/core/extensions/context-types.d.ts +35 -0
  97. package/dist/core/extensions/context-types.d.ts.map +1 -1
  98. package/dist/core/extensions/context-types.js.map +1 -1
  99. package/dist/core/extensions/event-types.d.ts +2 -2
  100. package/dist/core/extensions/event-types.d.ts.map +1 -1
  101. package/dist/core/extensions/event-types.js.map +1 -1
  102. package/dist/core/extensions/index.d.ts +1 -1
  103. package/dist/core/extensions/index.d.ts.map +1 -1
  104. package/dist/core/extensions/index.js.map +1 -1
  105. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  106. package/dist/core/extensions/loader-virtual-modules.js +6 -1
  107. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  108. package/dist/core/extensions/runner.d.ts +6 -0
  109. package/dist/core/extensions/runner.d.ts.map +1 -1
  110. package/dist/core/extensions/runner.js +65 -1
  111. package/dist/core/extensions/runner.js.map +1 -1
  112. package/dist/core/model-runtime.d.ts +2 -0
  113. package/dist/core/model-runtime.d.ts.map +1 -1
  114. package/dist/core/model-runtime.js +4 -0
  115. package/dist/core/model-runtime.js.map +1 -1
  116. package/dist/core/runtime-credentials.d.ts +1 -0
  117. package/dist/core/runtime-credentials.d.ts.map +1 -1
  118. package/dist/core/runtime-credentials.js +8 -0
  119. package/dist/core/runtime-credentials.js.map +1 -1
  120. package/dist/core/sdk.d.ts.map +1 -1
  121. package/dist/core/sdk.js +5 -5
  122. package/dist/core/sdk.js.map +1 -1
  123. package/dist/core/session-manager-storage.d.ts +2 -0
  124. package/dist/core/session-manager-storage.d.ts.map +1 -1
  125. package/dist/core/session-manager-storage.js +4 -2
  126. package/dist/core/session-manager-storage.js.map +1 -1
  127. package/dist/core/slash-commands.js +1 -1
  128. package/dist/core/slash-commands.js.map +1 -1
  129. package/dist/core/workflow-stage-admission.d.ts +6 -1
  130. package/dist/core/workflow-stage-admission.d.ts.map +1 -1
  131. package/dist/core/workflow-stage-admission.js +8 -9
  132. package/dist/core/workflow-stage-admission.js.map +1 -1
  133. package/dist/index-extensions.d.ts +1 -1
  134. package/dist/index-extensions.d.ts.map +1 -1
  135. package/dist/index-extensions.js.map +1 -1
  136. package/dist/index.d.ts +0 -1
  137. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/footer.js +1 -1
  139. package/dist/modes/interactive/components/footer.js.map +1 -1
  140. package/dist/modes/interactive/interactive-autocomplete.js +1 -1
  141. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  142. package/dist/modes/interactive/interactive-extension-runtime.js +1 -1
  143. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  144. package/dist/modes/interactive/interactive-startup.js +1 -1
  145. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  146. package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -0
  147. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  148. package/dist/modes/interactive-engine/isolated-runtime.js +69 -10
  149. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  150. package/dist/modes/rpc/rpc-client-api.d.ts +18 -2
  151. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  152. package/dist/modes/rpc/rpc-client-api.js +33 -5
  153. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  154. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  155. package/dist/modes/rpc/rpc-command-handler.js +8 -4
  156. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  157. package/dist/modes/rpc/rpc-types.d.ts +13 -0
  158. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  159. package/dist/modes/rpc/rpc-types.js.map +1 -1
  160. package/docs/extensions.md +19 -0
  161. package/docs/intercom.md +15 -6
  162. package/docs/packages.md +2 -2
  163. package/docs/providers.md +8 -3
  164. package/docs/quickstart.md +2 -2
  165. package/docs/rpc.md +21 -4
  166. package/docs/settings.md +6 -4
  167. package/docs/subagents.md +1 -1
  168. package/docs/usage.md +1 -1
  169. package/docs/workflows.md +108 -239
  170. package/npm-shrinkwrap.json +32 -32
  171. package/package.json +9 -13
  172. package/dist/builtin/workflows/ambient.d.ts +0 -61
  173. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +0 -26
  174. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +0 -391
  175. package/dist/builtin/workflows/builtin/adversarial-verification.ts +0 -34
  176. package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +0 -14
  177. package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +0 -108
  178. package/dist/builtin/workflows/builtin/classify-and-act.ts +0 -40
  179. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +0 -14
  180. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +0 -96
  181. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +0 -37
  182. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +0 -41
  183. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +0 -90
  184. package/dist/builtin/workflows/builtin/generate-and-filter.ts +0 -31
  185. package/dist/builtin/workflows/builtin/goal-artifacts.ts +0 -64
  186. package/dist/builtin/workflows/builtin/goal-convergence.ts +0 -87
  187. package/dist/builtin/workflows/builtin/goal-ledger.ts +0 -139
  188. package/dist/builtin/workflows/builtin/goal-models.ts +0 -72
  189. package/dist/builtin/workflows/builtin/goal-orchestrator-prompts.ts +0 -94
  190. package/dist/builtin/workflows/builtin/goal-prompts.ts +0 -217
  191. package/dist/builtin/workflows/builtin/goal-reducer.ts +0 -176
  192. package/dist/builtin/workflows/builtin/goal-reports.ts +0 -76
  193. package/dist/builtin/workflows/builtin/goal-reverify.ts +0 -305
  194. package/dist/builtin/workflows/builtin/goal-review.ts +0 -139
  195. package/dist/builtin/workflows/builtin/goal-runner.ts +0 -504
  196. package/dist/builtin/workflows/builtin/goal-schemas.ts +0 -89
  197. package/dist/builtin/workflows/builtin/goal-types.ts +0 -164
  198. package/dist/builtin/workflows/builtin/goal.ts +0 -78
  199. package/dist/builtin/workflows/builtin/index.ts +0 -16
  200. package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +0 -87
  201. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +0 -282
  202. package/dist/builtin/workflows/builtin/loop-until-done.ts +0 -51
  203. package/dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts +0 -305
  204. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +0 -337
  205. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +0 -347
  206. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +0 -313
  207. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +0 -311
  208. package/dist/builtin/workflows/builtin/open-claude-design.ts +0 -57
  209. package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +0 -28
  210. package/dist/builtin/workflows/builtin/progress-scoring.ts +0 -230
  211. package/dist/builtin/workflows/builtin/ralph-core.ts +0 -449
  212. package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +0 -100
  213. package/dist/builtin/workflows/builtin/ralph-models.ts +0 -183
  214. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +0 -103
  215. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +0 -104
  216. package/dist/builtin/workflows/builtin/ralph-runner.ts +0 -459
  217. package/dist/builtin/workflows/builtin/ralph.ts +0 -82
  218. package/dist/builtin/workflows/builtin/review-convergence.ts +0 -229
  219. package/dist/builtin/workflows/builtin/selection-math.ts +0 -156
  220. package/dist/builtin/workflows/builtin/steering-context.ts +0 -51
  221. package/dist/builtin/workflows/builtin/tournament-prompts.ts +0 -70
  222. package/dist/builtin/workflows/builtin/tournament-runner.ts +0 -400
  223. package/dist/builtin/workflows/builtin/tournament.ts +0 -73
  224. package/dist/builtin/workflows/builtin/verification-criteria.ts +0 -330
  225. package/dist/builtin/workflows/builtin/verification-prompts.ts +0 -206
  226. package/dist/builtin/workflows/builtin/verification-usage.ts +0 -44
@@ -3854,10 +3854,10 @@ function hasAssistantMessage(entries) {
3854
3854
  return entries.some((entry) => entry.type === "message" && entry.message.role === "assistant");
3855
3855
  }
3856
3856
  function persistAppendedEntry(filePath, entries, entry, flushed) {
3857
- if (!hasAssistantMessage(entries))
3858
- return false;
3859
3857
  if (flushed)
3860
3858
  appendSessionEntry(filePath, entry);
3859
+ else if (!hasAssistantMessage(entries))
3860
+ return false;
3861
3861
  else
3862
3862
  appendSessionEntries(filePath, entries);
3863
3863
  return true;
@@ -9925,6 +9925,8 @@ function appendDurableDisplayCard(session, message, delivery) {
9925
9925
  const card = { ...message, excludeFromContext: true };
9926
9926
  const admitted = message;
9927
9927
  const intentEntryId = session.sessionManager.appendCustomMessageEntry(card.customType, card.content, card.display, card.details, true, { delivery }, admitted.stageAdmissionKey);
9928
+ if (admitted.stageAdmissionKey !== undefined)
9929
+ session.sessionManager.flush();
9928
9930
  session.agent.state.messages.push(card);
9929
9931
  return { card, intentEntryId };
9930
9932
  }
@@ -10150,12 +10152,17 @@ var init_agent_session_persistent_custom_messages = __esm(() => {
10150
10152
  });
10151
10153
 
10152
10154
  // src/core/agent-session-custom-message-commit.ts
10155
+ function appendDurableStageAdmission(session, message) {
10156
+ session._appendCustomMessage(message);
10157
+ if (message.stageAdmissionKey !== undefined)
10158
+ session.sessionManager?.flush();
10159
+ }
10153
10160
  async function commitAdmittedCustomMessage(session, appMessage, options) {
10154
10161
  const owner = resolveWorkflowStageDeliveryTarget(session);
10155
10162
  if (owner !== session)
10156
10163
  return commitAdmittedCustomMessage(owner, appMessage, options);
10157
10164
  const self = session;
10158
- const useProtectedReconciliation = options?.persistWhenStreaming === true && options.triggerTurn === true && options.excludeFromContext !== true;
10165
+ const useProtectedReconciliation = options?.persistWhenStreaming === true && options.excludeFromContext !== true && (options.triggerTurn === true || options.stageAdmissionKey !== undefined);
10159
10166
  if (options?.deliverAs === "nextTurn") {
10160
10167
  self._pendingNextTurnMessages.push(appMessage);
10161
10168
  } else if (self._queuedMessagesPaused) {
@@ -10169,20 +10176,20 @@ async function commitAdmittedCustomMessage(session, appMessage, options) {
10169
10176
  } else if (self.isStreaming) {
10170
10177
  self._pendingCustomMessages.push(appMessage);
10171
10178
  } else {
10172
- self._appendCustomMessage(appMessage);
10179
+ appendDurableStageAdmission(self, appMessage);
10173
10180
  }
10174
10181
  } else if (options?.deliverAs === "interrupt" && options.triggerTurn) {
10175
10182
  const interrupt = self._enqueueInterruptCustomMessage(appMessage, options);
10176
10183
  self._workflowStageAdmission?.trackAdmittedWork(interrupt);
10177
10184
  interrupt.catch(() => {});
10178
10185
  } else if (self.isStreaming && options?.excludeFromContext === true && options.triggerTurn !== true && options.deliverAs === undefined) {
10179
- self._appendCustomMessage(appMessage);
10186
+ appendDurableStageAdmission(self, appMessage);
10180
10187
  } else if (self.isStreaming && options?.triggerTurn === false) {
10181
10188
  self._pendingCustomMessages.push(appMessage);
10182
10189
  } else if (self.isStreaming && useProtectedReconciliation) {
10183
10190
  await queueProtectedStreamingCustomMessage(self, appMessage, options?.deliverAs === "followUp" ? "followUp" : "steer");
10184
10191
  } else if (self.isStreaming && options?.persistWhenStreaming === true) {
10185
- self._appendCustomMessage(appMessage);
10192
+ appendDurableStageAdmission(self, appMessage);
10186
10193
  } else if (self.isStreaming && options?.triggerTurn !== false) {
10187
10194
  self._queueAgentMessage(appMessage, options?.deliverAs === "followUp" ? "followUp" : "steer");
10188
10195
  } else if (options?.triggerTurn) {
@@ -10205,7 +10212,7 @@ async function commitAdmittedCustomMessage(session, appMessage, options) {
10205
10212
  self._continueQueuedAgentMessages().catch(() => {});
10206
10213
  }
10207
10214
  } else {
10208
- self._appendCustomMessage(appMessage);
10215
+ appendDurableStageAdmission(self, appMessage);
10209
10216
  }
10210
10217
  }
10211
10218
  function _commitAdmittedCustomMessage(appMessage, options) {
@@ -12226,6 +12233,8 @@ class ExtensionRunner {
12226
12233
  shortcutDiagnostics = [];
12227
12234
  commandDiagnostics = [];
12228
12235
  staleMessage;
12236
+ uiPromptBinding = 0;
12237
+ activeUIPrompt;
12229
12238
  constructor(extensions, runtime, cwd, sessionManager, modelRegistry, orchestrationContext, subagentPolicy) {
12230
12239
  this.extensions = extensions;
12231
12240
  this.runtime = runtime;
@@ -12320,9 +12329,71 @@ class ExtensionRunner {
12320
12329
  this.reloadHandler = async () => {};
12321
12330
  }
12322
12331
  setUIContext(uiContext, mode = "print") {
12323
- this.uiContext = uiContext ?? noOpUIContext;
12332
+ this.endActiveUIPrompt();
12333
+ const binding = ++this.uiPromptBinding;
12334
+ this.uiContext = uiContext ? this.wrapUIPromptContext(uiContext, binding) : noOpUIContext;
12324
12335
  this.mode = mode;
12325
12336
  }
12337
+ wrapUIPromptContext(ui, binding) {
12338
+ return {
12339
+ ...ui,
12340
+ select: (title, options, opts) => this.withUIPrompt(binding, "select", title, () => ui.select(title, options, opts)),
12341
+ confirm: (title, message, opts) => this.withUIPrompt(binding, "confirm", title, () => ui.confirm(title, message, opts)),
12342
+ input: (title, placeholder, opts) => this.withUIPrompt(binding, "input", title, () => ui.input(title, placeholder, opts)),
12343
+ editor: (title, prefill, opts) => this.withUIPrompt(binding, "editor", title, () => ui.editor(title, prefill, opts)),
12344
+ custom: (factory, options) => this.withUIPrompt(binding, "custom", undefined, () => ui.custom(factory, options))
12345
+ };
12346
+ }
12347
+ withUIPrompt(binding, kind, title, run) {
12348
+ if (binding !== this.uiPromptBinding)
12349
+ return run();
12350
+ let prompt = this.activeUIPrompt;
12351
+ if (!prompt) {
12352
+ prompt = { depth: 0, kind, title };
12353
+ this.activeUIPrompt = prompt;
12354
+ this.emitUIPromptEvent({
12355
+ type: "ui_prompt_start",
12356
+ reason: "ui_prompt",
12357
+ kind,
12358
+ ...title === undefined ? {} : { title }
12359
+ });
12360
+ }
12361
+ prompt.depth += 1;
12362
+ let finished = false;
12363
+ const finish = () => {
12364
+ if (finished)
12365
+ return;
12366
+ finished = true;
12367
+ if (this.activeUIPrompt !== prompt)
12368
+ return;
12369
+ prompt.depth -= 1;
12370
+ if (prompt.depth === 0)
12371
+ this.endActiveUIPrompt(prompt);
12372
+ };
12373
+ try {
12374
+ return run().finally(finish);
12375
+ } catch (error) {
12376
+ finish();
12377
+ throw error;
12378
+ }
12379
+ }
12380
+ endActiveUIPrompt(prompt = this.activeUIPrompt) {
12381
+ if (!prompt || this.activeUIPrompt !== prompt)
12382
+ return;
12383
+ this.activeUIPrompt = undefined;
12384
+ prompt.depth = 0;
12385
+ this.emitUIPromptEvent({
12386
+ type: "ui_prompt_end",
12387
+ reason: "ui_prompt",
12388
+ kind: prompt.kind,
12389
+ ...prompt.title === undefined ? {} : { title: prompt.title }
12390
+ });
12391
+ }
12392
+ emitUIPromptEvent(event) {
12393
+ queueMicrotask(() => {
12394
+ this.emit(event);
12395
+ });
12396
+ }
12326
12397
  getUIContext() {
12327
12398
  return this.uiContext;
12328
12399
  }
@@ -21628,11 +21699,20 @@ function isCodexFastModeCandidateModelId(modelId) {
21628
21699
  const provider = modelId?.split("/", 1)[0];
21629
21700
  return provider !== undefined && isCodexFastModeSupportedProvider(provider);
21630
21701
  }
21631
- function isCodexFastModeSupportedModel(model) {
21632
- return isCodexFastModeSupportedProvider(model.provider) || model.api === "openai-codex-responses";
21702
+ function isGitHubCopilotModel(model) {
21703
+ return model.provider === "github-copilot";
21704
+ }
21705
+ function isGitHubCopilotFastModeSupportedModel(model, credential) {
21706
+ if (!isGitHubCopilotModel(model) || credential?.type !== "oauth")
21707
+ return false;
21708
+ const fastModelIds = credential.fastModelIds;
21709
+ return Array.isArray(fastModelIds) && fastModelIds.every((modelId) => typeof modelId === "string") && fastModelIds.includes(`${model.id}-fast`);
21633
21710
  }
21634
- function hasSupportedCodexFastModeModel(models) {
21635
- return models.some(isCodexFastModeSupportedModel);
21711
+ function isCodexFastModeSupportedModel(model, copilotCredential) {
21712
+ return isCodexFastModeSupportedProvider(model.provider) || model.api === "openai-codex-responses" || model.id !== undefined && isGitHubCopilotFastModeSupportedModel({ provider: model.provider, id: model.id }, copilotCredential);
21713
+ }
21714
+ function hasSupportedCodexFastModeModel(models, copilotCredential) {
21715
+ return models.some((model) => isCodexFastModeSupportedModel(model, copilotCredential));
21636
21716
  }
21637
21717
  function isWorkflowStageOrchestrationContext(context) {
21638
21718
  return context?.kind === "workflow-stage";
@@ -21643,11 +21723,11 @@ function getCodexFastModeScope(context) {
21643
21723
  function isCodexFastModeEnabledForScope(settings, scope) {
21644
21724
  return settings[scope];
21645
21725
  }
21646
- function shouldApplyCodexFastModeForScope(model, settings, scope) {
21647
- return isCodexFastModeSupportedModel(model) && isCodexFastModeEnabledForScope(settings, scope);
21726
+ function shouldApplyCodexFastModeForScope(model, settings, scope, copilotCredential) {
21727
+ return isCodexFastModeSupportedModel(model, copilotCredential) && isCodexFastModeEnabledForScope(settings, scope);
21648
21728
  }
21649
- function shouldApplyCodexFastMode(model, settings, context) {
21650
- return shouldApplyCodexFastModeForScope(model, settings, getCodexFastModeScope(context));
21729
+ function shouldApplyCodexFastMode(model, settings, context, copilotCredential) {
21730
+ return shouldApplyCodexFastModeForScope(model, settings, getCodexFastModeScope(context), copilotCredential);
21651
21731
  }
21652
21732
  function formatCodexFastModeModelLabel(modelName, enabled) {
21653
21733
  return enabled ? `${modelName} fast` : modelName;
@@ -21788,7 +21868,7 @@ class FooterComponent {
21788
21868
  pwd += ` • ${sessionName}`;
21789
21869
  const modelName = state.model?.id || "no-model";
21790
21870
  const fastModeSettings = this.session.settingsManager.getCodexFastModeSettings();
21791
- const fastModeEnabled = state.model ? shouldApplyCodexFastMode(state.model, fastModeSettings, this.session.orchestrationContext) : false;
21871
+ const fastModeEnabled = state.model ? shouldApplyCodexFastMode(state.model, fastModeSettings, this.session.orchestrationContext, this.session.modelRuntime.getCredentialSnapshot?.("github-copilot")) : false;
21792
21872
  let modelLabel2 = modelName;
21793
21873
  if (state.model?.reasoning) {
21794
21874
  const thinkingLevel = state.thinkingLevel || "off";
@@ -39432,14 +39512,18 @@ import { AsyncLocalStorage } from "node:async_hooks";
39432
39512
 
39433
39513
  class WorkflowStageAdmissionBoundary {
39434
39514
  open = true;
39435
- completed = new Set;
39515
+ completed;
39436
39516
  inFlight = new Map;
39437
39517
  pending = new Set;
39438
39518
  invocationContext = new AsyncLocalStorage;
39439
39519
  closePromise;
39440
39520
  drainAdmittedWork;
39441
- constructor(drainAdmittedWork = async () => {}) {
39442
- this.drainAdmittedWork = drainAdmittedWork;
39521
+ constructor(drainAdmittedWork = undefined, completedKeys = []) {
39522
+ this.drainAdmittedWork = drainAdmittedWork ?? (async () => {});
39523
+ this.completed = new Set(completedKeys);
39524
+ }
39525
+ static restore(entries, drainAdmittedWork) {
39526
+ return new WorkflowStageAdmissionBoundary(drainAdmittedWork, Array.from(entries).flatMap((entry) => entry.type === "custom_message" && typeof entry.stageAdmissionKey === "string" ? [entry.stageAdmissionKey] : []));
39443
39527
  }
39444
39528
  admit(key, deliver, routeLate) {
39445
39529
  if (key !== undefined) {
@@ -39678,7 +39762,7 @@ class AgentSessionBase {
39678
39762
  this._subagentPolicy = config.subagentPolicy;
39679
39763
  this._systemPromptTransform = config.systemPromptTransform;
39680
39764
  const stageContext = config.orchestrationContext?.kind === "workflow-stage" ? config.orchestrationContext : undefined;
39681
- this._workflowStageAdmission = stageContext?.messageAdmission?.boundary ?? (stageContext ? new WorkflowStageAdmissionBoundary : undefined);
39765
+ this._workflowStageAdmission = stageContext?.messageAdmission?.boundary ?? (stageContext ? WorkflowStageAdmissionBoundary.restore(this.sessionManager.getBranch()) : undefined);
39682
39766
  if (this._workflowStageAdmission && stageContext && stageContext.messageAdmission === undefined) {
39683
39767
  stageContext.messageAdmission = {
39684
39768
  boundary: this._workflowStageAdmission,
@@ -46657,6 +46741,31 @@ class RemoteQueuePause {
46657
46741
  var init_remote_queue_pause = () => {};
46658
46742
 
46659
46743
  // src/modes/interactive-engine/isolated-runtime.ts
46744
+ import { clampThinkingLevel as clampThinkingLevel5 } from "@bastani/pi-ai/compat";
46745
+ function applyPersistedModelDefault(session, model, alreadyInScope) {
46746
+ session.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
46747
+ if (alreadyInScope || session.scopedModels.length === 0)
46748
+ return;
46749
+ const enabledModels = session.settingsManager.getEnabledModels();
46750
+ if (!enabledModels?.length)
46751
+ return;
46752
+ const modelReference = `${model.provider}/${model.id}`;
46753
+ if (enabledModels.some((pattern) => pattern.toLowerCase() === modelReference.toLowerCase()))
46754
+ return;
46755
+ session.settingsManager.setEnabledModels([...enabledModels, modelReference]);
46756
+ }
46757
+ function thinkingPersistTarget(result) {
46758
+ if (!result.provider || !result.modelId)
46759
+ return;
46760
+ return { provider: result.provider, modelId: result.modelId };
46761
+ }
46762
+ function applyPersistedThinkingDefault(session, level, target) {
46763
+ if (target) {
46764
+ session.settingsManager.setModelThinkingLevel(target.provider, target.modelId, level);
46765
+ return;
46766
+ }
46767
+ session.settingsManager.setDefaultThinkingLevel(level);
46768
+ }
46660
46769
  var IsolatedInteractiveRuntime;
46661
46770
  var init_isolated_runtime = __esm(() => {
46662
46771
  init_agent_session_runtime();
@@ -46675,6 +46784,7 @@ var init_isolated_runtime = __esm(() => {
46675
46784
  steeringMessages = [];
46676
46785
  followUpMessages = [];
46677
46786
  queueUpdateGeneration = 0;
46787
+ thinkingEpoch = 0;
46678
46788
  pendingQueueClear;
46679
46789
  engineCallbackActive = false;
46680
46790
  queuePause;
@@ -47039,43 +47149,56 @@ var init_isolated_runtime = __esm(() => {
47039
47149
  },
47040
47150
  setModel: {
47041
47151
  configurable: true,
47042
- value: async (model) => {
47043
- const selected = await this.client.setModel(model.provider, model.id);
47044
- session.agent.state.model = session.modelRuntime.getModel(selected.provider, selected.id) ?? model;
47152
+ value: async (model, options) => {
47153
+ const selected = await this.client.setModel(model.provider, model.id, options);
47154
+ const nextModel = session.modelRuntime.getModel(selected.provider, selected.id) ?? model;
47155
+ session.agent.state.model = nextModel;
47045
47156
  this.resolveModelFallback();
47157
+ if (options?.persist === true)
47158
+ await this.syncPersistedModelCatalog(session, nextModel);
47046
47159
  }
47047
47160
  },
47048
47161
  setThinkingLevel: {
47049
47162
  configurable: true,
47050
- value: (level) => {
47051
- session.agent.state.thinkingLevel = level;
47052
- this.dispatchBestEffort("set thinking level", this.client.setThinkingLevel(level));
47163
+ value: (level, options) => {
47164
+ const availableLevels = session.getAvailableThinkingLevels();
47165
+ const effectiveLevel = availableLevels.includes(level) ? level : session.model ? clampThinkingLevel5(session.model, level) : "off";
47166
+ session.agent.state.thinkingLevel = effectiveLevel;
47167
+ const epoch = ++this.thinkingEpoch;
47168
+ this.dispatchBestEffort("set thinking level", this.client.setThinkingLevelAck(level, options).then((result) => {
47169
+ this.applyThinkingAck(session, epoch, result, options?.persist === true);
47170
+ }));
47053
47171
  }
47054
47172
  },
47055
47173
  cycleModel: {
47056
47174
  configurable: true,
47057
- value: async (direction) => {
47175
+ value: async (direction, options) => {
47058
47176
  const previousModel = session.model;
47059
- const result = await this.client.cycleModel(direction);
47177
+ const result = await this.client.cycleModel(direction, options);
47060
47178
  if (!result)
47061
47179
  return;
47062
47180
  const model = session.modelRuntime.getModel(result.model.provider, result.model.id) ?? result.model;
47063
47181
  session.agent.state.model = model;
47064
47182
  session.agent.state.thinkingLevel = result.thinkingLevel;
47065
47183
  this.resolveModelFallbackAfterExplicitModelSelection(previousModel, model);
47184
+ if (options?.persist === true)
47185
+ await this.syncPersistedModelCatalog(session, model);
47066
47186
  return { ...result, model };
47067
47187
  }
47068
47188
  },
47069
47189
  cycleThinkingLevel: {
47070
47190
  configurable: true,
47071
- value: () => {
47191
+ value: (options) => {
47072
47192
  const levels = session.getAvailableThinkingLevels();
47073
47193
  if (levels.length <= 1)
47074
47194
  return;
47075
47195
  const current = levels.indexOf(session.thinkingLevel);
47076
47196
  const level = levels[(current + 1) % levels.length];
47077
47197
  session.agent.state.thinkingLevel = level;
47078
- this.dispatchBestEffort("cycle thinking level", this.client.setThinkingLevel(level));
47198
+ const epoch = ++this.thinkingEpoch;
47199
+ this.dispatchBestEffort("cycle thinking level", this.client.setThinkingLevelAck(level, options).then((result) => {
47200
+ this.applyThinkingAck(session, epoch, result, options?.persist === true);
47201
+ }));
47079
47202
  return level;
47080
47203
  }
47081
47204
  },
@@ -47119,6 +47242,14 @@ var init_isolated_runtime = __esm(() => {
47119
47242
  this.engineCallbackActive = false;
47120
47243
  }
47121
47244
  }
47245
+ applyThinkingAck(session, epoch, result, persist) {
47246
+ if (persist) {
47247
+ applyPersistedThinkingDefault(session, result.level, thinkingPersistTarget(result));
47248
+ }
47249
+ if (epoch === this.thinkingEpoch) {
47250
+ session.agent.state.thinkingLevel = result.level;
47251
+ }
47252
+ }
47122
47253
  dispatchBestEffort(label, operation) {
47123
47254
  operation.catch((error) => {
47124
47255
  if (this.health.isRecovering())
@@ -47159,6 +47290,12 @@ var init_isolated_runtime = __esm(() => {
47159
47290
  }
47160
47291
  });
47161
47292
  }
47293
+ async syncPersistedModelCatalog(session, model) {
47294
+ const alreadyInScope = session.scopedModels.some((scoped) => scoped.model.provider === model.provider && scoped.model.id === model.id);
47295
+ const catalog = await this.client.requestInternal({ type: "get_available_models" });
47296
+ this.remoteModelCatalog.apply(catalog);
47297
+ applyPersistedModelDefault(session, model, alreadyInScope);
47298
+ }
47162
47299
  refreshSessionView() {
47163
47300
  const session = super.session;
47164
47301
  const sessionFile = session.sessionFile;
@@ -47198,6 +47335,7 @@ var init_isolated_runtime = __esm(() => {
47198
47335
  session.agent.state.model = event.model;
47199
47336
  break;
47200
47337
  case "thinking_level_changed":
47338
+ this.thinkingEpoch += 1;
47201
47339
  session.agent.state.thinkingLevel = event.level;
47202
47340
  break;
47203
47341
  case "session_info_changed":
@@ -48411,7 +48549,7 @@ var init_slash_commands = __esm(() => {
48411
48549
  { name: "tree", description: "Navigate session tree (switch branches)" },
48412
48550
  { name: "thinking", description: "Set thinking level", argumentHint: "<level>" },
48413
48551
  { name: "scoped-models", description: "Enable/disable models for ctrl+p cycling" },
48414
- { name: "fast", description: "Configure Codex fast mode for chat and workflows" },
48552
+ { name: "fast", description: "Configure OpenAI fast mode for chat and workflows in supported models" },
48415
48553
  { name: "export", description: "Export session (HTML default, or specify path: .html/.jsonl)" },
48416
48554
  { name: "import", description: "Import and resume a session from a JSONL file" },
48417
48555
  { name: "share", description: "Share session as a secret GitHub gist" },
@@ -49863,7 +50001,7 @@ var init_interactive_autocomplete = __esm(() => {
49863
50001
  return [...this.session.modelRuntime.getAvailableSnapshot()];
49864
50002
  };
49865
50003
  InteractiveModeBase.prototype.hasCodexFastModeSupportedModels = function() {
49866
- return hasSupportedCodexFastModeModel(this.getCodexFastModeCandidateModels());
50004
+ return hasSupportedCodexFastModeModel(this.getCodexFastModeCandidateModels(), this.session.modelRuntime.getCredentialSnapshot?.("github-copilot"));
49867
50005
  };
49868
50006
  InteractiveModeBase.prototype.buildRemoteSlashCommands = function(localCommands) {
49869
50007
  const remote = getInteractiveEngineRemoteCommands(this.runtimeHost);
@@ -50551,7 +50689,7 @@ var init_interactive_startup = __esm(() => {
50551
50689
  if (!model) {
50552
50690
  return modelLabel2;
50553
50691
  }
50554
- const fastModeEnabled = shouldApplyCodexFastMode(model, this.session.settingsManager.getCodexFastModeSettings(), this.session.orchestrationContext);
50692
+ const fastModeEnabled = shouldApplyCodexFastMode(model, this.session.settingsManager.getCodexFastModeSettings(), this.session.orchestrationContext, this.session.modelRuntime.getCredentialSnapshot?.("github-copilot"));
50555
50693
  return formatCodexFastModeModelLabel(modelLabel2, fastModeEnabled);
50556
50694
  };
50557
50695
  InteractiveModeBase.prototype.getStartupIdentityText = function(maxWidth, gap = 0, manifestoPhase = 4) {
@@ -51477,7 +51615,7 @@ var init_interactive_extension_runtime = __esm(() => {
51477
51615
  if (shortcuts.size === 0)
51478
51616
  return;
51479
51617
  const createContext = () => ({
51480
- ui: this.createExtensionUIContext(),
51618
+ ui: extensionRunner.getUIContext(),
51481
51619
  mode: "tui",
51482
51620
  hasUI: true,
51483
51621
  cwd: this.sessionManager.getCwd(),
@@ -55066,7 +55204,7 @@ var init_interactive_selectors = __esm(() => {
55066
55204
  });
55067
55205
 
55068
55206
  // src/modes/interactive/interactive-model-routing.ts
55069
- import { clampThinkingLevel as clampThinkingLevel5 } from "@bastani/pi-ai/compat";
55207
+ import { clampThinkingLevel as clampThinkingLevel6 } from "@bastani/pi-ai/compat";
55070
55208
  function resolveThinkingSelectorDefault(rawDefault, availableLevels, model) {
55071
55209
  if (rawDefault === undefined)
55072
55210
  return;
@@ -55074,7 +55212,7 @@ function resolveThinkingSelectorDefault(rawDefault, availableLevels, model) {
55074
55212
  return rawDefault;
55075
55213
  if (!model)
55076
55214
  return availableLevels.includes("off") ? "off" : availableLevels[0];
55077
- const clamped = clampThinkingLevel5(model, rawDefault);
55215
+ const clamped = clampThinkingLevel6(model, rawDefault);
55078
55216
  if (availableLevels.includes(clamped))
55079
55217
  return clamped;
55080
55218
  return availableLevels.includes("off") ? "off" : availableLevels[0];
@@ -57931,6 +58069,152 @@ function buildStagePromptAdapter(id, kind, args, createdAt) {
57931
58069
  // dist/builtin/workflows/src/shared/stage-ui-broker.ts
57932
58070
  import { randomUUID as randomUUID7 } from "node:crypto";
57933
58071
 
58072
+ // dist/builtin/workflows/src/shared/pending-stage-delivery.ts
58073
+ var PENDING_STAGE_MESSAGE_LIMIT = 50;
58074
+ var PENDING_STAGE_UNDELIVERABLE_NOTIFICATION_PREFIX = "atomic-pending-stage-undeliverable";
58075
+ function queueStageMessage(messages2, input2, senderGroup, runGroup, stageIdentity) {
58076
+ if (normalizeDeliveryGroup(senderGroup) !== normalizeDeliveryGroup(runGroup)) {
58077
+ return { ok: false, reason: "group_mismatch", runId: input2.runId, stageKey: input2.stageKey };
58078
+ }
58079
+ const messageId = input2.message.id;
58080
+ const queued = pendingStageMessagesFor(messages2, input2.runId, input2.stageKey, stageIdentity);
58081
+ const existing = messages2.find((entry2) => entry2.runId === input2.runId && entry2.id === messageId);
58082
+ if (existing !== undefined) {
58083
+ if (pendingStageMessageSignature(existing, stageIdentity) !== pendingStageMessageSignature(input2, stageIdentity)) {
58084
+ return {
58085
+ ok: false,
58086
+ reason: "message_id_conflict",
58087
+ runId: input2.runId,
58088
+ stageKey: input2.stageKey,
58089
+ messageId
58090
+ };
58091
+ }
58092
+ const queuedPosition = queued.indexOf(existing);
58093
+ return {
58094
+ ok: true,
58095
+ messages: messages2,
58096
+ entry: existing,
58097
+ ...queuedPosition >= 0 ? { position: queuedPosition + 1 } : {},
58098
+ deduplicated: true
58099
+ };
58100
+ }
58101
+ if (queued.length >= PENDING_STAGE_MESSAGE_LIMIT) {
58102
+ return {
58103
+ ok: false,
58104
+ reason: "capacity",
58105
+ limit: PENDING_STAGE_MESSAGE_LIMIT,
58106
+ runId: input2.runId,
58107
+ stageKey: input2.stageKey
58108
+ };
58109
+ }
58110
+ const entry = {
58111
+ ...input2,
58112
+ id: messageId,
58113
+ ...stageIdentity !== undefined ? { stageId: stageIdentity.id } : {},
58114
+ ...stageIdentity?.replayKey !== undefined ? { stageReplayKey: stageIdentity.replayKey } : {},
58115
+ admissionOrder: nextAdmissionOrder(messages2, input2.runId),
58116
+ status: "queued"
58117
+ };
58118
+ return {
58119
+ ok: true,
58120
+ messages: [...messages2, entry],
58121
+ entry,
58122
+ position: queued.length + 1,
58123
+ deduplicated: false
58124
+ };
58125
+ }
58126
+ function pendingStageMessagesFor(messages2, runId, stageKey, stageIdentity) {
58127
+ return messages2.map((entry, index) => ({ entry, index })).filter(({ entry }) => matchesPendingStage(entry, runId, stageKey, stageIdentity) && entry.status === "queued").sort((left, right) => (left.entry.admissionOrder ?? left.index + 1) - (right.entry.admissionOrder ?? right.index + 1) || left.index - right.index).map(({ entry }) => entry);
58128
+ }
58129
+ function markPendingStageMessageDelivered(messages2, runId, stageKey, messageId, deliveredAt, stageIdentity) {
58130
+ return updateQueuedPendingStageMessage(messages2, runId, stageKey, messageId, stageIdentity, (entry) => ({
58131
+ ...entry,
58132
+ status: "delivered",
58133
+ deliveredAt
58134
+ }));
58135
+ }
58136
+ function markPendingStageMessageUndeliverable(messages2, runId, stageKey, messageId, reason, stageIdentity) {
58137
+ return updateQueuedPendingStageMessage(messages2, runId, stageKey, messageId, stageIdentity, (entry) => ({
58138
+ ...entry,
58139
+ status: "undeliverable",
58140
+ undeliverableReason: reason,
58141
+ undeliverableNotificationId: pendingStageUndeliverableNotificationId(entry)
58142
+ }));
58143
+ }
58144
+ function markPendingStageMessageUndeliverableNotified(messages2, runId, stageKey, messageId, notificationId, notifiedAt) {
58145
+ const index = messages2.findIndex((entry) => matchesPendingStage(entry, runId, stageKey) && entry.id === messageId && entry.status === "undeliverable" && entry.undeliverableNotificationId === notificationId && entry.undeliverableNotifiedAt === undefined);
58146
+ if (index < 0)
58147
+ return messages2;
58148
+ const next = [...messages2];
58149
+ next[index] = { ...next[index], undeliverableNotifiedAt: notifiedAt };
58150
+ return next;
58151
+ }
58152
+ function pendingStageUndeliverableNotificationId(entry) {
58153
+ return [
58154
+ PENDING_STAGE_UNDELIVERABLE_NOTIFICATION_PREFIX,
58155
+ encodeURIComponent(entry.runId),
58156
+ encodeURIComponent(entry.stageKey),
58157
+ encodeURIComponent(entry.id)
58158
+ ].join(":");
58159
+ }
58160
+ function updateQueuedPendingStageMessage(messages2, runId, stageKey, messageId, stageIdentity, update2) {
58161
+ const index = messages2.findIndex((entry) => matchesPendingStage(entry, runId, stageKey, stageIdentity) && entry.id === messageId && entry.status === "queued");
58162
+ if (index < 0)
58163
+ return messages2;
58164
+ const next = [...messages2];
58165
+ next[index] = update2(next[index]);
58166
+ return next;
58167
+ }
58168
+ function matchesPendingStage(entry, runId, stageKey, stageIdentity) {
58169
+ if (entry.runId !== runId)
58170
+ return false;
58171
+ if (stageIdentity === undefined)
58172
+ return entry.stageKey === stageKey;
58173
+ return entry.stageId === stageIdentity.id || entry.stageReplayKey !== undefined && entry.stageReplayKey === stageIdentity.replayKey || entry.stageId === undefined && stageIdentity.aliases.includes(entry.stageKey);
58174
+ }
58175
+ function nextAdmissionOrder(messages2, runId) {
58176
+ let greatest = 0;
58177
+ let legacyPosition = 0;
58178
+ for (const entry of messages2) {
58179
+ if (entry.runId !== runId)
58180
+ continue;
58181
+ legacyPosition += 1;
58182
+ greatest = Math.max(greatest, entry.admissionOrder ?? legacyPosition);
58183
+ }
58184
+ return greatest + 1;
58185
+ }
58186
+ function pendingStageMessageSignature(entry, stageIdentity) {
58187
+ const storedTarget = "status" in entry ? entry.stageReplayKey ?? entry.stageId : undefined;
58188
+ const { timestamp: transportTimestamp, ...logicalMessage } = entry.message;
58189
+ return stableJson({
58190
+ target: storedTarget ?? stageIdentity?.replayKey ?? stageIdentity?.id ?? entry.stageKey,
58191
+ sender: entry.senderReturnAddress ?? entry.from.id,
58192
+ message: {
58193
+ ...logicalMessage,
58194
+ expectsReply: logicalMessage.expectsReply ?? false,
58195
+ content: {
58196
+ ...logicalMessage.content,
58197
+ attachments: logicalMessage.content.attachments ?? []
58198
+ }
58199
+ }
58200
+ });
58201
+ }
58202
+ function stableJson(value) {
58203
+ return JSON.stringify(sortJsonValue(value));
58204
+ }
58205
+ function sortJsonValue(value) {
58206
+ if (Array.isArray(value))
58207
+ return value.map(sortJsonValue);
58208
+ if (typeof value !== "object" || value === null)
58209
+ return value;
58210
+ return Object.fromEntries(Object.entries(value).filter(([, nested]) => nested !== undefined).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortJsonValue(nested)]));
58211
+ }
58212
+ function normalizeDeliveryGroup(value) {
58213
+ if (typeof value !== "string")
58214
+ return "default";
58215
+ const trimmed = value.trim();
58216
+ return trimmed.length > 0 ? trimmed : "default";
58217
+ }
57934
58218
  // dist/builtin/workflows/src/shared/flat-string.ts
57935
58219
  function flattenTruncatedString(value) {
57936
58220
  return value.split("").join("");
@@ -58238,6 +58522,7 @@ function compactStage(stage) {
58238
58522
  inputRequest,
58239
58523
  notices,
58240
58524
  mcpScope: _mcpScope,
58525
+ pendingStageDeliveryAvailable: _pendingStageDeliveryAvailable,
58241
58526
  attemptedModels: _attemptedModels,
58242
58527
  modelAttempts: _modelAttempts,
58243
58528
  result: _result,
@@ -58493,6 +58778,133 @@ function createStoreContext(state = createStoreState()) {
58493
58778
  };
58494
58779
  }
58495
58780
 
58781
+ // dist/builtin/workflows/src/shared/store-pending-stage-delivery-methods.ts
58782
+ function createPendingStageDeliveryStoreMethods(context) {
58783
+ const transitions = new Map;
58784
+ const serialize = async (runId, transition) => {
58785
+ const previous2 = transitions.get(runId) ?? Promise.resolve();
58786
+ const result = previous2.catch(() => {
58787
+ return;
58788
+ }).then(transition);
58789
+ const settled = result.then(() => {
58790
+ return;
58791
+ }, () => {
58792
+ return;
58793
+ });
58794
+ transitions.set(runId, settled);
58795
+ settled.finally(() => {
58796
+ if (transitions.get(runId) === settled)
58797
+ transitions.delete(runId);
58798
+ });
58799
+ return await result;
58800
+ };
58801
+ return {
58802
+ async queueStageMessage(input2, senderGroup, runGroup, backend) {
58803
+ return await serialize(input2.runId, async () => {
58804
+ const run = context.findRun(input2.runId);
58805
+ if (run === undefined)
58806
+ return;
58807
+ const stageIdentity = resolvePendingStageIdentity(run, input2.stageKey);
58808
+ const result = queueStageMessage(run.pendingStageMessages ?? [], input2, senderGroup, runGroup, stageIdentity);
58809
+ if (result.ok && !result.deduplicated) {
58810
+ await persistTransition(backend, input2.runId, result.messages);
58811
+ run.pendingStageMessages = [...result.messages];
58812
+ context.bumpAndNotify();
58813
+ }
58814
+ return result;
58815
+ });
58816
+ },
58817
+ async validateLiveStageMessage(input2) {
58818
+ return await serialize(input2.runId, async () => {
58819
+ const run = context.findRun(input2.runId);
58820
+ if (run === undefined)
58821
+ return;
58822
+ const result = queueStageMessage(run.pendingStageMessages ?? [], input2, undefined, undefined, resolvePendingStageIdentity(run, input2.stageKey));
58823
+ if (!result.ok) {
58824
+ return result.reason === "message_id_conflict" ? { outcome: "message_id_conflict", messageId: result.messageId } : { outcome: "forward" };
58825
+ }
58826
+ if (!result.deduplicated)
58827
+ return { outcome: "forward" };
58828
+ if (result.entry.status === "delivered")
58829
+ return { outcome: "delivered" };
58830
+ if (result.entry.status === "undeliverable") {
58831
+ return { outcome: "undeliverable", reason: result.entry.undeliverableReason };
58832
+ }
58833
+ if (result.position === undefined) {
58834
+ throw new Error(`atomic-workflows: queued message ${input2.message.id} has no active position`);
58835
+ }
58836
+ return { outcome: "queued", position: result.position };
58837
+ });
58838
+ },
58839
+ pendingStageMessagesFor(runId, stageKey) {
58840
+ const run = context.findRun(runId);
58841
+ return pendingStageMessagesFor(run?.pendingStageMessages ?? [], runId, stageKey, run === undefined ? undefined : resolvePendingStageIdentity(run, stageKey));
58842
+ },
58843
+ async markPendingStageMessageDelivered(runId, stageKey, messageId, deliveredAt, backend) {
58844
+ return await serialize(runId, async () => {
58845
+ const run = context.findRun(runId);
58846
+ if (run === undefined)
58847
+ return false;
58848
+ const current = run.pendingStageMessages ?? [];
58849
+ const next = markPendingStageMessageDelivered(current, runId, stageKey, messageId, deliveredAt, resolvePendingStageIdentity(run, stageKey));
58850
+ if (next === current)
58851
+ return false;
58852
+ await persistTransition(backend, runId, next);
58853
+ run.pendingStageMessages = [...next];
58854
+ context.bumpAndNotify();
58855
+ return true;
58856
+ });
58857
+ },
58858
+ async markPendingStageMessageUndeliverable(runId, stageKey, messageId, reason, backend) {
58859
+ return await serialize(runId, async () => {
58860
+ const run = context.findRun(runId);
58861
+ if (run === undefined)
58862
+ return false;
58863
+ const current = run.pendingStageMessages ?? [];
58864
+ const next = markPendingStageMessageUndeliverable(current, runId, stageKey, messageId, reason, resolvePendingStageIdentity(run, stageKey));
58865
+ if (next === current)
58866
+ return false;
58867
+ await persistTransition(backend, runId, next);
58868
+ run.pendingStageMessages = [...next];
58869
+ context.bumpAndNotify();
58870
+ return true;
58871
+ });
58872
+ },
58873
+ async markPendingStageMessageUndeliverableNotified(runId, stageKey, messageId, notificationId, notifiedAt, backend) {
58874
+ return await serialize(runId, async () => {
58875
+ const run = context.findRun(runId);
58876
+ if (run === undefined)
58877
+ return false;
58878
+ const current = run.pendingStageMessages ?? [];
58879
+ const next = markPendingStageMessageUndeliverableNotified(current, runId, stageKey, messageId, notificationId, notifiedAt);
58880
+ if (next === current)
58881
+ return false;
58882
+ await persistTransition(backend, runId, next);
58883
+ run.pendingStageMessages = [...next];
58884
+ context.bumpAndNotify();
58885
+ return true;
58886
+ });
58887
+ }
58888
+ };
58889
+ }
58890
+ function resolvePendingStageIdentity(run, stageKey) {
58891
+ const exactIds = run.stages.filter((stage2) => stage2.id === stageKey);
58892
+ const candidates = exactIds.length > 0 ? exactIds : run.stages.filter((stage2) => stage2.name === stageKey);
58893
+ if (candidates.length !== 1)
58894
+ return;
58895
+ const stage = candidates[0];
58896
+ return {
58897
+ id: stage.id,
58898
+ ...stage.replayKey !== undefined ? { replayKey: stage.replayKey } : {},
58899
+ aliases: stage.id === stage.name ? [stage.id] : [stage.id, stage.name]
58900
+ };
58901
+ }
58902
+ async function persistTransition(backend, runId, messages2) {
58903
+ if (!await backend.persistPendingStageMessages(runId, messages2)) {
58904
+ throw new Error(`atomic-workflows: durable workflow ${runId} is unavailable for pending-stage persistence`);
58905
+ }
58906
+ }
58907
+
58496
58908
  // dist/builtin/workflows/src/shared/store-prompt-methods.ts
58497
58909
  function createPromptStoreMethods(context) {
58498
58910
  const { state } = context;
@@ -59407,6 +59819,7 @@ function createStore() {
59407
59819
  const context = createStoreContext();
59408
59820
  return {
59409
59821
  ...createRunStoreMethods(context),
59822
+ ...createPendingStageDeliveryStoreMethods(context),
59410
59823
  ...createStageStoreMethods(context),
59411
59824
  ...createToolNodeStoreMethods(context),
59412
59825
  ...createPromptStoreMethods(context)
@@ -60148,6 +60561,381 @@ ${formatValidationErrors(errors)}`);
60148
60561
  }
60149
60562
  return resolved;
60150
60563
  }
60564
+ // dist/builtin/workflows/src/shared/workflow-failures-signals.ts
60565
+ function asRecord2(value) {
60566
+ return value !== null && typeof value === "object" ? value : undefined;
60567
+ }
60568
+ function field2(value, key2) {
60569
+ return asRecord2(value)?.[key2];
60570
+ }
60571
+ function safeField(value, key2) {
60572
+ try {
60573
+ return field2(value, key2);
60574
+ } catch {
60575
+ return;
60576
+ }
60577
+ }
60578
+ function nonZeroExitCode(value) {
60579
+ if (typeof value === "number")
60580
+ return Number.isFinite(value) && value !== 0;
60581
+ if (typeof value !== "string")
60582
+ return false;
60583
+ const parsed = Number(value.trim());
60584
+ return Number.isFinite(parsed) && parsed !== 0;
60585
+ }
60586
+ function nonEmptyProcessOutput(value) {
60587
+ if (typeof value === "string")
60588
+ return value.length > 0;
60589
+ if (value instanceof ArrayBuffer)
60590
+ return value.byteLength > 0;
60591
+ return ArrayBuffer.isView(value) && value.byteLength > 0;
60592
+ }
60593
+ function findProcessFailureError(value, seen, depth) {
60594
+ if (value === null || typeof value !== "object" || depth >= 8 || seen.has(value))
60595
+ return;
60596
+ seen.add(value);
60597
+ if (nonZeroExitCode(safeField(value, "exitCode")))
60598
+ return value;
60599
+ if (nonEmptyProcessOutput(safeField(value, "stdout")))
60600
+ return value;
60601
+ if (nonEmptyProcessOutput(safeField(value, "stderr")))
60602
+ return value;
60603
+ for (const key2 of ["cause", "error", "response", "body"]) {
60604
+ const selected = findProcessFailureError(safeField(value, key2), seen, depth + 1);
60605
+ if (selected !== undefined)
60606
+ return selected;
60607
+ }
60608
+ const diagnostics = safeField(value, "diagnostics");
60609
+ if (Array.isArray(diagnostics)) {
60610
+ for (const diagnostic of diagnostics) {
60611
+ const selected = findProcessFailureError(safeField(diagnostic, "error") ?? diagnostic, seen, depth + 1);
60612
+ if (selected !== undefined)
60613
+ return selected;
60614
+ }
60615
+ }
60616
+ const errors = safeField(value, "errors");
60617
+ if (!Array.isArray(errors))
60618
+ return;
60619
+ for (const error of errors) {
60620
+ const selected = findProcessFailureError(error, seen, depth + 1);
60621
+ if (selected !== undefined)
60622
+ return selected;
60623
+ }
60624
+ return;
60625
+ }
60626
+ function selectProcessFailureError(error) {
60627
+ return findProcessFailureError(error, new Set, 0) ?? error;
60628
+ }
60629
+ function hasProcessFailureEvidence(error) {
60630
+ return findProcessFailureError(error, new Set, 0) !== undefined;
60631
+ }
60632
+ function stringField4(value, key2) {
60633
+ const raw = field2(value, key2);
60634
+ return typeof raw === "string" && raw.length > 0 ? raw : undefined;
60635
+ }
60636
+ function errorMessage3(error) {
60637
+ const structuredMessage = structuredErrorMessage(error);
60638
+ if (structuredMessage !== undefined)
60639
+ return structuredMessage;
60640
+ if (error instanceof Error && typeof error.message === "string")
60641
+ return error.message;
60642
+ if (typeof error === "string")
60643
+ return error;
60644
+ return String(error);
60645
+ }
60646
+ function errorName2(error) {
60647
+ return error instanceof Error ? error.name : stringField4(error, "name");
60648
+ }
60649
+ function structuredErrorMessage(error) {
60650
+ return stringField4(error, "errorMessage") ?? stringField4(error, "message") ?? stringField4(error, "statusText");
60651
+ }
60652
+ function integerFrom2(value) {
60653
+ if (typeof value === "number" && Number.isInteger(value))
60654
+ return value;
60655
+ if (typeof value !== "string" || value.trim().length === 0)
60656
+ return;
60657
+ const parsed = Number(value.trim());
60658
+ return Number.isInteger(parsed) ? parsed : undefined;
60659
+ }
60660
+ function numberFrom(value) {
60661
+ if (typeof value === "number" && Number.isFinite(value))
60662
+ return value;
60663
+ if (typeof value !== "string" || value.trim().length === 0)
60664
+ return;
60665
+ const parsed = Number(value.trim());
60666
+ return Number.isFinite(parsed) ? parsed : undefined;
60667
+ }
60668
+ function retryAfterHeaderMs(value) {
60669
+ const numeric = numberFrom(value);
60670
+ if (numeric !== undefined && numeric >= 0)
60671
+ return Math.round(numeric * 1000);
60672
+ if (typeof value !== "string" || value.trim().length === 0)
60673
+ return;
60674
+ const dateMs = Date.parse(value);
60675
+ if (!Number.isFinite(dateMs))
60676
+ return;
60677
+ return Math.max(0, dateMs - Date.now());
60678
+ }
60679
+ function retryAfterMsFrom(error) {
60680
+ const directMs = numberFrom(field2(error, "retryAfterMs"));
60681
+ if (directMs !== undefined && directMs >= 0)
60682
+ return Math.round(directMs);
60683
+ const seconds = numberFrom(field2(error, "retryAfterSeconds"));
60684
+ if (seconds !== undefined && seconds >= 0)
60685
+ return Math.round(seconds * 1000);
60686
+ const retryAfter = retryAfterHeaderMs(field2(error, "retryAfter"));
60687
+ if (retryAfter !== undefined)
60688
+ return retryAfter;
60689
+ const retryAfterHeader = retryAfterHeaderMs(field2(error, "retry-after"));
60690
+ if (retryAfterHeader !== undefined)
60691
+ return retryAfterHeader;
60692
+ const headers = field2(error, "headers");
60693
+ const headerRecord = asRecord2(headers);
60694
+ const headerValue = headerRecord?.["retry-after"] ?? headerRecord?.["Retry-After"];
60695
+ return retryAfterHeaderMs(headerValue);
60696
+ }
60697
+ function structuredSignal2(error) {
60698
+ const status = integerFrom2(field2(error, "status")) ?? integerFrom2(field2(error, "statusCode")) ?? integerFrom2(field2(error, "httpStatus"));
60699
+ const rawCode = field2(error, "code");
60700
+ const code = typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : undefined;
60701
+ const name = errorName2(error);
60702
+ const stopReason = stringField4(error, "stopReason");
60703
+ const message = structuredErrorMessage(error);
60704
+ const retryAfterMs = retryAfterMsFrom(error);
60705
+ return {
60706
+ ...status !== undefined ? { status } : {},
60707
+ ...code !== undefined ? { code } : {},
60708
+ ...name !== undefined ? { name } : {},
60709
+ ...stopReason !== undefined ? { stopReason } : {},
60710
+ ...message !== undefined ? { message } : {},
60711
+ ...retryAfterMs !== undefined ? { retryAfterMs } : {}
60712
+ };
60713
+ }
60714
+ function causeOf2(error) {
60715
+ if (error instanceof Error)
60716
+ return error.cause;
60717
+ return field2(error, "cause");
60718
+ }
60719
+ function diagnosticErrors2(error) {
60720
+ const diagnostics = field2(error, "diagnostics");
60721
+ if (!Array.isArray(diagnostics))
60722
+ return [];
60723
+ const errors = [];
60724
+ for (const diagnostic of diagnostics) {
60725
+ const diagnosticError = field2(diagnostic, "error");
60726
+ errors.push(diagnosticError ?? diagnostic);
60727
+ }
60728
+ return errors;
60729
+ }
60730
+ function nestedProviderError(error) {
60731
+ return field2(error, "error") ?? field2(error, "response") ?? field2(error, "body");
60732
+ }
60733
+ function normalizeCode2(value) {
60734
+ if (value === undefined)
60735
+ return;
60736
+ return String(value).trim().toLowerCase().replaceAll("-", "_").replaceAll(" ", "_");
60737
+ }
60738
+ function httpStatusFromCode(value) {
60739
+ if (value === undefined)
60740
+ return;
60741
+ if (typeof value === "number") {
60742
+ return Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
60743
+ }
60744
+ const trimmed = value.trim();
60745
+ if (!/^\d{3}$/.test(trimmed))
60746
+ return;
60747
+ const parsed = Number(trimmed);
60748
+ return parsed >= 100 && parsed <= 599 ? parsed : undefined;
60749
+ }
60750
+ function codeEvidenceFrom(value) {
60751
+ const status = httpStatusFromCode(value);
60752
+ if (status !== undefined)
60753
+ return { kind: "wrapper_http_status", status };
60754
+ const normalized = normalizeCode2(value);
60755
+ return normalized !== undefined && normalized.length > 0 ? { kind: "semantic_code", normalized } : undefined;
60756
+ }
60757
+ function tokenize(value) {
60758
+ const tokens = [];
60759
+ let current = "";
60760
+ for (const char of value.toLowerCase()) {
60761
+ if (char >= "a" && char <= "z" || char >= "0" && char <= "9") {
60762
+ current += char;
60763
+ } else if (current.length > 0) {
60764
+ tokens.push(current);
60765
+ current = "";
60766
+ }
60767
+ }
60768
+ if (current.length > 0)
60769
+ tokens.push(current);
60770
+ return tokens;
60771
+ }
60772
+ function hasPhrase(tokens, phrase) {
60773
+ if (phrase.length === 0 || phrase.length > tokens.length)
60774
+ return false;
60775
+ for (let index = 0;index <= tokens.length - phrase.length; index += 1) {
60776
+ let matched = true;
60777
+ for (let offset = 0;offset < phrase.length; offset += 1) {
60778
+ if (tokens[index + offset] !== phrase[offset]) {
60779
+ matched = false;
60780
+ break;
60781
+ }
60782
+ }
60783
+ if (matched)
60784
+ return true;
60785
+ }
60786
+ return false;
60787
+ }
60788
+ function hasAnyPhrase(tokens, phrases) {
60789
+ return phrases.some((phrase) => hasPhrase(tokens, phrase));
60790
+ }
60791
+ function tokenNearAny(tokens, anchor, candidates, distance) {
60792
+ for (let index = 0;index < tokens.length; index += 1) {
60793
+ if (tokens[index] !== anchor)
60794
+ continue;
60795
+ const start = Math.max(0, index - distance);
60796
+ const end = Math.min(tokens.length - 1, index + distance);
60797
+ for (let cursor = start;cursor <= end; cursor += 1) {
60798
+ if (cursor !== index && candidates.has(tokens[cursor]))
60799
+ return true;
60800
+ }
60801
+ }
60802
+ return false;
60803
+ }
60804
+ function redactedSecretReplacement(prefix) {
60805
+ return `${prefix}[redacted]`;
60806
+ }
60807
+ function redactSensitiveText(value) {
60808
+ return value.replace(/(sk-[A-Za-z0-9_-]{8})[A-Za-z0-9_-]+/g, redactedSecretReplacement("$1")).replace(/\b(authorization\s*:\s*bearer\s+)[^\s,;]+/gi, "$1[redacted]").replace(/\b(bearer\s+)[A-Za-z0-9._~+/-]{8,}=*/gi, "$1[redacted]").replace(/((?:api[_-]?key|token|credential|secret)\s*[:=]\s*)[^\s,;]+/gi, "$1[redacted]");
60809
+ }
60810
+
60811
+ // dist/builtin/workflows/src/durable/tool-outcome.ts
60812
+ var TOOL_FAILURE_TEXT_LIMIT_BYTES = 16384;
60813
+ var TRUNCATION_PREFIX = `[workflow tool output truncated; showing final bytes]
60814
+ `;
60815
+ function safeField2(error, key2) {
60816
+ try {
60817
+ return field2(error, key2);
60818
+ } catch {
60819
+ return;
60820
+ }
60821
+ }
60822
+ function exposedText(error, key2) {
60823
+ const value = safeField2(error, key2);
60824
+ if (typeof value === "string")
60825
+ return value;
60826
+ try {
60827
+ if (value instanceof ArrayBuffer)
60828
+ return new TextDecoder().decode(value);
60829
+ if (ArrayBuffer.isView(value)) {
60830
+ return new TextDecoder().decode(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
60831
+ }
60832
+ } catch {
60833
+ return;
60834
+ }
60835
+ return;
60836
+ }
60837
+ function boundedSafeToolFailureText(value) {
60838
+ const redacted = redactSensitiveText(value);
60839
+ const bytes = new TextEncoder().encode(redacted);
60840
+ if (bytes.byteLength <= TOOL_FAILURE_TEXT_LIMIT_BYTES)
60841
+ return redacted;
60842
+ const prefix = new TextEncoder().encode(TRUNCATION_PREFIX);
60843
+ const tailLength = Math.max(0, TOOL_FAILURE_TEXT_LIMIT_BYTES - prefix.byteLength);
60844
+ let start = bytes.byteLength - tailLength;
60845
+ const decoder = new TextDecoder("utf-8", { fatal: true });
60846
+ while (start < bytes.byteLength) {
60847
+ try {
60848
+ return TRUNCATION_PREFIX + decoder.decode(bytes.slice(start));
60849
+ } catch {
60850
+ start += 1;
60851
+ }
60852
+ }
60853
+ return TRUNCATION_PREFIX.slice(0, TOOL_FAILURE_TEXT_LIMIT_BYTES);
60854
+ }
60855
+ function safeErrorText(error) {
60856
+ try {
60857
+ return String(error);
60858
+ } catch {
60859
+ return "Tool callback failed";
60860
+ }
60861
+ }
60862
+ function normalizeWorkflowToolError(error) {
60863
+ error = selectProcessFailureError(error);
60864
+ const exitCode = safeField2(error, "exitCode");
60865
+ const stdout = exposedText(error, "stdout");
60866
+ const stderr = exposedText(error, "stderr");
60867
+ let message;
60868
+ let name;
60869
+ try {
60870
+ message = errorMessage3(error);
60871
+ } catch {
60872
+ message = safeErrorText(error);
60873
+ }
60874
+ try {
60875
+ name = errorName2(error) ?? "Error";
60876
+ } catch {
60877
+ name = "Error";
60878
+ }
60879
+ return {
60880
+ name: boundedSafeToolFailureText(name),
60881
+ message: boundedSafeToolFailureText(message),
60882
+ ...typeof exitCode === "number" && Number.isInteger(exitCode) ? { exitCode } : {},
60883
+ ...stdout !== undefined ? { stdout: boundedSafeToolFailureText(stdout) } : {},
60884
+ ...stderr !== undefined ? { stderr: boundedSafeToolFailureText(stderr) } : {}
60885
+ };
60886
+ }
60887
+ function workflowToolSuccess(value, attempts, cached) {
60888
+ return { ok: true, value, attempts, cached };
60889
+ }
60890
+ function workflowToolFailure(error, attempts, cached) {
60891
+ return { ok: false, error: normalizeWorkflowToolError(error), attempts, cached };
60892
+ }
60893
+ function workflowToolOutcomeFromValue(value) {
60894
+ if (value === null || typeof value !== "object" || Array.isArray(value))
60895
+ return;
60896
+ const candidate = value;
60897
+ if (!Number.isInteger(candidate.attempts) || typeof candidate.cached !== "boolean")
60898
+ return;
60899
+ if (candidate.ok === true && "value" in candidate)
60900
+ return candidate;
60901
+ const error = candidate.error;
60902
+ if (candidate.ok !== false || error === null || typeof error !== "object" || Array.isArray(error))
60903
+ return;
60904
+ const details = error;
60905
+ if (typeof details.name !== "string" || typeof details.message !== "string" || details.exitCode !== undefined && !Number.isInteger(details.exitCode) || details.stdout !== undefined && typeof details.stdout !== "string" || details.stderr !== undefined && typeof details.stderr !== "string")
60906
+ return;
60907
+ return candidate;
60908
+ }
60909
+ function replayedWorkflowToolOutcome(outcome) {
60910
+ return { ...outcome, cached: true };
60911
+ }
60912
+
60913
+ // dist/builtin/workflows/src/durable/types.ts
60914
+ var DURABLE_TOOL_TOPOLOGY_VERSION = 1;
60915
+ var DURABLE_STAGE_TOPOLOGY_VERSION = 1;
60916
+ var DURABLE_BOUNDARY_TOPOLOGY_VERSION = 1;
60917
+
60918
+ // dist/builtin/workflows/src/durable/durable-hash.ts
60919
+ import { createHash as createHash6 } from "node:crypto";
60920
+ function durableHash(value) {
60921
+ const canonical = canonicalJsonString(value);
60922
+ const digest = createHash6("sha256").update(canonical).digest("hex");
60923
+ return `h${digest.slice(0, 32)}`;
60924
+ }
60925
+ function canonicalJsonString(value) {
60926
+ if (value === null || typeof value !== "object")
60927
+ return JSON.stringify(value);
60928
+ if (Array.isArray(value))
60929
+ return `[${value.map(canonicalJsonString).join(",")}]`;
60930
+ const object = value;
60931
+ const keys = Object.keys(object).sort();
60932
+ return `{${keys.map((key2) => `${JSON.stringify(key2)}:${canonicalJsonString(object[key2])}`).join(",")}}`;
60933
+ }
60934
+ // dist/builtin/workflows/src/durable/backend.ts
60935
+ function pendingStageMessagesForDurableRun(backend, logicalRunId, rootWorkflowId = logicalRunId) {
60936
+ return (backend.getWorkflow(rootWorkflowId)?.pendingStageMessages ?? []).filter((entry) => entry.runId === logicalRunId);
60937
+ }
60938
+
60151
60939
  // dist/builtin/workflows/src/runs/foreground/executor-child-helpers.ts
60152
60940
  function cloneWorkflowChildValue(value) {
60153
60941
  return structuredClone(value);
@@ -60201,11 +60989,6 @@ function workflowChildReplaySnapshot(alias, childResult) {
60201
60989
  };
60202
60990
  }
60203
60991
 
60204
- // dist/builtin/workflows/src/durable/types.ts
60205
- var DURABLE_TOOL_TOPOLOGY_VERSION = 1;
60206
- var DURABLE_STAGE_TOPOLOGY_VERSION = 1;
60207
- var DURABLE_BOUNDARY_TOPOLOGY_VERSION = 1;
60208
-
60209
60992
  // dist/builtin/workflows/src/durable/stage-topology-validation.ts
60210
60993
  function immutableStageGroupError(stages) {
60211
60994
  const occurrenceError = promptOccurrenceIdentityError(stages);
@@ -60779,23 +61562,6 @@ function validatedInvocationRecords(input2) {
60779
61562
  return { stages, start };
60780
61563
  }
60781
61564
 
60782
- // dist/builtin/workflows/src/durable/durable-hash.ts
60783
- import { createHash as createHash6 } from "node:crypto";
60784
- function durableHash(value) {
60785
- const canonical = canonicalJsonString(value);
60786
- const digest = createHash6("sha256").update(canonical).digest("hex");
60787
- return `h${digest.slice(0, 32)}`;
60788
- }
60789
- function canonicalJsonString(value) {
60790
- if (value === null || typeof value !== "object")
60791
- return JSON.stringify(value);
60792
- if (Array.isArray(value))
60793
- return `[${value.map(canonicalJsonString).join(",")}]`;
60794
- const object = value;
60795
- const keys = Object.keys(object).sort();
60796
- return `{${keys.map((key2) => `${JSON.stringify(key2)}:${canonicalJsonString(object[key2])}`).join(",")}}`;
60797
- }
60798
-
60799
61565
  // dist/builtin/workflows/src/durable/child-invocation.ts
60800
61566
  function durableChildInvocationFingerprint(child, inputs) {
60801
61567
  return durableHash({
@@ -60804,354 +61570,6 @@ function durableChildInvocationFingerprint(child, inputs) {
60804
61570
  });
60805
61571
  }
60806
61572
 
60807
- // dist/builtin/workflows/src/shared/workflow-failures-signals.ts
60808
- function asRecord2(value) {
60809
- return value !== null && typeof value === "object" ? value : undefined;
60810
- }
60811
- function field2(value, key2) {
60812
- return asRecord2(value)?.[key2];
60813
- }
60814
- function safeField(value, key2) {
60815
- try {
60816
- return field2(value, key2);
60817
- } catch {
60818
- return;
60819
- }
60820
- }
60821
- function nonZeroExitCode(value) {
60822
- if (typeof value === "number")
60823
- return Number.isFinite(value) && value !== 0;
60824
- if (typeof value !== "string")
60825
- return false;
60826
- const parsed = Number(value.trim());
60827
- return Number.isFinite(parsed) && parsed !== 0;
60828
- }
60829
- function nonEmptyProcessOutput(value) {
60830
- if (typeof value === "string")
60831
- return value.length > 0;
60832
- if (value instanceof ArrayBuffer)
60833
- return value.byteLength > 0;
60834
- return ArrayBuffer.isView(value) && value.byteLength > 0;
60835
- }
60836
- function findProcessFailureError(value, seen, depth) {
60837
- if (value === null || typeof value !== "object" || depth >= 8 || seen.has(value))
60838
- return;
60839
- seen.add(value);
60840
- if (nonZeroExitCode(safeField(value, "exitCode")))
60841
- return value;
60842
- if (nonEmptyProcessOutput(safeField(value, "stdout")))
60843
- return value;
60844
- if (nonEmptyProcessOutput(safeField(value, "stderr")))
60845
- return value;
60846
- for (const key2 of ["cause", "error", "response", "body"]) {
60847
- const selected = findProcessFailureError(safeField(value, key2), seen, depth + 1);
60848
- if (selected !== undefined)
60849
- return selected;
60850
- }
60851
- const diagnostics = safeField(value, "diagnostics");
60852
- if (Array.isArray(diagnostics)) {
60853
- for (const diagnostic of diagnostics) {
60854
- const selected = findProcessFailureError(safeField(diagnostic, "error") ?? diagnostic, seen, depth + 1);
60855
- if (selected !== undefined)
60856
- return selected;
60857
- }
60858
- }
60859
- const errors = safeField(value, "errors");
60860
- if (!Array.isArray(errors))
60861
- return;
60862
- for (const error of errors) {
60863
- const selected = findProcessFailureError(error, seen, depth + 1);
60864
- if (selected !== undefined)
60865
- return selected;
60866
- }
60867
- return;
60868
- }
60869
- function selectProcessFailureError(error) {
60870
- return findProcessFailureError(error, new Set, 0) ?? error;
60871
- }
60872
- function hasProcessFailureEvidence(error) {
60873
- return findProcessFailureError(error, new Set, 0) !== undefined;
60874
- }
60875
- function stringField4(value, key2) {
60876
- const raw = field2(value, key2);
60877
- return typeof raw === "string" && raw.length > 0 ? raw : undefined;
60878
- }
60879
- function errorMessage3(error) {
60880
- const structuredMessage = structuredErrorMessage(error);
60881
- if (structuredMessage !== undefined)
60882
- return structuredMessage;
60883
- if (error instanceof Error && typeof error.message === "string")
60884
- return error.message;
60885
- if (typeof error === "string")
60886
- return error;
60887
- return String(error);
60888
- }
60889
- function errorName2(error) {
60890
- return error instanceof Error ? error.name : stringField4(error, "name");
60891
- }
60892
- function structuredErrorMessage(error) {
60893
- return stringField4(error, "errorMessage") ?? stringField4(error, "message") ?? stringField4(error, "statusText");
60894
- }
60895
- function integerFrom2(value) {
60896
- if (typeof value === "number" && Number.isInteger(value))
60897
- return value;
60898
- if (typeof value !== "string" || value.trim().length === 0)
60899
- return;
60900
- const parsed = Number(value.trim());
60901
- return Number.isInteger(parsed) ? parsed : undefined;
60902
- }
60903
- function numberFrom(value) {
60904
- if (typeof value === "number" && Number.isFinite(value))
60905
- return value;
60906
- if (typeof value !== "string" || value.trim().length === 0)
60907
- return;
60908
- const parsed = Number(value.trim());
60909
- return Number.isFinite(parsed) ? parsed : undefined;
60910
- }
60911
- function retryAfterHeaderMs(value) {
60912
- const numeric = numberFrom(value);
60913
- if (numeric !== undefined && numeric >= 0)
60914
- return Math.round(numeric * 1000);
60915
- if (typeof value !== "string" || value.trim().length === 0)
60916
- return;
60917
- const dateMs = Date.parse(value);
60918
- if (!Number.isFinite(dateMs))
60919
- return;
60920
- return Math.max(0, dateMs - Date.now());
60921
- }
60922
- function retryAfterMsFrom(error) {
60923
- const directMs = numberFrom(field2(error, "retryAfterMs"));
60924
- if (directMs !== undefined && directMs >= 0)
60925
- return Math.round(directMs);
60926
- const seconds = numberFrom(field2(error, "retryAfterSeconds"));
60927
- if (seconds !== undefined && seconds >= 0)
60928
- return Math.round(seconds * 1000);
60929
- const retryAfter = retryAfterHeaderMs(field2(error, "retryAfter"));
60930
- if (retryAfter !== undefined)
60931
- return retryAfter;
60932
- const retryAfterHeader = retryAfterHeaderMs(field2(error, "retry-after"));
60933
- if (retryAfterHeader !== undefined)
60934
- return retryAfterHeader;
60935
- const headers = field2(error, "headers");
60936
- const headerRecord = asRecord2(headers);
60937
- const headerValue = headerRecord?.["retry-after"] ?? headerRecord?.["Retry-After"];
60938
- return retryAfterHeaderMs(headerValue);
60939
- }
60940
- function structuredSignal2(error) {
60941
- const status = integerFrom2(field2(error, "status")) ?? integerFrom2(field2(error, "statusCode")) ?? integerFrom2(field2(error, "httpStatus"));
60942
- const rawCode = field2(error, "code");
60943
- const code = typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : undefined;
60944
- const name = errorName2(error);
60945
- const stopReason = stringField4(error, "stopReason");
60946
- const message = structuredErrorMessage(error);
60947
- const retryAfterMs = retryAfterMsFrom(error);
60948
- return {
60949
- ...status !== undefined ? { status } : {},
60950
- ...code !== undefined ? { code } : {},
60951
- ...name !== undefined ? { name } : {},
60952
- ...stopReason !== undefined ? { stopReason } : {},
60953
- ...message !== undefined ? { message } : {},
60954
- ...retryAfterMs !== undefined ? { retryAfterMs } : {}
60955
- };
60956
- }
60957
- function causeOf2(error) {
60958
- if (error instanceof Error)
60959
- return error.cause;
60960
- return field2(error, "cause");
60961
- }
60962
- function diagnosticErrors2(error) {
60963
- const diagnostics = field2(error, "diagnostics");
60964
- if (!Array.isArray(diagnostics))
60965
- return [];
60966
- const errors = [];
60967
- for (const diagnostic of diagnostics) {
60968
- const diagnosticError = field2(diagnostic, "error");
60969
- errors.push(diagnosticError ?? diagnostic);
60970
- }
60971
- return errors;
60972
- }
60973
- function nestedProviderError(error) {
60974
- return field2(error, "error") ?? field2(error, "response") ?? field2(error, "body");
60975
- }
60976
- function normalizeCode2(value) {
60977
- if (value === undefined)
60978
- return;
60979
- return String(value).trim().toLowerCase().replaceAll("-", "_").replaceAll(" ", "_");
60980
- }
60981
- function httpStatusFromCode(value) {
60982
- if (value === undefined)
60983
- return;
60984
- if (typeof value === "number") {
60985
- return Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
60986
- }
60987
- const trimmed = value.trim();
60988
- if (!/^\d{3}$/.test(trimmed))
60989
- return;
60990
- const parsed = Number(trimmed);
60991
- return parsed >= 100 && parsed <= 599 ? parsed : undefined;
60992
- }
60993
- function codeEvidenceFrom(value) {
60994
- const status = httpStatusFromCode(value);
60995
- if (status !== undefined)
60996
- return { kind: "wrapper_http_status", status };
60997
- const normalized = normalizeCode2(value);
60998
- return normalized !== undefined && normalized.length > 0 ? { kind: "semantic_code", normalized } : undefined;
60999
- }
61000
- function tokenize(value) {
61001
- const tokens = [];
61002
- let current = "";
61003
- for (const char of value.toLowerCase()) {
61004
- if (char >= "a" && char <= "z" || char >= "0" && char <= "9") {
61005
- current += char;
61006
- } else if (current.length > 0) {
61007
- tokens.push(current);
61008
- current = "";
61009
- }
61010
- }
61011
- if (current.length > 0)
61012
- tokens.push(current);
61013
- return tokens;
61014
- }
61015
- function hasPhrase(tokens, phrase) {
61016
- if (phrase.length === 0 || phrase.length > tokens.length)
61017
- return false;
61018
- for (let index = 0;index <= tokens.length - phrase.length; index += 1) {
61019
- let matched = true;
61020
- for (let offset = 0;offset < phrase.length; offset += 1) {
61021
- if (tokens[index + offset] !== phrase[offset]) {
61022
- matched = false;
61023
- break;
61024
- }
61025
- }
61026
- if (matched)
61027
- return true;
61028
- }
61029
- return false;
61030
- }
61031
- function hasAnyPhrase(tokens, phrases) {
61032
- return phrases.some((phrase) => hasPhrase(tokens, phrase));
61033
- }
61034
- function tokenNearAny(tokens, anchor, candidates, distance) {
61035
- for (let index = 0;index < tokens.length; index += 1) {
61036
- if (tokens[index] !== anchor)
61037
- continue;
61038
- const start = Math.max(0, index - distance);
61039
- const end = Math.min(tokens.length - 1, index + distance);
61040
- for (let cursor = start;cursor <= end; cursor += 1) {
61041
- if (cursor !== index && candidates.has(tokens[cursor]))
61042
- return true;
61043
- }
61044
- }
61045
- return false;
61046
- }
61047
- function redactedSecretReplacement(prefix) {
61048
- return `${prefix}[redacted]`;
61049
- }
61050
- function redactSensitiveText(value) {
61051
- return value.replace(/(sk-[A-Za-z0-9_-]{8})[A-Za-z0-9_-]+/g, redactedSecretReplacement("$1")).replace(/\b(authorization\s*:\s*bearer\s+)[^\s,;]+/gi, "$1[redacted]").replace(/\b(bearer\s+)[A-Za-z0-9._~+/-]{8,}=*/gi, "$1[redacted]").replace(/((?:api[_-]?key|token|credential|secret)\s*[:=]\s*)[^\s,;]+/gi, "$1[redacted]");
61052
- }
61053
-
61054
- // dist/builtin/workflows/src/durable/tool-outcome.ts
61055
- var TOOL_FAILURE_TEXT_LIMIT_BYTES = 16384;
61056
- var TRUNCATION_PREFIX = `[workflow tool output truncated; showing final bytes]
61057
- `;
61058
- function safeField2(error, key2) {
61059
- try {
61060
- return field2(error, key2);
61061
- } catch {
61062
- return;
61063
- }
61064
- }
61065
- function exposedText(error, key2) {
61066
- const value = safeField2(error, key2);
61067
- if (typeof value === "string")
61068
- return value;
61069
- try {
61070
- if (value instanceof ArrayBuffer)
61071
- return new TextDecoder().decode(value);
61072
- if (ArrayBuffer.isView(value)) {
61073
- return new TextDecoder().decode(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
61074
- }
61075
- } catch {
61076
- return;
61077
- }
61078
- return;
61079
- }
61080
- function boundedSafeToolFailureText(value) {
61081
- const redacted = redactSensitiveText(value);
61082
- const bytes = new TextEncoder().encode(redacted);
61083
- if (bytes.byteLength <= TOOL_FAILURE_TEXT_LIMIT_BYTES)
61084
- return redacted;
61085
- const prefix = new TextEncoder().encode(TRUNCATION_PREFIX);
61086
- const tailLength = Math.max(0, TOOL_FAILURE_TEXT_LIMIT_BYTES - prefix.byteLength);
61087
- let start = bytes.byteLength - tailLength;
61088
- const decoder = new TextDecoder("utf-8", { fatal: true });
61089
- while (start < bytes.byteLength) {
61090
- try {
61091
- return TRUNCATION_PREFIX + decoder.decode(bytes.slice(start));
61092
- } catch {
61093
- start += 1;
61094
- }
61095
- }
61096
- return TRUNCATION_PREFIX.slice(0, TOOL_FAILURE_TEXT_LIMIT_BYTES);
61097
- }
61098
- function safeErrorText(error) {
61099
- try {
61100
- return String(error);
61101
- } catch {
61102
- return "Tool callback failed";
61103
- }
61104
- }
61105
- function normalizeWorkflowToolError(error) {
61106
- error = selectProcessFailureError(error);
61107
- const exitCode = safeField2(error, "exitCode");
61108
- const stdout = exposedText(error, "stdout");
61109
- const stderr = exposedText(error, "stderr");
61110
- let message;
61111
- let name;
61112
- try {
61113
- message = errorMessage3(error);
61114
- } catch {
61115
- message = safeErrorText(error);
61116
- }
61117
- try {
61118
- name = errorName2(error) ?? "Error";
61119
- } catch {
61120
- name = "Error";
61121
- }
61122
- return {
61123
- name: boundedSafeToolFailureText(name),
61124
- message: boundedSafeToolFailureText(message),
61125
- ...typeof exitCode === "number" && Number.isInteger(exitCode) ? { exitCode } : {},
61126
- ...stdout !== undefined ? { stdout: boundedSafeToolFailureText(stdout) } : {},
61127
- ...stderr !== undefined ? { stderr: boundedSafeToolFailureText(stderr) } : {}
61128
- };
61129
- }
61130
- function workflowToolSuccess(value, attempts, cached) {
61131
- return { ok: true, value, attempts, cached };
61132
- }
61133
- function workflowToolFailure(error, attempts, cached) {
61134
- return { ok: false, error: normalizeWorkflowToolError(error), attempts, cached };
61135
- }
61136
- function workflowToolOutcomeFromValue(value) {
61137
- if (value === null || typeof value !== "object" || Array.isArray(value))
61138
- return;
61139
- const candidate = value;
61140
- if (!Number.isInteger(candidate.attempts) || typeof candidate.cached !== "boolean")
61141
- return;
61142
- if (candidate.ok === true && "value" in candidate)
61143
- return candidate;
61144
- const error = candidate.error;
61145
- if (candidate.ok !== false || error === null || typeof error !== "object" || Array.isArray(error))
61146
- return;
61147
- const details = error;
61148
- if (typeof details.name !== "string" || typeof details.message !== "string" || details.exitCode !== undefined && !Number.isInteger(details.exitCode) || details.stdout !== undefined && typeof details.stdout !== "string" || details.stderr !== undefined && typeof details.stderr !== "string")
61149
- return;
61150
- return candidate;
61151
- }
61152
- function replayedWorkflowToolOutcome(outcome) {
61153
- return { ...outcome, cached: true };
61154
- }
61155
61573
  // dist/builtin/workflows/src/durable/stage-topology.ts
61156
61574
  function activeStageTopology(backend, workflowId, replayKey) {
61157
61575
  const checkpoints = backend.listCheckpoints(workflowId);
@@ -61887,6 +62305,10 @@ function withMidSessionResumePrompt(stage, enabled) {
61887
62305
  });
61888
62306
  return stage;
61889
62307
  }
62308
+ function pendingStageIdForReplay(backend, workflowId, replayKey, stageName) {
62309
+ const candidates = new Set((backend.getWorkflow(workflowId)?.pendingStageMessages ?? []).filter((entry) => entry.stageReplayKey === replayKey || entry.stageReplayKey === undefined && entry.stageKey === stageName).map((entry) => entry.stageId).filter((stageId) => stageId !== undefined));
62310
+ return candidates.size === 1 ? candidates.values().next().value : undefined;
62311
+ }
61890
62312
  function createDurableStagePrimitive(input2) {
61891
62313
  return (name, options) => {
61892
62314
  const replayKey = input2.nextReplayKey(name);
@@ -61898,13 +62320,12 @@ function createDurableStagePrimitive(input2) {
61898
62320
  const session = input2.backend.getStageSession(input2.workflowId, replayKey);
61899
62321
  const isMidSessionResume = session?.sessionFile !== undefined;
61900
62322
  const topology = activeStageTopology(input2.backend, input2.workflowId, replayKey);
62323
+ const durableStageId = topology?.stageId ?? pendingStageIdForReplay(input2.backend, input2.workflowId, replayKey, name);
61901
62324
  const liveOptions = {
61902
62325
  ...options ?? {},
61903
62326
  durableReplayKey: replayKey,
61904
- ...topology !== undefined ? {
61905
- durableStageId: topology.stageId,
61906
- durableParentIds: [...topology.parentIds]
61907
- } : {},
62327
+ ...durableStageId !== undefined ? { durableStageId } : {},
62328
+ ...topology !== undefined ? { durableParentIds: [...topology.parentIds] } : {},
61908
62329
  ...isMidSessionResume ? {
61909
62330
  resumeFromSessionFile: session.sessionFile,
61910
62331
  durableAccumulatedDurationMs: session.durationMs ?? 0
@@ -63171,6 +63592,9 @@ class ScopedDurableBackend {
63171
63592
  this.persistent = inner.persistent;
63172
63593
  }
63173
63594
  registerWorkflow(_handle) {}
63595
+ persistPendingStageMessages(workflowId, messages2, logicalRunId = workflowId) {
63596
+ return this.inner.persistPendingStageMessages(this.scope.rootWorkflowId, messages2, logicalRunId);
63597
+ }
63174
63598
  recordCheckpoint(checkpoint) {
63175
63599
  this.inner.recordCheckpoint(this.remap(checkpoint));
63176
63600
  }
@@ -65308,6 +65732,7 @@ function appendStageStart(api, payload) {
65308
65732
  name: payload.name,
65309
65733
  parentIds: [...payload.parentIds],
65310
65734
  ...payload.model !== undefined ? { model: payload.model } : {},
65735
+ ...payload.pendingStageDeliveryAvailable !== undefined ? { pendingStageDeliveryAvailable: payload.pendingStageDeliveryAvailable } : {},
65311
65736
  ...payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {},
65312
65737
  ...payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {},
65313
65738
  ...payload.replayed !== undefined ? { replayed: payload.replayed } : {},
@@ -67034,6 +67459,7 @@ import { randomUUID as randomUUID9 } from "node:crypto";
67034
67459
 
67035
67460
  // dist/builtin/workflows/src/shared/intercom-group.ts
67036
67461
  import { randomUUID as randomUUID8 } from "node:crypto";
67462
+ var DEFAULT_INTERCOM_GROUP = "default";
67037
67463
  function workflowInvocationIntercomGroup(rootRunId) {
67038
67464
  return `workflow:${rootRunId}`;
67039
67465
  }
@@ -67043,6 +67469,12 @@ function normalizeAutoGroupSentinel(group) {
67043
67469
  const sentinel = group.trim().toLowerCase();
67044
67470
  return sentinel === "true" || sentinel === "auto" ? true : group;
67045
67471
  }
67472
+ function normalizeGroup(value) {
67473
+ if (typeof value !== "string")
67474
+ return DEFAULT_INTERCOM_GROUP;
67475
+ const trimmed = value.trim();
67476
+ return trimmed.length > 0 ? trimmed : DEFAULT_INTERCOM_GROUP;
67477
+ }
67046
67478
  function resolveStageGroup(stageOptions, workflowGroup) {
67047
67479
  if (!stageOptions)
67048
67480
  return workflowGroup;
@@ -67067,6 +67499,11 @@ function stageHasIntercomAccess(stageOptions) {
67067
67499
  return false;
67068
67500
  return true;
67069
67501
  }
67502
+ function stageCanUseWorkflowPendingStageRoute(stageOptions, workflowGroup) {
67503
+ if (!stageHasIntercomAccess(stageOptions) || stageOptions?.group === true)
67504
+ return false;
67505
+ return normalizeGroup(resolveStageGroup(stageOptions, workflowGroup)) === normalizeGroup(workflowGroup);
67506
+ }
67070
67507
 
67071
67508
  // dist/builtin/workflows/builtin/verification-usage.ts
67072
67509
  function fold_usage(results) {
@@ -67353,9 +67790,9 @@ function createRunBudgetController(input2) {
67353
67790
  function createParallelPrimitive(input2) {
67354
67791
  return async (steps, options = {}) => {
67355
67792
  input2.runtime.exit.throwIfWorkflowExitSelected();
67356
- const normalizeGroup = (value) => value.group === undefined ? value : { ...value, group: normalizeAutoGroupSentinel(value.group) };
67357
- const normalizedOptions = normalizeGroup(options);
67358
- const normalizedSteps = steps.map(normalizeGroup);
67793
+ const normalizeGroup2 = (value) => value.group === undefined ? value : { ...value, group: normalizeAutoGroupSentinel(value.group) };
67794
+ const normalizedOptions = normalizeGroup2(options);
67795
+ const normalizedSteps = steps.map(normalizeGroup2);
67359
67796
  const needsAutoGroup = normalizedOptions.group === true || normalizedSteps.some((step) => step.group === true);
67360
67797
  const autoGroup = needsAutoGroup ? randomUUID9() : undefined;
67361
67798
  const resolveAutoGroup = (value) => value.group === true && autoGroup ? { ...value, group: autoGroup } : value;
@@ -69230,7 +69667,7 @@ function createAdmittedToolExecutionTracker(options = {}) {
69230
69667
  const inFlight = new Set;
69231
69668
  const admissions = [];
69232
69669
  const failures = [];
69233
- let nextAdmissionOrder = 0;
69670
+ let nextAdmissionOrder2 = 0;
69234
69671
  let state = "OPEN";
69235
69672
  let closing;
69236
69673
  const abandonment = Promise.withResolvers();
@@ -69281,7 +69718,7 @@ function createAdmittedToolExecutionTracker(options = {}) {
69281
69718
  return { accepted: false, error, bindNode() {}, noteCancelled() {} };
69282
69719
  }
69283
69720
  const admission = {
69284
- admissionOrder: ++nextAdmissionOrder,
69721
+ admissionOrder: ++nextAdmissionOrder2,
69285
69722
  nodeId: undefined,
69286
69723
  failure: undefined,
69287
69724
  cancelled: false,
@@ -70623,6 +71060,150 @@ function createReplayStageContext(input2) {
70623
71060
  };
70624
71061
  }
70625
71062
 
71063
+ // dist/builtin/workflows/src/durable/run-owner-backend.ts
71064
+ function durableRootRunIdForRun(runs, runId) {
71065
+ return reciprocalWorkflowRootRunId(new Map(runs.map((run2) => [run2.id, run2])), runId);
71066
+ }
71067
+ function durableBackendForRun(backend, runs, runId) {
71068
+ const rootRunId = durableRootRunIdForRun(runs, runId);
71069
+ if (rootRunId === undefined)
71070
+ return;
71071
+ const runById = new Map(runs.map((run2) => [run2.id, run2]));
71072
+ if (rootRunId === runId)
71073
+ return backend;
71074
+ const scopes = [];
71075
+ let current = runById.get(runId);
71076
+ while (current !== undefined && current.id !== rootRunId) {
71077
+ const parent = current.parentRunId === undefined ? undefined : runById.get(current.parentRunId);
71078
+ const boundary = parent?.stages.find((stage) => stage.id === current?.parentStageId);
71079
+ if (parent === undefined || boundary?.replayKey === undefined)
71080
+ return;
71081
+ scopes.push(boundary.replayKey);
71082
+ current = parent;
71083
+ }
71084
+ if (current?.id !== rootRunId)
71085
+ return;
71086
+ let view = backend;
71087
+ for (const scopePrefix of scopes.reverse()) {
71088
+ view = new ScopedDurableBackend(view, { rootWorkflowId: rootRunId, scopePrefix });
71089
+ }
71090
+ return view;
71091
+ }
71092
+
71093
+ // dist/builtin/workflows/src/shared/pending-stage-route-capability.ts
71094
+ import { randomUUID as randomUUID10 } from "node:crypto";
71095
+ var routeCapabilities = new WeakMap;
71096
+ function workflowPendingStageRouteCapability(store2, runId) {
71097
+ let capabilities = routeCapabilities.get(store2);
71098
+ if (capabilities === undefined) {
71099
+ capabilities = new Map;
71100
+ routeCapabilities.set(store2, capabilities);
71101
+ }
71102
+ let capability = capabilities.get(runId);
71103
+ if (capability === undefined) {
71104
+ capability = randomUUID10();
71105
+ capabilities.set(runId, capability);
71106
+ }
71107
+ return capability;
71108
+ }
71109
+
71110
+ // dist/builtin/workflows/src/runs/foreground/pending-stage-delivery.ts
71111
+ var pendingDeliveryClaims = new WeakMap;
71112
+ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName) {
71113
+ let resolveReady;
71114
+ let rejectReady;
71115
+ let readyPromise;
71116
+ let drainError;
71117
+ let drainPromise;
71118
+ const pendingReady = () => {
71119
+ if (readyPromise === undefined) {
71120
+ readyPromise = new Promise((resolve23, reject) => {
71121
+ resolveReady = resolve23;
71122
+ rejectReady = reject;
71123
+ });
71124
+ }
71125
+ return readyPromise;
71126
+ };
71127
+ return {
71128
+ routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
71129
+ deliverPending(deliver) {
71130
+ if (drainPromise === undefined) {
71131
+ drainError = undefined;
71132
+ const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver);
71133
+ const drain2 = attempt.then(() => resolveReady?.(), (error) => {
71134
+ drainError = error;
71135
+ rejectReady?.(error);
71136
+ readyPromise = undefined;
71137
+ resolveReady = undefined;
71138
+ rejectReady = undefined;
71139
+ if (drainPromise === drain2)
71140
+ drainPromise = undefined;
71141
+ throw error;
71142
+ });
71143
+ drainPromise = drain2;
71144
+ }
71145
+ return drainPromise;
71146
+ },
71147
+ ready() {
71148
+ if (activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && (stageId === stageName || activeStore.pendingStageMessagesFor(runId, stageName).length === 0)) {
71149
+ return;
71150
+ }
71151
+ return drainError === undefined ? pendingReady() : Promise.reject(drainError);
71152
+ }
71153
+ };
71154
+ }
71155
+ async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver) {
71156
+ const candidateIds = new Set([
71157
+ ...activeStore.pendingStageMessagesFor(runId, stageId),
71158
+ ...activeStore.pendingStageMessagesFor(runId, stageName)
71159
+ ].map((entry) => entry.id));
71160
+ const entries = (activeStore.runs().find((run2) => run2.id === runId)?.pendingStageMessages ?? []).map((entry, index) => ({ entry, index })).filter(({ entry }) => candidateIds.has(entry.id)).sort((left, right) => (left.entry.admissionOrder ?? left.index + 1) - (right.entry.admissionOrder ?? right.index + 1) || left.index - right.index).map(({ entry }) => entry);
71161
+ const rootBackend = getDurableBackend();
71162
+ const backend = durableBackendForRun(rootBackend, activeStore.runs(), runId);
71163
+ if (backend === undefined) {
71164
+ throw new Error(`atomic-workflows: workflow run ${runId} has no durable owner for pending-stage delivery`);
71165
+ }
71166
+ for (const entry of entries) {
71167
+ const releaseClaim = claimPendingDelivery(activeStore, runId, entry.stageKey, entry.id);
71168
+ if (releaseClaim === undefined)
71169
+ continue;
71170
+ try {
71171
+ await deliver(toPendingStageSender(entry), entry.message);
71172
+ if (!await activeStore.markPendingStageMessageDelivered(runId, entry.stageKey, entry.id, new Date().toISOString(), backend)) {
71173
+ throw new Error(`atomic-workflows: pending-stage message ${entry.id} changed during delivery`);
71174
+ }
71175
+ } finally {
71176
+ releaseClaim();
71177
+ }
71178
+ }
71179
+ }
71180
+ function claimPendingDelivery(store2, runId, stageKey, messageId) {
71181
+ let claims = pendingDeliveryClaims.get(store2);
71182
+ if (claims === undefined) {
71183
+ claims = new Set;
71184
+ pendingDeliveryClaims.set(store2, claims);
71185
+ }
71186
+ const key2 = JSON.stringify([runId, stageKey, messageId]);
71187
+ if (claims.has(key2))
71188
+ return;
71189
+ claims.add(key2);
71190
+ return () => {
71191
+ claims?.delete(key2);
71192
+ if (claims?.size === 0)
71193
+ pendingDeliveryClaims.delete(store2);
71194
+ };
71195
+ }
71196
+ function toPendingStageSender(entry) {
71197
+ return {
71198
+ ...entry.from,
71199
+ cwd: entry.from.cwd ?? "",
71200
+ model: entry.from.model ?? "unknown",
71201
+ pid: entry.from.pid ?? 0,
71202
+ startedAt: entry.from.startedAt ?? entry.message.timestamp,
71203
+ lastActivity: entry.from.lastActivity ?? entry.message.timestamp
71204
+ };
71205
+ }
71206
+
70626
71207
  // dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts
70627
71208
  init_src();
70628
71209
 
@@ -71014,7 +71595,7 @@ function workflowSessionOptions(meta2) {
71014
71595
  workflow: { runId: meta2.runId, stageId: meta2.stageId, stageName: meta2.stageName }
71015
71596
  };
71016
71597
  }
71017
- function workflowOrchestrationContext(meta2, stageOptions) {
71598
+ function workflowOrchestrationContext(meta2, stageOptions, pendingStageDelivery) {
71018
71599
  const base = {
71019
71600
  kind: "workflow-stage",
71020
71601
  workflowRunId: meta2.runId,
@@ -71023,11 +71604,12 @@ function workflowOrchestrationContext(meta2, stageOptions) {
71023
71604
  constraints: { disableWorkflowTool: true }
71024
71605
  };
71025
71606
  const intercomGroup = stageHasIntercomAccess(stageOptions) ? resolveStageGroup(stageOptions, meta2.workflowIntercomGroup) : undefined;
71026
- return intercomGroup ? { ...base, intercomGroup } : base;
71607
+ const context = intercomGroup ? { ...base, intercomGroup } : base;
71608
+ return pendingStageDelivery === undefined ? context : { ...context, pendingStageDelivery };
71027
71609
  }
71028
- function stripWorkflowOnlyOptions(options, defaultSessionDir, meta2) {
71610
+ function stripWorkflowOnlyOptions(options, defaultSessionDir, meta2, pendingStageDelivery) {
71029
71611
  const classification = workflowSessionOptions(meta2);
71030
- const orchestrationContext = workflowOrchestrationContext(meta2, options);
71612
+ const orchestrationContext = workflowOrchestrationContext(meta2, options, pendingStageDelivery);
71031
71613
  if (!options) {
71032
71614
  return defaultSessionDir === undefined ? { orchestrationContext } : {
71033
71615
  orchestrationContext,
@@ -72393,7 +72975,7 @@ class StageSessionController {
72393
72975
  });
72394
72976
  let created;
72395
72977
  try {
72396
- created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta), {
72978
+ created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta, this.opts.pendingStageDelivery), {
72397
72979
  ...this.meta,
72398
72980
  stageOptions,
72399
72981
  ...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
@@ -72410,10 +72992,12 @@ class StageSessionController {
72410
72992
  throw this.staleCreationReason(startGeneration);
72411
72993
  }
72412
72994
  const session = attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
72413
- if (session instanceof Promise)
72414
- return await session;
72995
+ const attachedSession = session instanceof Promise ? await session : session;
72996
+ const pendingStageDeliveryReady = this.sharedOrchestrationContext?.pendingStageDelivery?.ready();
72997
+ if (pendingStageDeliveryReady !== undefined)
72998
+ await pendingStageDeliveryReady;
72415
72999
  await this.opts.onSessionReady?.();
72416
- return session;
73000
+ return attachedSession;
72417
73001
  }
72418
73002
  attachSession(created) {
72419
73003
  const result = normalizeSessionCreateResult(created);
@@ -73165,6 +73749,12 @@ function createWorkflowStageFactory(input2) {
73165
73749
  const replaySource = replayDecision.kind === "replay" ? replayDecision.source : undefined;
73166
73750
  const executeReplaySource = replayDecision.kind === "execute" ? replayDecision.source : undefined;
73167
73751
  const shouldReplay = replaySource !== undefined;
73752
+ const stageOptionsForContext = executeReplaySource?.sessionFile === undefined ? options : {
73753
+ ...options ?? {},
73754
+ context: options?.context ?? "fork",
73755
+ forkFromSessionFile: options?.forkFromSessionFile ?? executeReplaySource.sessionFile
73756
+ };
73757
+ const pendingStageDeliveryAvailable = stageCanUseWorkflowPendingStageRoute(stageOptionsForContext, input2.workflowIntercomGroup);
73168
73758
  const stageSnapshot = {
73169
73759
  id: stageId,
73170
73760
  name,
@@ -73172,6 +73762,7 @@ function createWorkflowStageFactory(input2) {
73172
73762
  status: shouldReplay ? "completed" : "pending",
73173
73763
  parentIds: Object.freeze(parentIds),
73174
73764
  toolEvents: [],
73765
+ pendingStageDeliveryAvailable,
73175
73766
  ...shouldReplay ? {
73176
73767
  startedAt: Date.now(),
73177
73768
  endedAt: Date.now(),
@@ -73200,11 +73791,6 @@ function createWorkflowStageFactory(input2) {
73200
73791
  throwIfWorkflowExitSelected: input2.exit.throwIfWorkflowExitSelected
73201
73792
  });
73202
73793
  }
73203
- const stageOptionsForContext = executeReplaySource?.sessionFile === undefined ? options : {
73204
- ...options ?? {},
73205
- context: options?.context ?? "fork",
73206
- forkFromSessionFile: options?.forkFromSessionFile ?? executeReplaySource.sessionFile
73207
- };
73208
73794
  const applyModelFallbackMeta = (meta2) => {
73209
73795
  if (meta2.model !== undefined)
73210
73796
  stageSnapshot.model = meta2.model;
@@ -73242,6 +73828,9 @@ function createWorkflowStageFactory(input2) {
73242
73828
  workflowIntercomGroup: input2.workflowIntercomGroup,
73243
73829
  signal: input2.signal,
73244
73830
  stageOptions: stageOptionsForContext,
73831
+ ...pendingStageDeliveryAvailable ? {
73832
+ pendingStageDelivery: createWorkflowPendingStageDelivery(input2.activeStore, input2.runId, stageId, name)
73833
+ } : {},
73245
73834
  models: input2.opts.models,
73246
73835
  executionMode: input2.opts.executionMode,
73247
73836
  defaultSessionDir: input2.opts.defaultSessionDir,
@@ -73367,6 +73956,7 @@ function createWorkflowStageFactory(input2) {
73367
73956
  name,
73368
73957
  parentIds: stageSnapshot.parentIds,
73369
73958
  ...stageReplayFields(stageSnapshot),
73959
+ pendingStageDeliveryAvailable,
73370
73960
  ts: stageSnapshot.startedAt ?? Date.now()
73371
73961
  });
73372
73962
  };
@@ -73729,6 +74319,9 @@ async function run(def, inputs, opts = {}) {
73729
74319
  status: "running",
73730
74320
  stages: [],
73731
74321
  toolNodes: [],
74322
+ pendingStageMessages: [
74323
+ ...pendingStageMessagesForDurableRun(rootBackend, runId, opts.parentRun?.rootRunId ?? runId)
74324
+ ],
73732
74325
  startedAt: Date.now(),
73733
74326
  ...opts.parentRun !== undefined ? {
73734
74327
  parentRunId: opts.parentRun.runId,