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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/CHANGELOG.md +19 -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 +680 -53
  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 +109 -35
  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 +173 -51
  21. package/dist/builtin/web-access/index.bundle.mjs +109 -35
  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-29wrp38a.js +199 -0
  28. package/dist/builtin/workflows/builtin/chunk-2dqb5s2q.js +602 -0
  29. package/dist/builtin/workflows/builtin/chunk-4febxsv4.js +264 -0
  30. package/dist/builtin/workflows/builtin/chunk-5n10x7j2.js +69730 -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-bfkmzv9h.js +156 -0
  37. package/dist/builtin/workflows/builtin/chunk-c53y8bdh.js +345 -0
  38. package/dist/builtin/workflows/builtin/chunk-cdtd3m3w.js +529 -0
  39. package/dist/builtin/workflows/builtin/chunk-cg9tmks0.js +206 -0
  40. package/dist/builtin/workflows/builtin/chunk-hdpj1dkw.js +2447 -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-qwzvgxnq.js +404 -0
  44. package/dist/builtin/workflows/builtin/chunk-qx2ptjs3.js +215 -0
  45. package/dist/builtin/workflows/builtin/chunk-v04c5qmd.js +1207 -0
  46. package/dist/builtin/workflows/builtin/chunk-wpckd35c.js +12 -0
  47. package/dist/builtin/workflows/builtin/chunk-x2ghn0je.js +4110 -0
  48. package/dist/builtin/workflows/builtin/chunk-zf28603f.js +1080 -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 +1228 -428
  63. package/dist/builtin/workflows/src/{index.bundle.mjs → index.js} +956 -427
  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/context-types.d.ts +35 -0
  91. package/dist/core/extensions/context-types.d.ts.map +1 -1
  92. package/dist/core/extensions/context-types.js.map +1 -1
  93. package/dist/core/extensions/index.d.ts +1 -1
  94. package/dist/core/extensions/index.d.ts.map +1 -1
  95. package/dist/core/extensions/index.js.map +1 -1
  96. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  97. package/dist/core/extensions/loader-virtual-modules.js +6 -1
  98. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  99. package/dist/core/model-runtime.d.ts +2 -0
  100. package/dist/core/model-runtime.d.ts.map +1 -1
  101. package/dist/core/model-runtime.js +4 -0
  102. package/dist/core/model-runtime.js.map +1 -1
  103. package/dist/core/runtime-credentials.d.ts +1 -0
  104. package/dist/core/runtime-credentials.d.ts.map +1 -1
  105. package/dist/core/runtime-credentials.js +8 -0
  106. package/dist/core/runtime-credentials.js.map +1 -1
  107. package/dist/core/sdk.d.ts.map +1 -1
  108. package/dist/core/sdk.js +5 -5
  109. package/dist/core/sdk.js.map +1 -1
  110. package/dist/core/session-manager-storage.d.ts +2 -0
  111. package/dist/core/session-manager-storage.d.ts.map +1 -1
  112. package/dist/core/session-manager-storage.js +4 -2
  113. package/dist/core/session-manager-storage.js.map +1 -1
  114. package/dist/core/slash-commands.js +1 -1
  115. package/dist/core/slash-commands.js.map +1 -1
  116. package/dist/core/workflow-stage-admission.d.ts +6 -1
  117. package/dist/core/workflow-stage-admission.d.ts.map +1 -1
  118. package/dist/core/workflow-stage-admission.js +8 -9
  119. package/dist/core/workflow-stage-admission.js.map +1 -1
  120. package/dist/index.d.ts +0 -1
  121. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/footer.js +1 -1
  123. package/dist/modes/interactive/components/footer.js.map +1 -1
  124. package/dist/modes/interactive/interactive-autocomplete.js +1 -1
  125. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  126. package/dist/modes/interactive/interactive-startup.js +1 -1
  127. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  128. package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -0
  129. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  130. package/dist/modes/interactive-engine/isolated-runtime.js +69 -10
  131. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  132. package/dist/modes/rpc/rpc-client-api.d.ts +18 -2
  133. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  134. package/dist/modes/rpc/rpc-client-api.js +33 -5
  135. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  136. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  137. package/dist/modes/rpc/rpc-command-handler.js +8 -4
  138. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  139. package/dist/modes/rpc/rpc-types.d.ts +13 -0
  140. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  141. package/dist/modes/rpc/rpc-types.js.map +1 -1
  142. package/docs/intercom.md +15 -6
  143. package/docs/packages.md +2 -2
  144. package/docs/providers.md +8 -3
  145. package/docs/quickstart.md +2 -2
  146. package/docs/rpc.md +21 -4
  147. package/docs/settings.md +6 -4
  148. package/docs/subagents.md +1 -1
  149. package/docs/usage.md +1 -1
  150. package/docs/workflows.md +108 -239
  151. package/npm-shrinkwrap.json +32 -32
  152. package/package.json +9 -13
  153. package/dist/builtin/workflows/ambient.d.ts +0 -61
  154. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +0 -26
  155. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +0 -391
  156. package/dist/builtin/workflows/builtin/adversarial-verification.ts +0 -34
  157. package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +0 -14
  158. package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +0 -108
  159. package/dist/builtin/workflows/builtin/classify-and-act.ts +0 -40
  160. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +0 -14
  161. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +0 -96
  162. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +0 -37
  163. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +0 -41
  164. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +0 -90
  165. package/dist/builtin/workflows/builtin/generate-and-filter.ts +0 -31
  166. package/dist/builtin/workflows/builtin/goal-artifacts.ts +0 -64
  167. package/dist/builtin/workflows/builtin/goal-convergence.ts +0 -87
  168. package/dist/builtin/workflows/builtin/goal-ledger.ts +0 -139
  169. package/dist/builtin/workflows/builtin/goal-models.ts +0 -72
  170. package/dist/builtin/workflows/builtin/goal-orchestrator-prompts.ts +0 -94
  171. package/dist/builtin/workflows/builtin/goal-prompts.ts +0 -217
  172. package/dist/builtin/workflows/builtin/goal-reducer.ts +0 -176
  173. package/dist/builtin/workflows/builtin/goal-reports.ts +0 -76
  174. package/dist/builtin/workflows/builtin/goal-reverify.ts +0 -305
  175. package/dist/builtin/workflows/builtin/goal-review.ts +0 -139
  176. package/dist/builtin/workflows/builtin/goal-runner.ts +0 -504
  177. package/dist/builtin/workflows/builtin/goal-schemas.ts +0 -89
  178. package/dist/builtin/workflows/builtin/goal-types.ts +0 -164
  179. package/dist/builtin/workflows/builtin/goal.ts +0 -78
  180. package/dist/builtin/workflows/builtin/index.ts +0 -16
  181. package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +0 -87
  182. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +0 -282
  183. package/dist/builtin/workflows/builtin/loop-until-done.ts +0 -51
  184. package/dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts +0 -305
  185. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +0 -337
  186. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +0 -347
  187. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +0 -313
  188. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +0 -311
  189. package/dist/builtin/workflows/builtin/open-claude-design.ts +0 -57
  190. package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +0 -28
  191. package/dist/builtin/workflows/builtin/progress-scoring.ts +0 -230
  192. package/dist/builtin/workflows/builtin/ralph-core.ts +0 -449
  193. package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +0 -100
  194. package/dist/builtin/workflows/builtin/ralph-models.ts +0 -183
  195. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +0 -103
  196. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +0 -104
  197. package/dist/builtin/workflows/builtin/ralph-runner.ts +0 -459
  198. package/dist/builtin/workflows/builtin/ralph.ts +0 -82
  199. package/dist/builtin/workflows/builtin/review-convergence.ts +0 -229
  200. package/dist/builtin/workflows/builtin/selection-math.ts +0 -156
  201. package/dist/builtin/workflows/builtin/steering-context.ts +0 -51
  202. package/dist/builtin/workflows/builtin/tournament-prompts.ts +0 -70
  203. package/dist/builtin/workflows/builtin/tournament-runner.ts +0 -400
  204. package/dist/builtin/workflows/builtin/tournament.ts +0 -73
  205. package/dist/builtin/workflows/builtin/verification-criteria.ts +0 -330
  206. package/dist/builtin/workflows/builtin/verification-prompts.ts +0 -206
  207. 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) {
@@ -21628,11 +21635,20 @@ function isCodexFastModeCandidateModelId(modelId) {
21628
21635
  const provider = modelId?.split("/", 1)[0];
21629
21636
  return provider !== undefined && isCodexFastModeSupportedProvider(provider);
21630
21637
  }
21631
- function isCodexFastModeSupportedModel(model) {
21632
- return isCodexFastModeSupportedProvider(model.provider) || model.api === "openai-codex-responses";
21638
+ function isGitHubCopilotModel(model) {
21639
+ return model.provider === "github-copilot";
21633
21640
  }
21634
- function hasSupportedCodexFastModeModel(models) {
21635
- return models.some(isCodexFastModeSupportedModel);
21641
+ function isGitHubCopilotFastModeSupportedModel(model, credential) {
21642
+ if (!isGitHubCopilotModel(model) || credential?.type !== "oauth")
21643
+ return false;
21644
+ const fastModelIds = credential.fastModelIds;
21645
+ return Array.isArray(fastModelIds) && fastModelIds.every((modelId) => typeof modelId === "string") && fastModelIds.includes(`${model.id}-fast`);
21646
+ }
21647
+ function isCodexFastModeSupportedModel(model, copilotCredential) {
21648
+ return isCodexFastModeSupportedProvider(model.provider) || model.api === "openai-codex-responses" || model.id !== undefined && isGitHubCopilotFastModeSupportedModel({ provider: model.provider, id: model.id }, copilotCredential);
21649
+ }
21650
+ function hasSupportedCodexFastModeModel(models, copilotCredential) {
21651
+ return models.some((model) => isCodexFastModeSupportedModel(model, copilotCredential));
21636
21652
  }
21637
21653
  function isWorkflowStageOrchestrationContext(context) {
21638
21654
  return context?.kind === "workflow-stage";
@@ -21643,11 +21659,11 @@ function getCodexFastModeScope(context) {
21643
21659
  function isCodexFastModeEnabledForScope(settings, scope) {
21644
21660
  return settings[scope];
21645
21661
  }
21646
- function shouldApplyCodexFastModeForScope(model, settings, scope) {
21647
- return isCodexFastModeSupportedModel(model) && isCodexFastModeEnabledForScope(settings, scope);
21662
+ function shouldApplyCodexFastModeForScope(model, settings, scope, copilotCredential) {
21663
+ return isCodexFastModeSupportedModel(model, copilotCredential) && isCodexFastModeEnabledForScope(settings, scope);
21648
21664
  }
21649
- function shouldApplyCodexFastMode(model, settings, context) {
21650
- return shouldApplyCodexFastModeForScope(model, settings, getCodexFastModeScope(context));
21665
+ function shouldApplyCodexFastMode(model, settings, context, copilotCredential) {
21666
+ return shouldApplyCodexFastModeForScope(model, settings, getCodexFastModeScope(context), copilotCredential);
21651
21667
  }
21652
21668
  function formatCodexFastModeModelLabel(modelName, enabled) {
21653
21669
  return enabled ? `${modelName} fast` : modelName;
@@ -21788,7 +21804,7 @@ class FooterComponent {
21788
21804
  pwd += ` • ${sessionName}`;
21789
21805
  const modelName = state.model?.id || "no-model";
21790
21806
  const fastModeSettings = this.session.settingsManager.getCodexFastModeSettings();
21791
- const fastModeEnabled = state.model ? shouldApplyCodexFastMode(state.model, fastModeSettings, this.session.orchestrationContext) : false;
21807
+ const fastModeEnabled = state.model ? shouldApplyCodexFastMode(state.model, fastModeSettings, this.session.orchestrationContext, this.session.modelRuntime.getCredentialSnapshot?.("github-copilot")) : false;
21792
21808
  let modelLabel2 = modelName;
21793
21809
  if (state.model?.reasoning) {
21794
21810
  const thinkingLevel = state.thinkingLevel || "off";
@@ -39432,14 +39448,18 @@ import { AsyncLocalStorage } from "node:async_hooks";
39432
39448
 
39433
39449
  class WorkflowStageAdmissionBoundary {
39434
39450
  open = true;
39435
- completed = new Set;
39451
+ completed;
39436
39452
  inFlight = new Map;
39437
39453
  pending = new Set;
39438
39454
  invocationContext = new AsyncLocalStorage;
39439
39455
  closePromise;
39440
39456
  drainAdmittedWork;
39441
- constructor(drainAdmittedWork = async () => {}) {
39442
- this.drainAdmittedWork = drainAdmittedWork;
39457
+ constructor(drainAdmittedWork = undefined, completedKeys = []) {
39458
+ this.drainAdmittedWork = drainAdmittedWork ?? (async () => {});
39459
+ this.completed = new Set(completedKeys);
39460
+ }
39461
+ static restore(entries, drainAdmittedWork) {
39462
+ return new WorkflowStageAdmissionBoundary(drainAdmittedWork, Array.from(entries).flatMap((entry) => entry.type === "custom_message" && typeof entry.stageAdmissionKey === "string" ? [entry.stageAdmissionKey] : []));
39443
39463
  }
39444
39464
  admit(key, deliver, routeLate) {
39445
39465
  if (key !== undefined) {
@@ -39678,7 +39698,7 @@ class AgentSessionBase {
39678
39698
  this._subagentPolicy = config.subagentPolicy;
39679
39699
  this._systemPromptTransform = config.systemPromptTransform;
39680
39700
  const stageContext = config.orchestrationContext?.kind === "workflow-stage" ? config.orchestrationContext : undefined;
39681
- this._workflowStageAdmission = stageContext?.messageAdmission?.boundary ?? (stageContext ? new WorkflowStageAdmissionBoundary : undefined);
39701
+ this._workflowStageAdmission = stageContext?.messageAdmission?.boundary ?? (stageContext ? WorkflowStageAdmissionBoundary.restore(this.sessionManager.getBranch()) : undefined);
39682
39702
  if (this._workflowStageAdmission && stageContext && stageContext.messageAdmission === undefined) {
39683
39703
  stageContext.messageAdmission = {
39684
39704
  boundary: this._workflowStageAdmission,
@@ -46657,6 +46677,31 @@ class RemoteQueuePause {
46657
46677
  var init_remote_queue_pause = () => {};
46658
46678
 
46659
46679
  // src/modes/interactive-engine/isolated-runtime.ts
46680
+ import { clampThinkingLevel as clampThinkingLevel5 } from "@bastani/pi-ai/compat";
46681
+ function applyPersistedModelDefault(session, model, alreadyInScope) {
46682
+ session.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
46683
+ if (alreadyInScope || session.scopedModels.length === 0)
46684
+ return;
46685
+ const enabledModels = session.settingsManager.getEnabledModels();
46686
+ if (!enabledModels?.length)
46687
+ return;
46688
+ const modelReference = `${model.provider}/${model.id}`;
46689
+ if (enabledModels.some((pattern) => pattern.toLowerCase() === modelReference.toLowerCase()))
46690
+ return;
46691
+ session.settingsManager.setEnabledModels([...enabledModels, modelReference]);
46692
+ }
46693
+ function thinkingPersistTarget(result) {
46694
+ if (!result.provider || !result.modelId)
46695
+ return;
46696
+ return { provider: result.provider, modelId: result.modelId };
46697
+ }
46698
+ function applyPersistedThinkingDefault(session, level, target) {
46699
+ if (target) {
46700
+ session.settingsManager.setModelThinkingLevel(target.provider, target.modelId, level);
46701
+ return;
46702
+ }
46703
+ session.settingsManager.setDefaultThinkingLevel(level);
46704
+ }
46660
46705
  var IsolatedInteractiveRuntime;
46661
46706
  var init_isolated_runtime = __esm(() => {
46662
46707
  init_agent_session_runtime();
@@ -46675,6 +46720,7 @@ var init_isolated_runtime = __esm(() => {
46675
46720
  steeringMessages = [];
46676
46721
  followUpMessages = [];
46677
46722
  queueUpdateGeneration = 0;
46723
+ thinkingEpoch = 0;
46678
46724
  pendingQueueClear;
46679
46725
  engineCallbackActive = false;
46680
46726
  queuePause;
@@ -47039,43 +47085,56 @@ var init_isolated_runtime = __esm(() => {
47039
47085
  },
47040
47086
  setModel: {
47041
47087
  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;
47088
+ value: async (model, options) => {
47089
+ const selected = await this.client.setModel(model.provider, model.id, options);
47090
+ const nextModel = session.modelRuntime.getModel(selected.provider, selected.id) ?? model;
47091
+ session.agent.state.model = nextModel;
47045
47092
  this.resolveModelFallback();
47093
+ if (options?.persist === true)
47094
+ await this.syncPersistedModelCatalog(session, nextModel);
47046
47095
  }
47047
47096
  },
47048
47097
  setThinkingLevel: {
47049
47098
  configurable: true,
47050
- value: (level) => {
47051
- session.agent.state.thinkingLevel = level;
47052
- this.dispatchBestEffort("set thinking level", this.client.setThinkingLevel(level));
47099
+ value: (level, options) => {
47100
+ const availableLevels = session.getAvailableThinkingLevels();
47101
+ const effectiveLevel = availableLevels.includes(level) ? level : session.model ? clampThinkingLevel5(session.model, level) : "off";
47102
+ session.agent.state.thinkingLevel = effectiveLevel;
47103
+ const epoch = ++this.thinkingEpoch;
47104
+ this.dispatchBestEffort("set thinking level", this.client.setThinkingLevelAck(level, options).then((result) => {
47105
+ this.applyThinkingAck(session, epoch, result, options?.persist === true);
47106
+ }));
47053
47107
  }
47054
47108
  },
47055
47109
  cycleModel: {
47056
47110
  configurable: true,
47057
- value: async (direction) => {
47111
+ value: async (direction, options) => {
47058
47112
  const previousModel = session.model;
47059
- const result = await this.client.cycleModel(direction);
47113
+ const result = await this.client.cycleModel(direction, options);
47060
47114
  if (!result)
47061
47115
  return;
47062
47116
  const model = session.modelRuntime.getModel(result.model.provider, result.model.id) ?? result.model;
47063
47117
  session.agent.state.model = model;
47064
47118
  session.agent.state.thinkingLevel = result.thinkingLevel;
47065
47119
  this.resolveModelFallbackAfterExplicitModelSelection(previousModel, model);
47120
+ if (options?.persist === true)
47121
+ await this.syncPersistedModelCatalog(session, model);
47066
47122
  return { ...result, model };
47067
47123
  }
47068
47124
  },
47069
47125
  cycleThinkingLevel: {
47070
47126
  configurable: true,
47071
- value: () => {
47127
+ value: (options) => {
47072
47128
  const levels = session.getAvailableThinkingLevels();
47073
47129
  if (levels.length <= 1)
47074
47130
  return;
47075
47131
  const current = levels.indexOf(session.thinkingLevel);
47076
47132
  const level = levels[(current + 1) % levels.length];
47077
47133
  session.agent.state.thinkingLevel = level;
47078
- this.dispatchBestEffort("cycle thinking level", this.client.setThinkingLevel(level));
47134
+ const epoch = ++this.thinkingEpoch;
47135
+ this.dispatchBestEffort("cycle thinking level", this.client.setThinkingLevelAck(level, options).then((result) => {
47136
+ this.applyThinkingAck(session, epoch, result, options?.persist === true);
47137
+ }));
47079
47138
  return level;
47080
47139
  }
47081
47140
  },
@@ -47119,6 +47178,14 @@ var init_isolated_runtime = __esm(() => {
47119
47178
  this.engineCallbackActive = false;
47120
47179
  }
47121
47180
  }
47181
+ applyThinkingAck(session, epoch, result, persist) {
47182
+ if (persist) {
47183
+ applyPersistedThinkingDefault(session, result.level, thinkingPersistTarget(result));
47184
+ }
47185
+ if (epoch === this.thinkingEpoch) {
47186
+ session.agent.state.thinkingLevel = result.level;
47187
+ }
47188
+ }
47122
47189
  dispatchBestEffort(label, operation) {
47123
47190
  operation.catch((error) => {
47124
47191
  if (this.health.isRecovering())
@@ -47159,6 +47226,12 @@ var init_isolated_runtime = __esm(() => {
47159
47226
  }
47160
47227
  });
47161
47228
  }
47229
+ async syncPersistedModelCatalog(session, model) {
47230
+ const alreadyInScope = session.scopedModels.some((scoped) => scoped.model.provider === model.provider && scoped.model.id === model.id);
47231
+ const catalog = await this.client.requestInternal({ type: "get_available_models" });
47232
+ this.remoteModelCatalog.apply(catalog);
47233
+ applyPersistedModelDefault(session, model, alreadyInScope);
47234
+ }
47162
47235
  refreshSessionView() {
47163
47236
  const session = super.session;
47164
47237
  const sessionFile = session.sessionFile;
@@ -47198,6 +47271,7 @@ var init_isolated_runtime = __esm(() => {
47198
47271
  session.agent.state.model = event.model;
47199
47272
  break;
47200
47273
  case "thinking_level_changed":
47274
+ this.thinkingEpoch += 1;
47201
47275
  session.agent.state.thinkingLevel = event.level;
47202
47276
  break;
47203
47277
  case "session_info_changed":
@@ -48411,7 +48485,7 @@ var init_slash_commands = __esm(() => {
48411
48485
  { name: "tree", description: "Navigate session tree (switch branches)" },
48412
48486
  { name: "thinking", description: "Set thinking level", argumentHint: "<level>" },
48413
48487
  { name: "scoped-models", description: "Enable/disable models for ctrl+p cycling" },
48414
- { name: "fast", description: "Configure Codex fast mode for chat and workflows" },
48488
+ { name: "fast", description: "Configure OpenAI fast mode for chat and workflows in supported models" },
48415
48489
  { name: "export", description: "Export session (HTML default, or specify path: .html/.jsonl)" },
48416
48490
  { name: "import", description: "Import and resume a session from a JSONL file" },
48417
48491
  { name: "share", description: "Share session as a secret GitHub gist" },
@@ -49863,7 +49937,7 @@ var init_interactive_autocomplete = __esm(() => {
49863
49937
  return [...this.session.modelRuntime.getAvailableSnapshot()];
49864
49938
  };
49865
49939
  InteractiveModeBase.prototype.hasCodexFastModeSupportedModels = function() {
49866
- return hasSupportedCodexFastModeModel(this.getCodexFastModeCandidateModels());
49940
+ return hasSupportedCodexFastModeModel(this.getCodexFastModeCandidateModels(), this.session.modelRuntime.getCredentialSnapshot?.("github-copilot"));
49867
49941
  };
49868
49942
  InteractiveModeBase.prototype.buildRemoteSlashCommands = function(localCommands) {
49869
49943
  const remote = getInteractiveEngineRemoteCommands(this.runtimeHost);
@@ -50551,7 +50625,7 @@ var init_interactive_startup = __esm(() => {
50551
50625
  if (!model) {
50552
50626
  return modelLabel2;
50553
50627
  }
50554
- const fastModeEnabled = shouldApplyCodexFastMode(model, this.session.settingsManager.getCodexFastModeSettings(), this.session.orchestrationContext);
50628
+ const fastModeEnabled = shouldApplyCodexFastMode(model, this.session.settingsManager.getCodexFastModeSettings(), this.session.orchestrationContext, this.session.modelRuntime.getCredentialSnapshot?.("github-copilot"));
50555
50629
  return formatCodexFastModeModelLabel(modelLabel2, fastModeEnabled);
50556
50630
  };
50557
50631
  InteractiveModeBase.prototype.getStartupIdentityText = function(maxWidth, gap = 0, manifestoPhase = 4) {
@@ -55066,7 +55140,7 @@ var init_interactive_selectors = __esm(() => {
55066
55140
  });
55067
55141
 
55068
55142
  // src/modes/interactive/interactive-model-routing.ts
55069
- import { clampThinkingLevel as clampThinkingLevel5 } from "@bastani/pi-ai/compat";
55143
+ import { clampThinkingLevel as clampThinkingLevel6 } from "@bastani/pi-ai/compat";
55070
55144
  function resolveThinkingSelectorDefault(rawDefault, availableLevels, model) {
55071
55145
  if (rawDefault === undefined)
55072
55146
  return;
@@ -55074,7 +55148,7 @@ function resolveThinkingSelectorDefault(rawDefault, availableLevels, model) {
55074
55148
  return rawDefault;
55075
55149
  if (!model)
55076
55150
  return availableLevels.includes("off") ? "off" : availableLevels[0];
55077
- const clamped = clampThinkingLevel5(model, rawDefault);
55151
+ const clamped = clampThinkingLevel6(model, rawDefault);
55078
55152
  if (availableLevels.includes(clamped))
55079
55153
  return clamped;
55080
55154
  return availableLevels.includes("off") ? "off" : availableLevels[0];
@@ -57931,6 +58005,152 @@ function buildStagePromptAdapter(id, kind, args, createdAt) {
57931
58005
  // dist/builtin/workflows/src/shared/stage-ui-broker.ts
57932
58006
  import { randomUUID as randomUUID7 } from "node:crypto";
57933
58007
 
58008
+ // dist/builtin/workflows/src/shared/pending-stage-delivery.ts
58009
+ var PENDING_STAGE_MESSAGE_LIMIT = 50;
58010
+ var PENDING_STAGE_UNDELIVERABLE_NOTIFICATION_PREFIX = "atomic-pending-stage-undeliverable";
58011
+ function queueStageMessage(messages2, input2, senderGroup, runGroup, stageIdentity) {
58012
+ if (normalizeDeliveryGroup(senderGroup) !== normalizeDeliveryGroup(runGroup)) {
58013
+ return { ok: false, reason: "group_mismatch", runId: input2.runId, stageKey: input2.stageKey };
58014
+ }
58015
+ const messageId = input2.message.id;
58016
+ const queued = pendingStageMessagesFor(messages2, input2.runId, input2.stageKey, stageIdentity);
58017
+ const existing = messages2.find((entry2) => entry2.runId === input2.runId && entry2.id === messageId);
58018
+ if (existing !== undefined) {
58019
+ if (pendingStageMessageSignature(existing, stageIdentity) !== pendingStageMessageSignature(input2, stageIdentity)) {
58020
+ return {
58021
+ ok: false,
58022
+ reason: "message_id_conflict",
58023
+ runId: input2.runId,
58024
+ stageKey: input2.stageKey,
58025
+ messageId
58026
+ };
58027
+ }
58028
+ const queuedPosition = queued.indexOf(existing);
58029
+ return {
58030
+ ok: true,
58031
+ messages: messages2,
58032
+ entry: existing,
58033
+ ...queuedPosition >= 0 ? { position: queuedPosition + 1 } : {},
58034
+ deduplicated: true
58035
+ };
58036
+ }
58037
+ if (queued.length >= PENDING_STAGE_MESSAGE_LIMIT) {
58038
+ return {
58039
+ ok: false,
58040
+ reason: "capacity",
58041
+ limit: PENDING_STAGE_MESSAGE_LIMIT,
58042
+ runId: input2.runId,
58043
+ stageKey: input2.stageKey
58044
+ };
58045
+ }
58046
+ const entry = {
58047
+ ...input2,
58048
+ id: messageId,
58049
+ ...stageIdentity !== undefined ? { stageId: stageIdentity.id } : {},
58050
+ ...stageIdentity?.replayKey !== undefined ? { stageReplayKey: stageIdentity.replayKey } : {},
58051
+ admissionOrder: nextAdmissionOrder(messages2, input2.runId),
58052
+ status: "queued"
58053
+ };
58054
+ return {
58055
+ ok: true,
58056
+ messages: [...messages2, entry],
58057
+ entry,
58058
+ position: queued.length + 1,
58059
+ deduplicated: false
58060
+ };
58061
+ }
58062
+ function pendingStageMessagesFor(messages2, runId, stageKey, stageIdentity) {
58063
+ 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);
58064
+ }
58065
+ function markPendingStageMessageDelivered(messages2, runId, stageKey, messageId, deliveredAt, stageIdentity) {
58066
+ return updateQueuedPendingStageMessage(messages2, runId, stageKey, messageId, stageIdentity, (entry) => ({
58067
+ ...entry,
58068
+ status: "delivered",
58069
+ deliveredAt
58070
+ }));
58071
+ }
58072
+ function markPendingStageMessageUndeliverable(messages2, runId, stageKey, messageId, reason, stageIdentity) {
58073
+ return updateQueuedPendingStageMessage(messages2, runId, stageKey, messageId, stageIdentity, (entry) => ({
58074
+ ...entry,
58075
+ status: "undeliverable",
58076
+ undeliverableReason: reason,
58077
+ undeliverableNotificationId: pendingStageUndeliverableNotificationId(entry)
58078
+ }));
58079
+ }
58080
+ function markPendingStageMessageUndeliverableNotified(messages2, runId, stageKey, messageId, notificationId, notifiedAt) {
58081
+ const index = messages2.findIndex((entry) => matchesPendingStage(entry, runId, stageKey) && entry.id === messageId && entry.status === "undeliverable" && entry.undeliverableNotificationId === notificationId && entry.undeliverableNotifiedAt === undefined);
58082
+ if (index < 0)
58083
+ return messages2;
58084
+ const next = [...messages2];
58085
+ next[index] = { ...next[index], undeliverableNotifiedAt: notifiedAt };
58086
+ return next;
58087
+ }
58088
+ function pendingStageUndeliverableNotificationId(entry) {
58089
+ return [
58090
+ PENDING_STAGE_UNDELIVERABLE_NOTIFICATION_PREFIX,
58091
+ encodeURIComponent(entry.runId),
58092
+ encodeURIComponent(entry.stageKey),
58093
+ encodeURIComponent(entry.id)
58094
+ ].join(":");
58095
+ }
58096
+ function updateQueuedPendingStageMessage(messages2, runId, stageKey, messageId, stageIdentity, update2) {
58097
+ const index = messages2.findIndex((entry) => matchesPendingStage(entry, runId, stageKey, stageIdentity) && entry.id === messageId && entry.status === "queued");
58098
+ if (index < 0)
58099
+ return messages2;
58100
+ const next = [...messages2];
58101
+ next[index] = update2(next[index]);
58102
+ return next;
58103
+ }
58104
+ function matchesPendingStage(entry, runId, stageKey, stageIdentity) {
58105
+ if (entry.runId !== runId)
58106
+ return false;
58107
+ if (stageIdentity === undefined)
58108
+ return entry.stageKey === stageKey;
58109
+ return entry.stageId === stageIdentity.id || entry.stageReplayKey !== undefined && entry.stageReplayKey === stageIdentity.replayKey || entry.stageId === undefined && stageIdentity.aliases.includes(entry.stageKey);
58110
+ }
58111
+ function nextAdmissionOrder(messages2, runId) {
58112
+ let greatest = 0;
58113
+ let legacyPosition = 0;
58114
+ for (const entry of messages2) {
58115
+ if (entry.runId !== runId)
58116
+ continue;
58117
+ legacyPosition += 1;
58118
+ greatest = Math.max(greatest, entry.admissionOrder ?? legacyPosition);
58119
+ }
58120
+ return greatest + 1;
58121
+ }
58122
+ function pendingStageMessageSignature(entry, stageIdentity) {
58123
+ const storedTarget = "status" in entry ? entry.stageReplayKey ?? entry.stageId : undefined;
58124
+ const { timestamp: transportTimestamp, ...logicalMessage } = entry.message;
58125
+ return stableJson({
58126
+ target: storedTarget ?? stageIdentity?.replayKey ?? stageIdentity?.id ?? entry.stageKey,
58127
+ sender: entry.senderReturnAddress ?? entry.from.id,
58128
+ message: {
58129
+ ...logicalMessage,
58130
+ expectsReply: logicalMessage.expectsReply ?? false,
58131
+ content: {
58132
+ ...logicalMessage.content,
58133
+ attachments: logicalMessage.content.attachments ?? []
58134
+ }
58135
+ }
58136
+ });
58137
+ }
58138
+ function stableJson(value) {
58139
+ return JSON.stringify(sortJsonValue(value));
58140
+ }
58141
+ function sortJsonValue(value) {
58142
+ if (Array.isArray(value))
58143
+ return value.map(sortJsonValue);
58144
+ if (typeof value !== "object" || value === null)
58145
+ return value;
58146
+ return Object.fromEntries(Object.entries(value).filter(([, nested]) => nested !== undefined).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortJsonValue(nested)]));
58147
+ }
58148
+ function normalizeDeliveryGroup(value) {
58149
+ if (typeof value !== "string")
58150
+ return "default";
58151
+ const trimmed = value.trim();
58152
+ return trimmed.length > 0 ? trimmed : "default";
58153
+ }
57934
58154
  // dist/builtin/workflows/src/shared/flat-string.ts
57935
58155
  function flattenTruncatedString(value) {
57936
58156
  return value.split("").join("");
@@ -58238,6 +58458,7 @@ function compactStage(stage) {
58238
58458
  inputRequest,
58239
58459
  notices,
58240
58460
  mcpScope: _mcpScope,
58461
+ pendingStageDeliveryAvailable: _pendingStageDeliveryAvailable,
58241
58462
  attemptedModels: _attemptedModels,
58242
58463
  modelAttempts: _modelAttempts,
58243
58464
  result: _result,
@@ -58493,6 +58714,133 @@ function createStoreContext(state = createStoreState()) {
58493
58714
  };
58494
58715
  }
58495
58716
 
58717
+ // dist/builtin/workflows/src/shared/store-pending-stage-delivery-methods.ts
58718
+ function createPendingStageDeliveryStoreMethods(context) {
58719
+ const transitions = new Map;
58720
+ const serialize = async (runId, transition) => {
58721
+ const previous2 = transitions.get(runId) ?? Promise.resolve();
58722
+ const result = previous2.catch(() => {
58723
+ return;
58724
+ }).then(transition);
58725
+ const settled = result.then(() => {
58726
+ return;
58727
+ }, () => {
58728
+ return;
58729
+ });
58730
+ transitions.set(runId, settled);
58731
+ settled.finally(() => {
58732
+ if (transitions.get(runId) === settled)
58733
+ transitions.delete(runId);
58734
+ });
58735
+ return await result;
58736
+ };
58737
+ return {
58738
+ async queueStageMessage(input2, senderGroup, runGroup, backend) {
58739
+ return await serialize(input2.runId, async () => {
58740
+ const run = context.findRun(input2.runId);
58741
+ if (run === undefined)
58742
+ return;
58743
+ const stageIdentity = resolvePendingStageIdentity(run, input2.stageKey);
58744
+ const result = queueStageMessage(run.pendingStageMessages ?? [], input2, senderGroup, runGroup, stageIdentity);
58745
+ if (result.ok && !result.deduplicated) {
58746
+ await persistTransition(backend, input2.runId, result.messages);
58747
+ run.pendingStageMessages = [...result.messages];
58748
+ context.bumpAndNotify();
58749
+ }
58750
+ return result;
58751
+ });
58752
+ },
58753
+ async validateLiveStageMessage(input2) {
58754
+ return await serialize(input2.runId, async () => {
58755
+ const run = context.findRun(input2.runId);
58756
+ if (run === undefined)
58757
+ return;
58758
+ const result = queueStageMessage(run.pendingStageMessages ?? [], input2, undefined, undefined, resolvePendingStageIdentity(run, input2.stageKey));
58759
+ if (!result.ok) {
58760
+ return result.reason === "message_id_conflict" ? { outcome: "message_id_conflict", messageId: result.messageId } : { outcome: "forward" };
58761
+ }
58762
+ if (!result.deduplicated)
58763
+ return { outcome: "forward" };
58764
+ if (result.entry.status === "delivered")
58765
+ return { outcome: "delivered" };
58766
+ if (result.entry.status === "undeliverable") {
58767
+ return { outcome: "undeliverable", reason: result.entry.undeliverableReason };
58768
+ }
58769
+ if (result.position === undefined) {
58770
+ throw new Error(`atomic-workflows: queued message ${input2.message.id} has no active position`);
58771
+ }
58772
+ return { outcome: "queued", position: result.position };
58773
+ });
58774
+ },
58775
+ pendingStageMessagesFor(runId, stageKey) {
58776
+ const run = context.findRun(runId);
58777
+ return pendingStageMessagesFor(run?.pendingStageMessages ?? [], runId, stageKey, run === undefined ? undefined : resolvePendingStageIdentity(run, stageKey));
58778
+ },
58779
+ async markPendingStageMessageDelivered(runId, stageKey, messageId, deliveredAt, backend) {
58780
+ return await serialize(runId, async () => {
58781
+ const run = context.findRun(runId);
58782
+ if (run === undefined)
58783
+ return false;
58784
+ const current = run.pendingStageMessages ?? [];
58785
+ const next = markPendingStageMessageDelivered(current, runId, stageKey, messageId, deliveredAt, resolvePendingStageIdentity(run, stageKey));
58786
+ if (next === current)
58787
+ return false;
58788
+ await persistTransition(backend, runId, next);
58789
+ run.pendingStageMessages = [...next];
58790
+ context.bumpAndNotify();
58791
+ return true;
58792
+ });
58793
+ },
58794
+ async markPendingStageMessageUndeliverable(runId, stageKey, messageId, reason, backend) {
58795
+ return await serialize(runId, async () => {
58796
+ const run = context.findRun(runId);
58797
+ if (run === undefined)
58798
+ return false;
58799
+ const current = run.pendingStageMessages ?? [];
58800
+ const next = markPendingStageMessageUndeliverable(current, runId, stageKey, messageId, reason, resolvePendingStageIdentity(run, stageKey));
58801
+ if (next === current)
58802
+ return false;
58803
+ await persistTransition(backend, runId, next);
58804
+ run.pendingStageMessages = [...next];
58805
+ context.bumpAndNotify();
58806
+ return true;
58807
+ });
58808
+ },
58809
+ async markPendingStageMessageUndeliverableNotified(runId, stageKey, messageId, notificationId, notifiedAt, backend) {
58810
+ return await serialize(runId, async () => {
58811
+ const run = context.findRun(runId);
58812
+ if (run === undefined)
58813
+ return false;
58814
+ const current = run.pendingStageMessages ?? [];
58815
+ const next = markPendingStageMessageUndeliverableNotified(current, runId, stageKey, messageId, notificationId, notifiedAt);
58816
+ if (next === current)
58817
+ return false;
58818
+ await persistTransition(backend, runId, next);
58819
+ run.pendingStageMessages = [...next];
58820
+ context.bumpAndNotify();
58821
+ return true;
58822
+ });
58823
+ }
58824
+ };
58825
+ }
58826
+ function resolvePendingStageIdentity(run, stageKey) {
58827
+ const exactIds = run.stages.filter((stage2) => stage2.id === stageKey);
58828
+ const candidates = exactIds.length > 0 ? exactIds : run.stages.filter((stage2) => stage2.name === stageKey);
58829
+ if (candidates.length !== 1)
58830
+ return;
58831
+ const stage = candidates[0];
58832
+ return {
58833
+ id: stage.id,
58834
+ ...stage.replayKey !== undefined ? { replayKey: stage.replayKey } : {},
58835
+ aliases: stage.id === stage.name ? [stage.id] : [stage.id, stage.name]
58836
+ };
58837
+ }
58838
+ async function persistTransition(backend, runId, messages2) {
58839
+ if (!await backend.persistPendingStageMessages(runId, messages2)) {
58840
+ throw new Error(`atomic-workflows: durable workflow ${runId} is unavailable for pending-stage persistence`);
58841
+ }
58842
+ }
58843
+
58496
58844
  // dist/builtin/workflows/src/shared/store-prompt-methods.ts
58497
58845
  function createPromptStoreMethods(context) {
58498
58846
  const { state } = context;
@@ -59407,6 +59755,7 @@ function createStore() {
59407
59755
  const context = createStoreContext();
59408
59756
  return {
59409
59757
  ...createRunStoreMethods(context),
59758
+ ...createPendingStageDeliveryStoreMethods(context),
59410
59759
  ...createStageStoreMethods(context),
59411
59760
  ...createToolNodeStoreMethods(context),
59412
59761
  ...createPromptStoreMethods(context)
@@ -60148,6 +60497,381 @@ ${formatValidationErrors(errors)}`);
60148
60497
  }
60149
60498
  return resolved;
60150
60499
  }
60500
+ // dist/builtin/workflows/src/shared/workflow-failures-signals.ts
60501
+ function asRecord2(value) {
60502
+ return value !== null && typeof value === "object" ? value : undefined;
60503
+ }
60504
+ function field2(value, key2) {
60505
+ return asRecord2(value)?.[key2];
60506
+ }
60507
+ function safeField(value, key2) {
60508
+ try {
60509
+ return field2(value, key2);
60510
+ } catch {
60511
+ return;
60512
+ }
60513
+ }
60514
+ function nonZeroExitCode(value) {
60515
+ if (typeof value === "number")
60516
+ return Number.isFinite(value) && value !== 0;
60517
+ if (typeof value !== "string")
60518
+ return false;
60519
+ const parsed = Number(value.trim());
60520
+ return Number.isFinite(parsed) && parsed !== 0;
60521
+ }
60522
+ function nonEmptyProcessOutput(value) {
60523
+ if (typeof value === "string")
60524
+ return value.length > 0;
60525
+ if (value instanceof ArrayBuffer)
60526
+ return value.byteLength > 0;
60527
+ return ArrayBuffer.isView(value) && value.byteLength > 0;
60528
+ }
60529
+ function findProcessFailureError(value, seen, depth) {
60530
+ if (value === null || typeof value !== "object" || depth >= 8 || seen.has(value))
60531
+ return;
60532
+ seen.add(value);
60533
+ if (nonZeroExitCode(safeField(value, "exitCode")))
60534
+ return value;
60535
+ if (nonEmptyProcessOutput(safeField(value, "stdout")))
60536
+ return value;
60537
+ if (nonEmptyProcessOutput(safeField(value, "stderr")))
60538
+ return value;
60539
+ for (const key2 of ["cause", "error", "response", "body"]) {
60540
+ const selected = findProcessFailureError(safeField(value, key2), seen, depth + 1);
60541
+ if (selected !== undefined)
60542
+ return selected;
60543
+ }
60544
+ const diagnostics = safeField(value, "diagnostics");
60545
+ if (Array.isArray(diagnostics)) {
60546
+ for (const diagnostic of diagnostics) {
60547
+ const selected = findProcessFailureError(safeField(diagnostic, "error") ?? diagnostic, seen, depth + 1);
60548
+ if (selected !== undefined)
60549
+ return selected;
60550
+ }
60551
+ }
60552
+ const errors = safeField(value, "errors");
60553
+ if (!Array.isArray(errors))
60554
+ return;
60555
+ for (const error of errors) {
60556
+ const selected = findProcessFailureError(error, seen, depth + 1);
60557
+ if (selected !== undefined)
60558
+ return selected;
60559
+ }
60560
+ return;
60561
+ }
60562
+ function selectProcessFailureError(error) {
60563
+ return findProcessFailureError(error, new Set, 0) ?? error;
60564
+ }
60565
+ function hasProcessFailureEvidence(error) {
60566
+ return findProcessFailureError(error, new Set, 0) !== undefined;
60567
+ }
60568
+ function stringField4(value, key2) {
60569
+ const raw = field2(value, key2);
60570
+ return typeof raw === "string" && raw.length > 0 ? raw : undefined;
60571
+ }
60572
+ function errorMessage3(error) {
60573
+ const structuredMessage = structuredErrorMessage(error);
60574
+ if (structuredMessage !== undefined)
60575
+ return structuredMessage;
60576
+ if (error instanceof Error && typeof error.message === "string")
60577
+ return error.message;
60578
+ if (typeof error === "string")
60579
+ return error;
60580
+ return String(error);
60581
+ }
60582
+ function errorName2(error) {
60583
+ return error instanceof Error ? error.name : stringField4(error, "name");
60584
+ }
60585
+ function structuredErrorMessage(error) {
60586
+ return stringField4(error, "errorMessage") ?? stringField4(error, "message") ?? stringField4(error, "statusText");
60587
+ }
60588
+ function integerFrom2(value) {
60589
+ if (typeof value === "number" && Number.isInteger(value))
60590
+ return value;
60591
+ if (typeof value !== "string" || value.trim().length === 0)
60592
+ return;
60593
+ const parsed = Number(value.trim());
60594
+ return Number.isInteger(parsed) ? parsed : undefined;
60595
+ }
60596
+ function numberFrom(value) {
60597
+ if (typeof value === "number" && Number.isFinite(value))
60598
+ return value;
60599
+ if (typeof value !== "string" || value.trim().length === 0)
60600
+ return;
60601
+ const parsed = Number(value.trim());
60602
+ return Number.isFinite(parsed) ? parsed : undefined;
60603
+ }
60604
+ function retryAfterHeaderMs(value) {
60605
+ const numeric = numberFrom(value);
60606
+ if (numeric !== undefined && numeric >= 0)
60607
+ return Math.round(numeric * 1000);
60608
+ if (typeof value !== "string" || value.trim().length === 0)
60609
+ return;
60610
+ const dateMs = Date.parse(value);
60611
+ if (!Number.isFinite(dateMs))
60612
+ return;
60613
+ return Math.max(0, dateMs - Date.now());
60614
+ }
60615
+ function retryAfterMsFrom(error) {
60616
+ const directMs = numberFrom(field2(error, "retryAfterMs"));
60617
+ if (directMs !== undefined && directMs >= 0)
60618
+ return Math.round(directMs);
60619
+ const seconds = numberFrom(field2(error, "retryAfterSeconds"));
60620
+ if (seconds !== undefined && seconds >= 0)
60621
+ return Math.round(seconds * 1000);
60622
+ const retryAfter = retryAfterHeaderMs(field2(error, "retryAfter"));
60623
+ if (retryAfter !== undefined)
60624
+ return retryAfter;
60625
+ const retryAfterHeader = retryAfterHeaderMs(field2(error, "retry-after"));
60626
+ if (retryAfterHeader !== undefined)
60627
+ return retryAfterHeader;
60628
+ const headers = field2(error, "headers");
60629
+ const headerRecord = asRecord2(headers);
60630
+ const headerValue = headerRecord?.["retry-after"] ?? headerRecord?.["Retry-After"];
60631
+ return retryAfterHeaderMs(headerValue);
60632
+ }
60633
+ function structuredSignal2(error) {
60634
+ const status = integerFrom2(field2(error, "status")) ?? integerFrom2(field2(error, "statusCode")) ?? integerFrom2(field2(error, "httpStatus"));
60635
+ const rawCode = field2(error, "code");
60636
+ const code = typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : undefined;
60637
+ const name = errorName2(error);
60638
+ const stopReason = stringField4(error, "stopReason");
60639
+ const message = structuredErrorMessage(error);
60640
+ const retryAfterMs = retryAfterMsFrom(error);
60641
+ return {
60642
+ ...status !== undefined ? { status } : {},
60643
+ ...code !== undefined ? { code } : {},
60644
+ ...name !== undefined ? { name } : {},
60645
+ ...stopReason !== undefined ? { stopReason } : {},
60646
+ ...message !== undefined ? { message } : {},
60647
+ ...retryAfterMs !== undefined ? { retryAfterMs } : {}
60648
+ };
60649
+ }
60650
+ function causeOf2(error) {
60651
+ if (error instanceof Error)
60652
+ return error.cause;
60653
+ return field2(error, "cause");
60654
+ }
60655
+ function diagnosticErrors2(error) {
60656
+ const diagnostics = field2(error, "diagnostics");
60657
+ if (!Array.isArray(diagnostics))
60658
+ return [];
60659
+ const errors = [];
60660
+ for (const diagnostic of diagnostics) {
60661
+ const diagnosticError = field2(diagnostic, "error");
60662
+ errors.push(diagnosticError ?? diagnostic);
60663
+ }
60664
+ return errors;
60665
+ }
60666
+ function nestedProviderError(error) {
60667
+ return field2(error, "error") ?? field2(error, "response") ?? field2(error, "body");
60668
+ }
60669
+ function normalizeCode2(value) {
60670
+ if (value === undefined)
60671
+ return;
60672
+ return String(value).trim().toLowerCase().replaceAll("-", "_").replaceAll(" ", "_");
60673
+ }
60674
+ function httpStatusFromCode(value) {
60675
+ if (value === undefined)
60676
+ return;
60677
+ if (typeof value === "number") {
60678
+ return Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
60679
+ }
60680
+ const trimmed = value.trim();
60681
+ if (!/^\d{3}$/.test(trimmed))
60682
+ return;
60683
+ const parsed = Number(trimmed);
60684
+ return parsed >= 100 && parsed <= 599 ? parsed : undefined;
60685
+ }
60686
+ function codeEvidenceFrom(value) {
60687
+ const status = httpStatusFromCode(value);
60688
+ if (status !== undefined)
60689
+ return { kind: "wrapper_http_status", status };
60690
+ const normalized = normalizeCode2(value);
60691
+ return normalized !== undefined && normalized.length > 0 ? { kind: "semantic_code", normalized } : undefined;
60692
+ }
60693
+ function tokenize(value) {
60694
+ const tokens = [];
60695
+ let current = "";
60696
+ for (const char of value.toLowerCase()) {
60697
+ if (char >= "a" && char <= "z" || char >= "0" && char <= "9") {
60698
+ current += char;
60699
+ } else if (current.length > 0) {
60700
+ tokens.push(current);
60701
+ current = "";
60702
+ }
60703
+ }
60704
+ if (current.length > 0)
60705
+ tokens.push(current);
60706
+ return tokens;
60707
+ }
60708
+ function hasPhrase(tokens, phrase) {
60709
+ if (phrase.length === 0 || phrase.length > tokens.length)
60710
+ return false;
60711
+ for (let index = 0;index <= tokens.length - phrase.length; index += 1) {
60712
+ let matched = true;
60713
+ for (let offset = 0;offset < phrase.length; offset += 1) {
60714
+ if (tokens[index + offset] !== phrase[offset]) {
60715
+ matched = false;
60716
+ break;
60717
+ }
60718
+ }
60719
+ if (matched)
60720
+ return true;
60721
+ }
60722
+ return false;
60723
+ }
60724
+ function hasAnyPhrase(tokens, phrases) {
60725
+ return phrases.some((phrase) => hasPhrase(tokens, phrase));
60726
+ }
60727
+ function tokenNearAny(tokens, anchor, candidates, distance) {
60728
+ for (let index = 0;index < tokens.length; index += 1) {
60729
+ if (tokens[index] !== anchor)
60730
+ continue;
60731
+ const start = Math.max(0, index - distance);
60732
+ const end = Math.min(tokens.length - 1, index + distance);
60733
+ for (let cursor = start;cursor <= end; cursor += 1) {
60734
+ if (cursor !== index && candidates.has(tokens[cursor]))
60735
+ return true;
60736
+ }
60737
+ }
60738
+ return false;
60739
+ }
60740
+ function redactedSecretReplacement(prefix) {
60741
+ return `${prefix}[redacted]`;
60742
+ }
60743
+ function redactSensitiveText(value) {
60744
+ 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]");
60745
+ }
60746
+
60747
+ // dist/builtin/workflows/src/durable/tool-outcome.ts
60748
+ var TOOL_FAILURE_TEXT_LIMIT_BYTES = 16384;
60749
+ var TRUNCATION_PREFIX = `[workflow tool output truncated; showing final bytes]
60750
+ `;
60751
+ function safeField2(error, key2) {
60752
+ try {
60753
+ return field2(error, key2);
60754
+ } catch {
60755
+ return;
60756
+ }
60757
+ }
60758
+ function exposedText(error, key2) {
60759
+ const value = safeField2(error, key2);
60760
+ if (typeof value === "string")
60761
+ return value;
60762
+ try {
60763
+ if (value instanceof ArrayBuffer)
60764
+ return new TextDecoder().decode(value);
60765
+ if (ArrayBuffer.isView(value)) {
60766
+ return new TextDecoder().decode(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
60767
+ }
60768
+ } catch {
60769
+ return;
60770
+ }
60771
+ return;
60772
+ }
60773
+ function boundedSafeToolFailureText(value) {
60774
+ const redacted = redactSensitiveText(value);
60775
+ const bytes = new TextEncoder().encode(redacted);
60776
+ if (bytes.byteLength <= TOOL_FAILURE_TEXT_LIMIT_BYTES)
60777
+ return redacted;
60778
+ const prefix = new TextEncoder().encode(TRUNCATION_PREFIX);
60779
+ const tailLength = Math.max(0, TOOL_FAILURE_TEXT_LIMIT_BYTES - prefix.byteLength);
60780
+ let start = bytes.byteLength - tailLength;
60781
+ const decoder = new TextDecoder("utf-8", { fatal: true });
60782
+ while (start < bytes.byteLength) {
60783
+ try {
60784
+ return TRUNCATION_PREFIX + decoder.decode(bytes.slice(start));
60785
+ } catch {
60786
+ start += 1;
60787
+ }
60788
+ }
60789
+ return TRUNCATION_PREFIX.slice(0, TOOL_FAILURE_TEXT_LIMIT_BYTES);
60790
+ }
60791
+ function safeErrorText(error) {
60792
+ try {
60793
+ return String(error);
60794
+ } catch {
60795
+ return "Tool callback failed";
60796
+ }
60797
+ }
60798
+ function normalizeWorkflowToolError(error) {
60799
+ error = selectProcessFailureError(error);
60800
+ const exitCode = safeField2(error, "exitCode");
60801
+ const stdout = exposedText(error, "stdout");
60802
+ const stderr = exposedText(error, "stderr");
60803
+ let message;
60804
+ let name;
60805
+ try {
60806
+ message = errorMessage3(error);
60807
+ } catch {
60808
+ message = safeErrorText(error);
60809
+ }
60810
+ try {
60811
+ name = errorName2(error) ?? "Error";
60812
+ } catch {
60813
+ name = "Error";
60814
+ }
60815
+ return {
60816
+ name: boundedSafeToolFailureText(name),
60817
+ message: boundedSafeToolFailureText(message),
60818
+ ...typeof exitCode === "number" && Number.isInteger(exitCode) ? { exitCode } : {},
60819
+ ...stdout !== undefined ? { stdout: boundedSafeToolFailureText(stdout) } : {},
60820
+ ...stderr !== undefined ? { stderr: boundedSafeToolFailureText(stderr) } : {}
60821
+ };
60822
+ }
60823
+ function workflowToolSuccess(value, attempts, cached) {
60824
+ return { ok: true, value, attempts, cached };
60825
+ }
60826
+ function workflowToolFailure(error, attempts, cached) {
60827
+ return { ok: false, error: normalizeWorkflowToolError(error), attempts, cached };
60828
+ }
60829
+ function workflowToolOutcomeFromValue(value) {
60830
+ if (value === null || typeof value !== "object" || Array.isArray(value))
60831
+ return;
60832
+ const candidate = value;
60833
+ if (!Number.isInteger(candidate.attempts) || typeof candidate.cached !== "boolean")
60834
+ return;
60835
+ if (candidate.ok === true && "value" in candidate)
60836
+ return candidate;
60837
+ const error = candidate.error;
60838
+ if (candidate.ok !== false || error === null || typeof error !== "object" || Array.isArray(error))
60839
+ return;
60840
+ const details = error;
60841
+ 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")
60842
+ return;
60843
+ return candidate;
60844
+ }
60845
+ function replayedWorkflowToolOutcome(outcome) {
60846
+ return { ...outcome, cached: true };
60847
+ }
60848
+
60849
+ // dist/builtin/workflows/src/durable/types.ts
60850
+ var DURABLE_TOOL_TOPOLOGY_VERSION = 1;
60851
+ var DURABLE_STAGE_TOPOLOGY_VERSION = 1;
60852
+ var DURABLE_BOUNDARY_TOPOLOGY_VERSION = 1;
60853
+
60854
+ // dist/builtin/workflows/src/durable/durable-hash.ts
60855
+ import { createHash as createHash6 } from "node:crypto";
60856
+ function durableHash(value) {
60857
+ const canonical = canonicalJsonString(value);
60858
+ const digest = createHash6("sha256").update(canonical).digest("hex");
60859
+ return `h${digest.slice(0, 32)}`;
60860
+ }
60861
+ function canonicalJsonString(value) {
60862
+ if (value === null || typeof value !== "object")
60863
+ return JSON.stringify(value);
60864
+ if (Array.isArray(value))
60865
+ return `[${value.map(canonicalJsonString).join(",")}]`;
60866
+ const object = value;
60867
+ const keys = Object.keys(object).sort();
60868
+ return `{${keys.map((key2) => `${JSON.stringify(key2)}:${canonicalJsonString(object[key2])}`).join(",")}}`;
60869
+ }
60870
+ // dist/builtin/workflows/src/durable/backend.ts
60871
+ function pendingStageMessagesForDurableRun(backend, logicalRunId, rootWorkflowId = logicalRunId) {
60872
+ return (backend.getWorkflow(rootWorkflowId)?.pendingStageMessages ?? []).filter((entry) => entry.runId === logicalRunId);
60873
+ }
60874
+
60151
60875
  // dist/builtin/workflows/src/runs/foreground/executor-child-helpers.ts
60152
60876
  function cloneWorkflowChildValue(value) {
60153
60877
  return structuredClone(value);
@@ -60201,11 +60925,6 @@ function workflowChildReplaySnapshot(alias, childResult) {
60201
60925
  };
60202
60926
  }
60203
60927
 
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
60928
  // dist/builtin/workflows/src/durable/stage-topology-validation.ts
60210
60929
  function immutableStageGroupError(stages) {
60211
60930
  const occurrenceError = promptOccurrenceIdentityError(stages);
@@ -60779,23 +61498,6 @@ function validatedInvocationRecords(input2) {
60779
61498
  return { stages, start };
60780
61499
  }
60781
61500
 
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
61501
  // dist/builtin/workflows/src/durable/child-invocation.ts
60800
61502
  function durableChildInvocationFingerprint(child, inputs) {
60801
61503
  return durableHash({
@@ -60804,354 +61506,6 @@ function durableChildInvocationFingerprint(child, inputs) {
60804
61506
  });
60805
61507
  }
60806
61508
 
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
61509
  // dist/builtin/workflows/src/durable/stage-topology.ts
61156
61510
  function activeStageTopology(backend, workflowId, replayKey) {
61157
61511
  const checkpoints = backend.listCheckpoints(workflowId);
@@ -61887,6 +62241,10 @@ function withMidSessionResumePrompt(stage, enabled) {
61887
62241
  });
61888
62242
  return stage;
61889
62243
  }
62244
+ function pendingStageIdForReplay(backend, workflowId, replayKey, stageName) {
62245
+ 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));
62246
+ return candidates.size === 1 ? candidates.values().next().value : undefined;
62247
+ }
61890
62248
  function createDurableStagePrimitive(input2) {
61891
62249
  return (name, options) => {
61892
62250
  const replayKey = input2.nextReplayKey(name);
@@ -61898,13 +62256,12 @@ function createDurableStagePrimitive(input2) {
61898
62256
  const session = input2.backend.getStageSession(input2.workflowId, replayKey);
61899
62257
  const isMidSessionResume = session?.sessionFile !== undefined;
61900
62258
  const topology = activeStageTopology(input2.backend, input2.workflowId, replayKey);
62259
+ const durableStageId = topology?.stageId ?? pendingStageIdForReplay(input2.backend, input2.workflowId, replayKey, name);
61901
62260
  const liveOptions = {
61902
62261
  ...options ?? {},
61903
62262
  durableReplayKey: replayKey,
61904
- ...topology !== undefined ? {
61905
- durableStageId: topology.stageId,
61906
- durableParentIds: [...topology.parentIds]
61907
- } : {},
62263
+ ...durableStageId !== undefined ? { durableStageId } : {},
62264
+ ...topology !== undefined ? { durableParentIds: [...topology.parentIds] } : {},
61908
62265
  ...isMidSessionResume ? {
61909
62266
  resumeFromSessionFile: session.sessionFile,
61910
62267
  durableAccumulatedDurationMs: session.durationMs ?? 0
@@ -63171,6 +63528,9 @@ class ScopedDurableBackend {
63171
63528
  this.persistent = inner.persistent;
63172
63529
  }
63173
63530
  registerWorkflow(_handle) {}
63531
+ persistPendingStageMessages(workflowId, messages2, logicalRunId = workflowId) {
63532
+ return this.inner.persistPendingStageMessages(this.scope.rootWorkflowId, messages2, logicalRunId);
63533
+ }
63174
63534
  recordCheckpoint(checkpoint) {
63175
63535
  this.inner.recordCheckpoint(this.remap(checkpoint));
63176
63536
  }
@@ -65308,6 +65668,7 @@ function appendStageStart(api, payload) {
65308
65668
  name: payload.name,
65309
65669
  parentIds: [...payload.parentIds],
65310
65670
  ...payload.model !== undefined ? { model: payload.model } : {},
65671
+ ...payload.pendingStageDeliveryAvailable !== undefined ? { pendingStageDeliveryAvailable: payload.pendingStageDeliveryAvailable } : {},
65311
65672
  ...payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {},
65312
65673
  ...payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {},
65313
65674
  ...payload.replayed !== undefined ? { replayed: payload.replayed } : {},
@@ -67034,6 +67395,7 @@ import { randomUUID as randomUUID9 } from "node:crypto";
67034
67395
 
67035
67396
  // dist/builtin/workflows/src/shared/intercom-group.ts
67036
67397
  import { randomUUID as randomUUID8 } from "node:crypto";
67398
+ var DEFAULT_INTERCOM_GROUP = "default";
67037
67399
  function workflowInvocationIntercomGroup(rootRunId) {
67038
67400
  return `workflow:${rootRunId}`;
67039
67401
  }
@@ -67043,6 +67405,12 @@ function normalizeAutoGroupSentinel(group) {
67043
67405
  const sentinel = group.trim().toLowerCase();
67044
67406
  return sentinel === "true" || sentinel === "auto" ? true : group;
67045
67407
  }
67408
+ function normalizeGroup(value) {
67409
+ if (typeof value !== "string")
67410
+ return DEFAULT_INTERCOM_GROUP;
67411
+ const trimmed = value.trim();
67412
+ return trimmed.length > 0 ? trimmed : DEFAULT_INTERCOM_GROUP;
67413
+ }
67046
67414
  function resolveStageGroup(stageOptions, workflowGroup) {
67047
67415
  if (!stageOptions)
67048
67416
  return workflowGroup;
@@ -67067,6 +67435,11 @@ function stageHasIntercomAccess(stageOptions) {
67067
67435
  return false;
67068
67436
  return true;
67069
67437
  }
67438
+ function stageCanUseWorkflowPendingStageRoute(stageOptions, workflowGroup) {
67439
+ if (!stageHasIntercomAccess(stageOptions) || stageOptions?.group === true)
67440
+ return false;
67441
+ return normalizeGroup(resolveStageGroup(stageOptions, workflowGroup)) === normalizeGroup(workflowGroup);
67442
+ }
67070
67443
 
67071
67444
  // dist/builtin/workflows/builtin/verification-usage.ts
67072
67445
  function fold_usage(results) {
@@ -67353,9 +67726,9 @@ function createRunBudgetController(input2) {
67353
67726
  function createParallelPrimitive(input2) {
67354
67727
  return async (steps, options = {}) => {
67355
67728
  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);
67729
+ const normalizeGroup2 = (value) => value.group === undefined ? value : { ...value, group: normalizeAutoGroupSentinel(value.group) };
67730
+ const normalizedOptions = normalizeGroup2(options);
67731
+ const normalizedSteps = steps.map(normalizeGroup2);
67359
67732
  const needsAutoGroup = normalizedOptions.group === true || normalizedSteps.some((step) => step.group === true);
67360
67733
  const autoGroup = needsAutoGroup ? randomUUID9() : undefined;
67361
67734
  const resolveAutoGroup = (value) => value.group === true && autoGroup ? { ...value, group: autoGroup } : value;
@@ -69230,7 +69603,7 @@ function createAdmittedToolExecutionTracker(options = {}) {
69230
69603
  const inFlight = new Set;
69231
69604
  const admissions = [];
69232
69605
  const failures = [];
69233
- let nextAdmissionOrder = 0;
69606
+ let nextAdmissionOrder2 = 0;
69234
69607
  let state = "OPEN";
69235
69608
  let closing;
69236
69609
  const abandonment = Promise.withResolvers();
@@ -69281,7 +69654,7 @@ function createAdmittedToolExecutionTracker(options = {}) {
69281
69654
  return { accepted: false, error, bindNode() {}, noteCancelled() {} };
69282
69655
  }
69283
69656
  const admission = {
69284
- admissionOrder: ++nextAdmissionOrder,
69657
+ admissionOrder: ++nextAdmissionOrder2,
69285
69658
  nodeId: undefined,
69286
69659
  failure: undefined,
69287
69660
  cancelled: false,
@@ -70623,6 +70996,150 @@ function createReplayStageContext(input2) {
70623
70996
  };
70624
70997
  }
70625
70998
 
70999
+ // dist/builtin/workflows/src/durable/run-owner-backend.ts
71000
+ function durableRootRunIdForRun(runs, runId) {
71001
+ return reciprocalWorkflowRootRunId(new Map(runs.map((run2) => [run2.id, run2])), runId);
71002
+ }
71003
+ function durableBackendForRun(backend, runs, runId) {
71004
+ const rootRunId = durableRootRunIdForRun(runs, runId);
71005
+ if (rootRunId === undefined)
71006
+ return;
71007
+ const runById = new Map(runs.map((run2) => [run2.id, run2]));
71008
+ if (rootRunId === runId)
71009
+ return backend;
71010
+ const scopes = [];
71011
+ let current = runById.get(runId);
71012
+ while (current !== undefined && current.id !== rootRunId) {
71013
+ const parent = current.parentRunId === undefined ? undefined : runById.get(current.parentRunId);
71014
+ const boundary = parent?.stages.find((stage) => stage.id === current?.parentStageId);
71015
+ if (parent === undefined || boundary?.replayKey === undefined)
71016
+ return;
71017
+ scopes.push(boundary.replayKey);
71018
+ current = parent;
71019
+ }
71020
+ if (current?.id !== rootRunId)
71021
+ return;
71022
+ let view = backend;
71023
+ for (const scopePrefix of scopes.reverse()) {
71024
+ view = new ScopedDurableBackend(view, { rootWorkflowId: rootRunId, scopePrefix });
71025
+ }
71026
+ return view;
71027
+ }
71028
+
71029
+ // dist/builtin/workflows/src/shared/pending-stage-route-capability.ts
71030
+ import { randomUUID as randomUUID10 } from "node:crypto";
71031
+ var routeCapabilities = new WeakMap;
71032
+ function workflowPendingStageRouteCapability(store2, runId) {
71033
+ let capabilities = routeCapabilities.get(store2);
71034
+ if (capabilities === undefined) {
71035
+ capabilities = new Map;
71036
+ routeCapabilities.set(store2, capabilities);
71037
+ }
71038
+ let capability = capabilities.get(runId);
71039
+ if (capability === undefined) {
71040
+ capability = randomUUID10();
71041
+ capabilities.set(runId, capability);
71042
+ }
71043
+ return capability;
71044
+ }
71045
+
71046
+ // dist/builtin/workflows/src/runs/foreground/pending-stage-delivery.ts
71047
+ var pendingDeliveryClaims = new WeakMap;
71048
+ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName) {
71049
+ let resolveReady;
71050
+ let rejectReady;
71051
+ let readyPromise;
71052
+ let drainError;
71053
+ let drainPromise;
71054
+ const pendingReady = () => {
71055
+ if (readyPromise === undefined) {
71056
+ readyPromise = new Promise((resolve23, reject) => {
71057
+ resolveReady = resolve23;
71058
+ rejectReady = reject;
71059
+ });
71060
+ }
71061
+ return readyPromise;
71062
+ };
71063
+ return {
71064
+ routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
71065
+ deliverPending(deliver) {
71066
+ if (drainPromise === undefined) {
71067
+ drainError = undefined;
71068
+ const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver);
71069
+ const drain2 = attempt.then(() => resolveReady?.(), (error) => {
71070
+ drainError = error;
71071
+ rejectReady?.(error);
71072
+ readyPromise = undefined;
71073
+ resolveReady = undefined;
71074
+ rejectReady = undefined;
71075
+ if (drainPromise === drain2)
71076
+ drainPromise = undefined;
71077
+ throw error;
71078
+ });
71079
+ drainPromise = drain2;
71080
+ }
71081
+ return drainPromise;
71082
+ },
71083
+ ready() {
71084
+ if (activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && (stageId === stageName || activeStore.pendingStageMessagesFor(runId, stageName).length === 0)) {
71085
+ return;
71086
+ }
71087
+ return drainError === undefined ? pendingReady() : Promise.reject(drainError);
71088
+ }
71089
+ };
71090
+ }
71091
+ async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver) {
71092
+ const candidateIds = new Set([
71093
+ ...activeStore.pendingStageMessagesFor(runId, stageId),
71094
+ ...activeStore.pendingStageMessagesFor(runId, stageName)
71095
+ ].map((entry) => entry.id));
71096
+ 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);
71097
+ const rootBackend = getDurableBackend();
71098
+ const backend = durableBackendForRun(rootBackend, activeStore.runs(), runId);
71099
+ if (backend === undefined) {
71100
+ throw new Error(`atomic-workflows: workflow run ${runId} has no durable owner for pending-stage delivery`);
71101
+ }
71102
+ for (const entry of entries) {
71103
+ const releaseClaim = claimPendingDelivery(activeStore, runId, entry.stageKey, entry.id);
71104
+ if (releaseClaim === undefined)
71105
+ continue;
71106
+ try {
71107
+ await deliver(toPendingStageSender(entry), entry.message);
71108
+ if (!await activeStore.markPendingStageMessageDelivered(runId, entry.stageKey, entry.id, new Date().toISOString(), backend)) {
71109
+ throw new Error(`atomic-workflows: pending-stage message ${entry.id} changed during delivery`);
71110
+ }
71111
+ } finally {
71112
+ releaseClaim();
71113
+ }
71114
+ }
71115
+ }
71116
+ function claimPendingDelivery(store2, runId, stageKey, messageId) {
71117
+ let claims = pendingDeliveryClaims.get(store2);
71118
+ if (claims === undefined) {
71119
+ claims = new Set;
71120
+ pendingDeliveryClaims.set(store2, claims);
71121
+ }
71122
+ const key2 = JSON.stringify([runId, stageKey, messageId]);
71123
+ if (claims.has(key2))
71124
+ return;
71125
+ claims.add(key2);
71126
+ return () => {
71127
+ claims?.delete(key2);
71128
+ if (claims?.size === 0)
71129
+ pendingDeliveryClaims.delete(store2);
71130
+ };
71131
+ }
71132
+ function toPendingStageSender(entry) {
71133
+ return {
71134
+ ...entry.from,
71135
+ cwd: entry.from.cwd ?? "",
71136
+ model: entry.from.model ?? "unknown",
71137
+ pid: entry.from.pid ?? 0,
71138
+ startedAt: entry.from.startedAt ?? entry.message.timestamp,
71139
+ lastActivity: entry.from.lastActivity ?? entry.message.timestamp
71140
+ };
71141
+ }
71142
+
70626
71143
  // dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts
70627
71144
  init_src();
70628
71145
 
@@ -71014,7 +71531,7 @@ function workflowSessionOptions(meta2) {
71014
71531
  workflow: { runId: meta2.runId, stageId: meta2.stageId, stageName: meta2.stageName }
71015
71532
  };
71016
71533
  }
71017
- function workflowOrchestrationContext(meta2, stageOptions) {
71534
+ function workflowOrchestrationContext(meta2, stageOptions, pendingStageDelivery) {
71018
71535
  const base = {
71019
71536
  kind: "workflow-stage",
71020
71537
  workflowRunId: meta2.runId,
@@ -71023,11 +71540,12 @@ function workflowOrchestrationContext(meta2, stageOptions) {
71023
71540
  constraints: { disableWorkflowTool: true }
71024
71541
  };
71025
71542
  const intercomGroup = stageHasIntercomAccess(stageOptions) ? resolveStageGroup(stageOptions, meta2.workflowIntercomGroup) : undefined;
71026
- return intercomGroup ? { ...base, intercomGroup } : base;
71543
+ const context = intercomGroup ? { ...base, intercomGroup } : base;
71544
+ return pendingStageDelivery === undefined ? context : { ...context, pendingStageDelivery };
71027
71545
  }
71028
- function stripWorkflowOnlyOptions(options, defaultSessionDir, meta2) {
71546
+ function stripWorkflowOnlyOptions(options, defaultSessionDir, meta2, pendingStageDelivery) {
71029
71547
  const classification = workflowSessionOptions(meta2);
71030
- const orchestrationContext = workflowOrchestrationContext(meta2, options);
71548
+ const orchestrationContext = workflowOrchestrationContext(meta2, options, pendingStageDelivery);
71031
71549
  if (!options) {
71032
71550
  return defaultSessionDir === undefined ? { orchestrationContext } : {
71033
71551
  orchestrationContext,
@@ -72393,7 +72911,7 @@ class StageSessionController {
72393
72911
  });
72394
72912
  let created;
72395
72913
  try {
72396
- created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta), {
72914
+ created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta, this.opts.pendingStageDelivery), {
72397
72915
  ...this.meta,
72398
72916
  stageOptions,
72399
72917
  ...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
@@ -72410,10 +72928,12 @@ class StageSessionController {
72410
72928
  throw this.staleCreationReason(startGeneration);
72411
72929
  }
72412
72930
  const session = attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
72413
- if (session instanceof Promise)
72414
- return await session;
72931
+ const attachedSession = session instanceof Promise ? await session : session;
72932
+ const pendingStageDeliveryReady = this.sharedOrchestrationContext?.pendingStageDelivery?.ready();
72933
+ if (pendingStageDeliveryReady !== undefined)
72934
+ await pendingStageDeliveryReady;
72415
72935
  await this.opts.onSessionReady?.();
72416
- return session;
72936
+ return attachedSession;
72417
72937
  }
72418
72938
  attachSession(created) {
72419
72939
  const result = normalizeSessionCreateResult(created);
@@ -73165,6 +73685,12 @@ function createWorkflowStageFactory(input2) {
73165
73685
  const replaySource = replayDecision.kind === "replay" ? replayDecision.source : undefined;
73166
73686
  const executeReplaySource = replayDecision.kind === "execute" ? replayDecision.source : undefined;
73167
73687
  const shouldReplay = replaySource !== undefined;
73688
+ const stageOptionsForContext = executeReplaySource?.sessionFile === undefined ? options : {
73689
+ ...options ?? {},
73690
+ context: options?.context ?? "fork",
73691
+ forkFromSessionFile: options?.forkFromSessionFile ?? executeReplaySource.sessionFile
73692
+ };
73693
+ const pendingStageDeliveryAvailable = stageCanUseWorkflowPendingStageRoute(stageOptionsForContext, input2.workflowIntercomGroup);
73168
73694
  const stageSnapshot = {
73169
73695
  id: stageId,
73170
73696
  name,
@@ -73172,6 +73698,7 @@ function createWorkflowStageFactory(input2) {
73172
73698
  status: shouldReplay ? "completed" : "pending",
73173
73699
  parentIds: Object.freeze(parentIds),
73174
73700
  toolEvents: [],
73701
+ pendingStageDeliveryAvailable,
73175
73702
  ...shouldReplay ? {
73176
73703
  startedAt: Date.now(),
73177
73704
  endedAt: Date.now(),
@@ -73200,11 +73727,6 @@ function createWorkflowStageFactory(input2) {
73200
73727
  throwIfWorkflowExitSelected: input2.exit.throwIfWorkflowExitSelected
73201
73728
  });
73202
73729
  }
73203
- const stageOptionsForContext = executeReplaySource?.sessionFile === undefined ? options : {
73204
- ...options ?? {},
73205
- context: options?.context ?? "fork",
73206
- forkFromSessionFile: options?.forkFromSessionFile ?? executeReplaySource.sessionFile
73207
- };
73208
73730
  const applyModelFallbackMeta = (meta2) => {
73209
73731
  if (meta2.model !== undefined)
73210
73732
  stageSnapshot.model = meta2.model;
@@ -73242,6 +73764,9 @@ function createWorkflowStageFactory(input2) {
73242
73764
  workflowIntercomGroup: input2.workflowIntercomGroup,
73243
73765
  signal: input2.signal,
73244
73766
  stageOptions: stageOptionsForContext,
73767
+ ...pendingStageDeliveryAvailable ? {
73768
+ pendingStageDelivery: createWorkflowPendingStageDelivery(input2.activeStore, input2.runId, stageId, name)
73769
+ } : {},
73245
73770
  models: input2.opts.models,
73246
73771
  executionMode: input2.opts.executionMode,
73247
73772
  defaultSessionDir: input2.opts.defaultSessionDir,
@@ -73367,6 +73892,7 @@ function createWorkflowStageFactory(input2) {
73367
73892
  name,
73368
73893
  parentIds: stageSnapshot.parentIds,
73369
73894
  ...stageReplayFields(stageSnapshot),
73895
+ pendingStageDeliveryAvailable,
73370
73896
  ts: stageSnapshot.startedAt ?? Date.now()
73371
73897
  });
73372
73898
  };
@@ -73729,6 +74255,9 @@ async function run(def, inputs, opts = {}) {
73729
74255
  status: "running",
73730
74256
  stages: [],
73731
74257
  toolNodes: [],
74258
+ pendingStageMessages: [
74259
+ ...pendingStageMessagesForDurableRun(rootBackend, runId, opts.parentRun?.rootRunId ?? runId)
74260
+ ],
73732
74261
  startedAt: Date.now(),
73733
74262
  ...opts.parentRun !== undefined ? {
73734
74263
  parentRunId: opts.parentRun.runId,