@bastani/atomic 0.9.40-alpha.2 → 0.9.41-alpha.1

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 (296) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +1 -1
  3. package/dist/builtin/intercom/CHANGELOG.md +26 -0
  4. package/dist/builtin/intercom/README.md +1 -1
  5. package/dist/builtin/intercom/broker/broker.ts +24 -21
  6. package/dist/builtin/intercom/broker/client.ts +97 -6
  7. package/dist/builtin/intercom/broker/list-reply.ts +53 -0
  8. package/dist/builtin/intercom/index.bundle.mjs +278 -46
  9. package/dist/builtin/intercom/package.json +1 -1
  10. package/dist/builtin/intercom/recoverable-disconnect.ts +27 -1
  11. package/dist/builtin/intercom/types.ts +8 -1
  12. package/dist/builtin/mcp/package.json +1 -1
  13. package/dist/builtin/subagents/CHANGELOG.md +45 -0
  14. package/dist/builtin/subagents/README.md +14 -0
  15. package/dist/builtin/subagents/package.json +1 -1
  16. package/dist/builtin/subagents/src/extension/index.bundle.mjs +99 -19
  17. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  18. package/dist/builtin/web-access/package.json +1 -1
  19. package/dist/builtin/workflows/CHANGELOG.md +44 -0
  20. package/dist/builtin/workflows/README.md +2 -0
  21. package/dist/builtin/workflows/package.json +1 -1
  22. package/dist/builtin/workflows/src/authoring.d.ts +1 -1
  23. package/dist/builtin/workflows/src/durable/journal/internal.d.ts +16 -0
  24. package/dist/builtin/workflows/src/durable/journal/legacy-journal-tables.d.ts +9 -0
  25. package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +6 -0
  26. package/dist/builtin/workflows/src/extension/index.bundle.mjs +441 -90
  27. package/dist/builtin/workflows/src/index.js +226 -34
  28. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +17 -1
  29. package/dist/cli/credential-print.d.ts.map +1 -1
  30. package/dist/cli/credential-print.js +1 -1
  31. package/dist/cli/credential-print.js.map +1 -1
  32. package/dist/config.d.ts +1 -0
  33. package/dist/config.d.ts.map +1 -1
  34. package/dist/config.js +1 -0
  35. package/dist/config.js.map +1 -1
  36. package/dist/core/agent-session-extension-bindings.d.ts +2 -1
  37. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  38. package/dist/core/agent-session-extension-bindings.js +33 -18
  39. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  40. package/dist/core/agent-session-methods.d.ts +2 -1
  41. package/dist/core/agent-session-methods.d.ts.map +1 -1
  42. package/dist/core/agent-session-methods.js.map +1 -1
  43. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  44. package/dist/core/agent-session-prompt.js +114 -21
  45. package/dist/core/agent-session-prompt.js.map +1 -1
  46. package/dist/core/agent-session-runtime.d.ts +1 -1
  47. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  48. package/dist/core/agent-session-runtime.js +6 -0
  49. package/dist/core/agent-session-runtime.js.map +1 -1
  50. package/dist/core/agent-session-state.d.ts +19 -1
  51. package/dist/core/agent-session-state.d.ts.map +1 -1
  52. package/dist/core/agent-session-state.js +41 -6
  53. package/dist/core/agent-session-state.js.map +1 -1
  54. package/dist/core/auth-storage-backends.d.ts +3 -1
  55. package/dist/core/auth-storage-backends.d.ts.map +1 -1
  56. package/dist/core/auth-storage-backends.js +79 -12
  57. package/dist/core/auth-storage-backends.js.map +1 -1
  58. package/dist/core/client-identity.d.ts +8 -0
  59. package/dist/core/client-identity.d.ts.map +1 -0
  60. package/dist/core/client-identity.js +16 -0
  61. package/dist/core/client-identity.js.map +1 -0
  62. package/dist/core/compaction/planner-outcome.d.ts.map +1 -1
  63. package/dist/core/compaction/planner-outcome.js +2 -1
  64. package/dist/core/compaction/planner-outcome.js.map +1 -1
  65. package/dist/core/execution-model-router.d.ts +18 -0
  66. package/dist/core/execution-model-router.d.ts.map +1 -1
  67. package/dist/core/execution-model-router.js +14 -8
  68. package/dist/core/execution-model-router.js.map +1 -1
  69. package/dist/core/extension-oauth-refresh-rejection.d.ts +12 -0
  70. package/dist/core/extension-oauth-refresh-rejection.d.ts.map +1 -0
  71. package/dist/core/extension-oauth-refresh-rejection.js +70 -0
  72. package/dist/core/extension-oauth-refresh-rejection.js.map +1 -0
  73. package/dist/core/extension-startup-failure.d.ts +30 -0
  74. package/dist/core/extension-startup-failure.d.ts.map +1 -0
  75. package/dist/core/extension-startup-failure.js +62 -0
  76. package/dist/core/extension-startup-failure.js.map +1 -0
  77. package/dist/core/extensions/context-types.d.ts +2 -0
  78. package/dist/core/extensions/context-types.d.ts.map +1 -1
  79. package/dist/core/extensions/context-types.js.map +1 -1
  80. package/dist/core/extensions/provider-types.d.ts +2 -0
  81. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  82. package/dist/core/extensions/provider-types.js.map +1 -1
  83. package/dist/core/extensions/runner-context.d.ts +1 -0
  84. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  85. package/dist/core/extensions/runner-context.js +8 -0
  86. package/dist/core/extensions/runner-context.js.map +1 -1
  87. package/dist/core/extensions/runner.d.ts +1 -0
  88. package/dist/core/extensions/runner.d.ts.map +1 -1
  89. package/dist/core/extensions/runner.js +3 -0
  90. package/dist/core/extensions/runner.js.map +1 -1
  91. package/dist/core/extensions/runtime-types.d.ts +1 -0
  92. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  93. package/dist/core/extensions/runtime-types.js.map +1 -1
  94. package/dist/core/extensions/workflow-run-control-hub.d.ts +1 -0
  95. package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -1
  96. package/dist/core/extensions/workflow-run-control-hub.js +3 -0
  97. package/dist/core/extensions/workflow-run-control-hub.js.map +1 -1
  98. package/dist/core/extensions/workflow-run-control.d.ts +8 -0
  99. package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
  100. package/dist/core/extensions/workflow-run-control.js.map +1 -1
  101. package/dist/core/model-fallback-failures.d.ts.map +1 -1
  102. package/dist/core/model-fallback-failures.js +12 -0
  103. package/dist/core/model-fallback-failures.js.map +1 -1
  104. package/dist/core/model-resolver-defaults.js +1 -1
  105. package/dist/core/model-resolver-defaults.js.map +1 -1
  106. package/dist/core/model-runtime-streaming.d.ts.map +1 -1
  107. package/dist/core/model-runtime-streaming.js +9 -3
  108. package/dist/core/model-runtime-streaming.js.map +1 -1
  109. package/dist/core/model-runtime.d.ts +5 -0
  110. package/dist/core/model-runtime.d.ts.map +1 -1
  111. package/dist/core/model-runtime.js +6 -0
  112. package/dist/core/model-runtime.js.map +1 -1
  113. package/dist/core/provider-composer-internal.d.ts +6 -5
  114. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  115. package/dist/core/provider-composer-internal.js +13 -2
  116. package/dist/core/provider-composer-internal.js.map +1 -1
  117. package/dist/core/sdk.d.ts.map +1 -1
  118. package/dist/core/sdk.js +12 -4
  119. package/dist/core/sdk.js.map +1 -1
  120. package/dist/core/storage/session/sql-session-store.d.ts +35 -0
  121. package/dist/core/storage/session/sql-session-store.d.ts.map +1 -1
  122. package/dist/core/storage/session/sql-session-store.js +158 -42
  123. package/dist/core/storage/session/sql-session-store.js.map +1 -1
  124. package/dist/core/structured-output/deadline.d.ts +40 -0
  125. package/dist/core/structured-output/deadline.d.ts.map +1 -0
  126. package/dist/core/structured-output/deadline.js +110 -0
  127. package/dist/core/structured-output/deadline.js.map +1 -0
  128. package/dist/core/structured-output/index.d.ts.map +1 -1
  129. package/dist/core/structured-output/index.js +103 -47
  130. package/dist/core/structured-output/index.js.map +1 -1
  131. package/dist/core/structured-output/rejection-detail.d.ts +9 -0
  132. package/dist/core/structured-output/rejection-detail.d.ts.map +1 -0
  133. package/dist/core/structured-output/rejection-detail.js +129 -0
  134. package/dist/core/structured-output/rejection-detail.js.map +1 -0
  135. package/dist/core/structured-output/types.d.ts +8 -1
  136. package/dist/core/structured-output/types.d.ts.map +1 -1
  137. package/dist/core/structured-output/types.js.map +1 -1
  138. package/dist/core/tasks/completion.d.ts +7 -1
  139. package/dist/core/tasks/completion.d.ts.map +1 -1
  140. package/dist/core/tasks/completion.js +28 -6
  141. package/dist/core/tasks/completion.js.map +1 -1
  142. package/dist/core/tasks/contracts.d.ts +6 -1
  143. package/dist/core/tasks/contracts.d.ts.map +1 -1
  144. package/dist/core/tasks/contracts.js.map +1 -1
  145. package/dist/core/tasks/pause.d.ts +2 -1
  146. package/dist/core/tasks/pause.d.ts.map +1 -1
  147. package/dist/core/tasks/pause.js +3 -2
  148. package/dist/core/tasks/pause.js.map +1 -1
  149. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  150. package/dist/core/tools/bash-pty-native.js +10 -5
  151. package/dist/core/tools/bash-pty-native.js.map +1 -1
  152. package/dist/core/tools/bash.d.ts.map +1 -1
  153. package/dist/core/tools/bash.js +16 -32
  154. package/dist/core/tools/bash.js.map +1 -1
  155. package/dist/core/tools/kill.d.ts.map +1 -1
  156. package/dist/core/tools/kill.js +17 -3
  157. package/dist/core/tools/kill.js.map +1 -1
  158. package/dist/core/tools/shell-task-render.d.ts +55 -0
  159. package/dist/core/tools/shell-task-render.d.ts.map +1 -0
  160. package/dist/core/tools/shell-task-render.js +123 -0
  161. package/dist/core/tools/shell-task-render.js.map +1 -0
  162. package/dist/core/tools/shell-task-status.d.ts +52 -0
  163. package/dist/core/tools/shell-task-status.d.ts.map +1 -0
  164. package/dist/core/tools/shell-task-status.js +184 -0
  165. package/dist/core/tools/shell-task-status.js.map +1 -0
  166. package/dist/core/tools/structured-output.d.ts +5 -0
  167. package/dist/core/tools/structured-output.d.ts.map +1 -1
  168. package/dist/core/tools/structured-output.js +3 -0
  169. package/dist/core/tools/structured-output.js.map +1 -1
  170. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  171. package/dist/extensions/codemode/execute.js +134 -57
  172. package/dist/extensions/codemode/execute.js.map +1 -1
  173. package/dist/extensions/mcp/config.d.ts.map +1 -1
  174. package/dist/extensions/mcp/config.js +3 -2
  175. package/dist/extensions/mcp/config.js.map +1 -1
  176. package/dist/index-extensions.d.ts +1 -0
  177. package/dist/index-extensions.d.ts.map +1 -1
  178. package/dist/index-extensions.js +3 -0
  179. package/dist/index-extensions.js.map +1 -1
  180. package/dist/index.d.ts +3 -1
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +3 -1
  183. package/dist/index.js.map +1 -1
  184. package/dist/main.d.ts.map +1 -1
  185. package/dist/main.js +19 -6
  186. package/dist/main.js.map +1 -1
  187. package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
  188. package/dist/modes/interactive/components/task-row.js +11 -1
  189. package/dist/modes/interactive/components/task-row.js.map +1 -1
  190. package/dist/modes/interactive/interactive-auth-routing.js +12 -10
  191. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  192. package/dist/modes/interactive/interactive-extension-custom-ui.js +20 -30
  193. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  194. package/dist/modes/interactive/interactive-extension-dialogs.js +23 -96
  195. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  196. package/dist/modes/interactive/interactive-extension-runtime.js +7 -8
  197. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  198. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  199. package/dist/modes/interactive/interactive-input-handling.js +27 -4
  200. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  201. package/dist/modes/interactive/interactive-mode-base.d.ts +20 -10
  202. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  203. package/dist/modes/interactive/interactive-mode-base.js +40 -5
  204. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  205. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  206. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  207. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  208. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  209. package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -4
  210. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  211. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  212. package/dist/modes/interactive/interactive-mode-types.d.ts +4 -1
  213. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  214. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  215. package/dist/modes/interactive/interactive-prompt-restore.d.ts +3 -0
  216. package/dist/modes/interactive/interactive-prompt-restore.d.ts.map +1 -1
  217. package/dist/modes/interactive/interactive-prompt-restore.js +9 -1
  218. package/dist/modes/interactive/interactive-prompt-restore.js.map +1 -1
  219. package/dist/modes/interactive/interactive-prompt-turn.js +30 -2
  220. package/dist/modes/interactive/interactive-prompt-turn.js.map +1 -1
  221. package/dist/modes/interactive/interactive-queueing.js +43 -8
  222. package/dist/modes/interactive/interactive-queueing.js.map +1 -1
  223. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  224. package/dist/modes/interactive/interactive-startup.js +12 -3
  225. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  226. package/dist/modes/interactive/theme/color-utils.d.ts +6 -1
  227. package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
  228. package/dist/modes/interactive/theme/color-utils.js +39 -17
  229. package/dist/modes/interactive/theme/color-utils.js.map +1 -1
  230. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  231. package/dist/modes/interactive/theme/theme-class.js +2 -2
  232. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  233. package/dist/modes/interactive/theme/theme-tokens.d.ts +6 -0
  234. package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -1
  235. package/dist/modes/interactive/theme/theme-tokens.js +7 -3
  236. package/dist/modes/interactive/theme/theme-tokens.js.map +1 -1
  237. package/dist/modes/interactive-engine/isolated-auth.d.ts +3 -0
  238. package/dist/modes/interactive-engine/isolated-auth.d.ts.map +1 -1
  239. package/dist/modes/interactive-engine/isolated-auth.js +13 -1
  240. package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
  241. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  242. package/dist/modes/interactive-engine/isolated-runtime.js +11 -2
  243. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  244. package/dist/modes/interactive-engine/remote-model-catalog.d.ts +8 -0
  245. package/dist/modes/interactive-engine/remote-model-catalog.d.ts.map +1 -1
  246. package/dist/modes/interactive-engine/remote-model-catalog.js +54 -0
  247. package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
  248. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  249. package/dist/modes/rpc/rpc-command-handler.js +4 -13
  250. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  251. package/dist/modes/rpc/rpc-model-catalog.d.ts +9 -0
  252. package/dist/modes/rpc/rpc-model-catalog.d.ts.map +1 -0
  253. package/dist/modes/rpc/rpc-model-catalog.js +19 -0
  254. package/dist/modes/rpc/rpc-model-catalog.js.map +1 -0
  255. package/dist/modes/rpc/rpc-provider-auth.d.ts.map +1 -1
  256. package/dist/modes/rpc/rpc-provider-auth.js +2 -6
  257. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  258. package/dist/modes/rpc/rpc-types.d.ts +6 -0
  259. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  260. package/dist/modes/rpc/rpc-types.js.map +1 -1
  261. package/dist/utils/changelog.d.ts +6 -0
  262. package/dist/utils/changelog.d.ts.map +1 -1
  263. package/dist/utils/changelog.js +11 -0
  264. package/dist/utils/changelog.js.map +1 -1
  265. package/dist/utils/clipboard.d.ts.map +1 -1
  266. package/dist/utils/clipboard.js +4 -0
  267. package/dist/utils/clipboard.js.map +1 -1
  268. package/dist/utils/tools-manager.d.ts.map +1 -1
  269. package/dist/utils/tools-manager.js +3 -2
  270. package/dist/utils/tools-manager.js.map +1 -1
  271. package/docs/background-tasks.md +5 -3
  272. package/docs/codemode.md +2 -2
  273. package/docs/custom-provider/oauth.md +42 -1
  274. package/docs/custom-provider/registration.md +2 -0
  275. package/docs/environment-variables.md +1 -0
  276. package/docs/extensions/api-reference.md +3 -4
  277. package/docs/extensions/authoring.md +1 -1
  278. package/docs/extensions/events.md +1 -1
  279. package/docs/providers.md +3 -3
  280. package/docs/rpc/protocol.md +4 -2
  281. package/docs/sdk/reference.md +2 -0
  282. package/docs/sdk/structured-decisions.md +7 -5
  283. package/docs/sdk.md +5 -2
  284. package/docs/settings.md +4 -2
  285. package/docs/subagents/reference.md +1 -1
  286. package/docs/subagents.md +15 -1
  287. package/docs/themes/reference.md +3 -1
  288. package/docs/usage.md +3 -1
  289. package/docs/workflows/api-reference.md +28 -0
  290. package/docs/workflows/operations.md +2 -2
  291. package/npm-shrinkwrap.json +32 -32
  292. package/package.json +3 -3
  293. package/dist/core/provider-attribution.d.ts +0 -4
  294. package/dist/core/provider-attribution.d.ts.map +0 -1
  295. package/dist/core/provider-attribution.js +0 -87
  296. package/dist/core/provider-attribution.js.map +0 -1
@@ -18,6 +18,10 @@
18
18
  * reconnect, or the previous attempt's session is still being torn down), the
19
19
  * same bounded retry that recovers a lost socket clears it (#3163). A refusal
20
20
  * whose code repeats identically on retry is not recoverable.
21
+ *
22
+ * A broker that accepts the socket but does not answer a registration in time is
23
+ * saturated, not gone. Its timeout is recoverable for the same reason, and a
24
+ * background relay that sees it keeps quiet unless the outage persists.
21
25
  */
22
26
 
23
27
  import { IntercomLiveRouteRefusedError } from "./live-route-refusal.js";
@@ -47,8 +51,18 @@ export class IntercomClientDisconnectedError extends Error implements Recoverabl
47
51
  }
48
52
  }
49
53
 
54
+ /** Raised when the broker accepted the socket but did not answer a registration within its bound. */
55
+ export class IntercomBrokerTimeoutError extends Error implements RecoverableDisconnectMarker {
56
+ readonly intercomRecoverableDisconnect = true;
57
+
58
+ constructor(message: string, options?: ErrorOptions) {
59
+ super(message, options);
60
+ this.name = "IntercomBrokerTimeoutError";
61
+ }
62
+ }
63
+
50
64
  /**
51
- * True for an `IntercomClientDisconnectedError` or a transient
65
+ * True for an `IntercomClientDisconnectedError`, an `IntercomBrokerTimeoutError`, or a transient
52
66
  * `IntercomLiveRouteRefusedError`, directly or as a bounded `cause` ancestor.
53
67
  */
54
68
  export function isRecoverableIntercomDisconnect(error: unknown): boolean {
@@ -56,8 +70,20 @@ export function isRecoverableIntercomDisconnect(error: unknown): boolean {
56
70
  for (let depth = 0; depth <= MAX_CAUSE_DEPTH; depth += 1) {
57
71
  if (!(current instanceof Error)) return false;
58
72
  if (current instanceof IntercomClientDisconnectedError) return true;
73
+ if (current instanceof IntercomBrokerTimeoutError) return true;
59
74
  if (current instanceof IntercomLiveRouteRefusedError) return current.transient;
60
75
  current = current.cause;
61
76
  }
62
77
  return false;
63
78
  }
79
+
80
+ /** True for an `IntercomBrokerTimeoutError`, directly or as a bounded `cause` ancestor. */
81
+ export function isIntercomBrokerTimeout(error: unknown): boolean {
82
+ let current: unknown = error;
83
+ for (let depth = 0; depth <= MAX_CAUSE_DEPTH; depth += 1) {
84
+ if (!(current instanceof Error)) return false;
85
+ if (current instanceof IntercomBrokerTimeoutError) return true;
86
+ current = current.cause;
87
+ }
88
+ return false;
89
+ }
@@ -70,6 +70,8 @@ export interface SessionDirectory {
70
70
  readonly sessions: SessionInfo[];
71
71
  readonly workflowStages: WorkflowStageRosterEntry[];
72
72
  readonly workflowFutureStages: WorkflowFutureStageRosterEntry[];
73
+ /** The peeked workflow invocation group exists but is visible only to its members. */
74
+ readonly restricted?: true;
73
75
  }
74
76
 
75
77
  export interface WorkflowStageRosterAnnouncement {
@@ -186,6 +188,8 @@ export type ClientMessage =
186
188
  | { type: "pending_stage_notification_result"; requestId: string; delivered: boolean }
187
189
  | {
188
190
  type: "register_pending_stage_route";
191
+ /** When present, the broker answers with `pending_stage_route_registered` once the route is applied. */
192
+ requestId?: string;
189
193
  runId: string;
190
194
  group: string;
191
195
  capability: string;
@@ -230,10 +234,12 @@ export type BrokerMessage =
230
234
  supervisorSessionId?: string;
231
235
  /** #3761: echoed only to a client that advertised it; that client may now send `received`. */
232
236
  acknowledgesReceipt?: true;
237
+ /** This broker acknowledges a `register_pending_stage_route` that carries a `requestId`; absent on older brokers. */
238
+ acknowledgesPendingStageRoutes?: true;
233
239
  }
234
240
  | { type: "registration_failed"; reason: string; code?: LiveWorkflowStageRouteRefusalCode }
235
241
  | { type: "question_target"; messageId: string; attemptId: string; sessionId: string }
236
- | { type: "sessions"; requestId: string; sessions: SessionInfo[]; workflowStages?: WorkflowStageRosterEntry[]; workflowFutureStages?: WorkflowFutureStageRosterEntry[] }
242
+ | { type: "sessions"; requestId: string; sessions: SessionInfo[]; workflowStages?: WorkflowStageRosterEntry[]; workflowFutureStages?: WorkflowFutureStageRosterEntry[]; restricted?: true }
237
243
  | { type: "groups"; requestId: string; groups: GroupSummary[] }
238
244
  | { type: "membership_ack"; requestId: string; groups: string[] }
239
245
  | { type: "supervisor_authorized"; requestId: string; capability: string; supervisorSessionId: string; childName: string }
@@ -251,6 +257,7 @@ export type BrokerMessage =
251
257
  live?: boolean;
252
258
  }
253
259
  | { type: "live_workflow_stage_route_registered"; requestId: string }
260
+ | { type: "pending_stage_route_registered"; requestId: string }
254
261
  /** A dormant route's run was resumed by another process, which now owns the run's routes (#3760). */
255
262
  | { type: "pending_stage_route_revoked"; runId: string }
256
263
  | { type: "presence_update"; session: SessionInfo }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.40-alpha.2",
3
+ "version": "0.9.41-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic's pi-compatible MCP integration for server connections, OAuth, tools, resources, and terminal management.",
6
6
  "contributors": [
@@ -2,6 +2,51 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.41-alpha.1] - 2026-10-21
6
+
7
+ ### Added
8
+
9
+ - Added a `resumeInFlight` subagent setting (`"never"`, `"ask"`, or `"auto"`, default `"never"`) for recovery of paused and quit subagents that are awaiting resume. `ask` confirms once, listing each subagent, and `auto` resumes each from its own session, with its completion reaching the session that launched it; `never` leaves them for a manual `resume`. It applies when Atomic starts or a session is resumed, to that session's own subagents, never to workflow-stage children, and an invalid value is reported and treated as `never` ([#3827](https://github.com/bastani-inc/atomic/issues/3827)).
10
+
11
+ ### Changed
12
+
13
+ - Quitting a subagent now behaves like quitting a workflow. The `quit` and `pause` results say the child is paused · awaiting resume and name `{ action: "resume", id: "<child-id>" }`; the parent's completion notice says the same, with the typed `quit` or `pause` stop reason instead of `parent-handoff` and without "This execution has ended". `{ action: "status", id }` reports a paused or quit child as paused · awaiting resume with its resume call, and `{ action: "status" }` lists every such child, including after Atomic restarts. Launch cards of such children show `‖ Paused · awaiting resume` (or `‖ Quit · paused · awaiting resume`) instead of `(resumable)`.
14
+
15
+ ### Fixed
16
+
17
+ - A subagent with `model: "auto"` no longer waits indefinitely on a slow routing model. Each routing inference now stops after the `httpIdleTimeoutMs` deadline (10 minutes by default), and the subagent runs on the current chat model when it satisfies the routing constraints ([#3806](https://github.com/bastani-inc/atomic/issues/3806))
18
+
19
+ ## [0.9.40] - 2026-10-20
20
+
21
+ ### Breaking Changes
22
+
23
+ - Removed the `kill` action from the `subagent` tool. Replace `subagent({ action: "kill", id })` with `subagent({ action: "quit", id })`, which stops the child gracefully and keeps it resumable. Calls with `action: "kill"` or the earlier `action: "interrupt"` are rejected with an error that names `quit` as the replacement ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
24
+
25
+ ### Added
26
+
27
+ - Added workflow-style run control to the `subagent` tool: `pause` stops a child and holds its queued messages until resume, `quit` stops it gracefully, and `resume` continues it from its own saved session under the same child id, Intercom name, and group. `pause` and `quit` accept `all: true` and also reach parallel children still queued behind their concurrency limit, which then start only when resumed, and `resume` accepts an optional `message`: a paused, quit, or interrupted child receives it once as its next prompt and then continues where it left off, and a completed or failed child receives it as one fresh prompt. Without `message`, the child is asked to continue where it left off, including a completed or failed child. A resumed child of a parallel run waits for a slot under that run's concurrency limit, and keeps its `worktree: true` worktree until it finishes; a paused or quit child holds no slot, and its worktree is kept only while it has uncommitted or untracked changes or commits that are not in the run's base. Resume continues in a kept worktree, or recreates a removed one from the run's base; a resume that fails keeps the worktree, its changes, and its branch. Steering and follow-up messages a child had queued when it was paused or quit are delivered once, in order, when it resumes, before the resume `message`. An SDK session without a task host records its subagents the same way, so `pause`, `resume` and `quit` work there too, also after the session is reopened; a child it resumes runs in the background and reports through a completion notice. A child paused or quit before it read its task or the resume message keeps them, and resume delivers them. `id` accepts the child id, task id, Intercom name, or a single-child run id ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
28
+ - Paused, quit, interrupted, completed, and failed children can be resumed, including children of a session you closed or switched away from (Atomic exit or crash, `/new`, `/resume` to another session, `/fork`). Children cancelled for good (owner or batch cancellation, a `/tasks` stop, the removed `kill` action) or reported gone after a restart are terminal, and `resume` on them returns an error that says why ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
29
+ - Background subagent launch cards now show the child's latest state, also after you reopen the session (`/resume` or `atomic --session <id>`) or view a workflow stage's transcript: running, paused, paused with its workflow stage, quit, or interrupted (resumable), completed, failed, or terminal (killed, gone after a restart, or its workflow stage ended). Expanding a card shows the end of the child's saved transcript. A resumed child continues in its original card, marked resumed, and replayed `pause`, `resume`, and `quit` calls render as their results, or as errors when they were rejected ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
30
+
31
+ ### Changed
32
+
33
+ - Updated the bundled Cua Driver skill to upstream `cua-driver-rs-v0.36.0`. It now starts with an efficient loop: targeted `get_window_state` reads with `query`, acting by `element_token`, batching actions with `run_steps` or `run_script`, re-reading only changes with `since:"latest"`, and verifying at checkpoints instead of after every action. It also covers opening local files with `launch_app`, browser fallbacks when browser tools refuse in the background, and macOS editor recipes.
34
+ - When a workflow stage closes for good (the stage finished, or its run ended or was cancelled), every subagent it launched becomes terminal, whether running, paused, quit, completed, or failed, and `resume` on them returns an error that says their workflow stage ended. A quit child stays resumable only while the session or stage that launched it can still resume it. `quit` also accepts a child paused with its workflow stage, and `pause` reports such a child as already paused. Pausing or quitting a workflow run, Atomic exiting, switching sessions, and an interrupted stage leave the stage's children resumable: `resume` continues them, and resuming the run after Atomic restarts restores them with the stage ([#3760](https://github.com/bastani-inc/atomic/issues/3760)). A stage blocked by a recoverable failure, such as a rate limit or provider outage that leaves its run resumable, keeps its paused and quit subagents resumable until the run is killed, cancelled, or ends without staying resumable; then they end with the stage.
35
+
36
+ ### Fixed
37
+
38
+ - Background subagents that were still running when Atomic exited are now relaunched from their own sessions when you resume the session (`atomic --session <id>` or `/resume`) or resume a workflow stage that launched them. They keep their original Intercom name and group and get fresh supervisor authorization, and Intercom messages sent to it by any session in its group wait for it from the moment the resumed session starts (or, for a stage's subagent, from the moment the interrupted run becomes addressable) until it has been restored. Only the session that launched a child restores it: a fork of that session (`/fork`, `atomic --fork`, or a branched session) copies the child's record but never relaunches, waits for, or reports the child. If a child cannot be restored, the resumed agent is told explicitly that it is gone, once: the child is then recorded as gone, so later resumes neither retry it nor repeat the notice ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
39
+ - On Windows, removing a `worktree: true` worktree now removes its directory. Its `node_modules` junction is unlinked first, so Git for Windows no longer leaves the directory behind, and older Git versions no longer delete the main checkout's `node_modules` through the junction.
40
+ - A `worktree: true` child resumed after an Atomic restart saves its tracked and untracked edits as a patch in its run's `worktree-diffs` directory before its worktree is removed, as a child of a fresh run does.
41
+ - Resuming a `worktree: true` child whose worktree was already removed, such as a completed child, now restores the edits it saved as a patch before it continues, so its earlier work is not lost. Each run saves its patches in its own `worktree-diffs/<run id>` directory, and each execution of a resumed child writes its own patch (`task-<n>-<agent>.<execution>.patch`) instead of overwriting the earlier one. Patches now include binary changes.
42
+ - A subagent that an SDK session without a task host resumed now stops when that session closes, as the original launch does. Reopening the session relaunches it automatically, as it does a task-host child, and the steering and follow-up messages it had queued and not read are delivered once, in order. A task-host child whose session or workflow stage closes now keeps its unread steering and follow-up messages the same way, and restoring or resuming it delivers them once, in order, instead of losing them.
43
+ - Opening a fork no longer changes the original session's subagent launch cards back to an older state copied into the fork, such as showing a completed child as running.
44
+ - `pause` or `quit` of a subagent that completes just before the stop takes effect now reports that it completed instead of "Paused", and Intercom messages sent to it are no longer held until a resume ([#3784](https://github.com/bastani-inc/atomic/pull/3784)).
45
+ - A parallel subagent paused or quit while it still waited for a free slot can now be resumed after Atomic restarts, and one still waiting when Atomic exited starts when its session reopens, instead of being reported unrestorable or gone. It starts as a new launch under the same child id, Intercom name, and group, with its original agent definition, task, working directory or worktree, model, and skills, and a `context: "fork"` child starts on the parent conversation its launch branched; if that branch can no longer be reopened, the child is reported gone rather than started without it. This holds in task-host and SDK sessions alike ([#3784](https://github.com/bastani-inc/atomic/pull/3784)).
46
+ - Subagents of a workflow stage whose run is killed while it waits, after Atomic restarts, for `/workflow resume` now end with the run: `resume` returns "its workflow stage ended", their cards no longer show them as resumable, and reopening the stage's session no longer restores them ([#3784](https://github.com/bastani-inc/atomic/pull/3784)).
47
+ - A subagent relaunched from its own session after Atomic restarts, or resumed with `resume`, now runs on the agent definition it was launched with: a user agent is no longer replaced by a project agent of the same name. A child launched with `context: "fork"` also keeps its Intercom bridge instructions under `intercomBridge.mode: "fork-only"`. Children recorded by an earlier version keep the previous lookup ([#3784](https://github.com/bastani-inc/atomic/pull/3784)).
48
+ - A queued parallel subagent that inherited its parent's model and thinking level now keeps them when it starts after Atomic restarts, instead of taking whatever model and thinking level the parent switched to meanwhile. If that model is no longer available, resume reports the child as gone instead of starting it on the parent's current model. A child restored or resumed from its own session also falls back to the model it was launched with, not the parent's current one, and a child launched outside any Intercom group no longer joins a group the parent joined later ([#3784](https://github.com/bastani-inc/atomic/pull/3784)).
49
+
5
50
  ## [0.9.40-alpha.1] - 2026-10-20
6
51
 
7
52
  ### Breaking Changes
@@ -620,6 +620,20 @@ Subagent configuration controls discovery, parallel limits, session storage, con
620
620
 
621
621
  Running capacity is selected when a parent's first child is created. Restart Atomic after changing this setting to apply the new capacity.
622
622
 
623
+ ### `resumeInFlight`
624
+
625
+ ```json
626
+ { "resumeInFlight": "ask" }
627
+ ```
628
+
629
+ Recovery of paused and quit subagents that are awaiting resume when a session starts or is resumed, using the same values as the workflow setting of that name:
630
+
631
+ - `never` (default): leave them listed under "Awaiting resume" for a manual `resume`.
632
+ - `ask`: confirm once, listing each subagent by name and id. No leaves them awaiting resume; without a UI it behaves like `never`.
633
+ - `auto`: resume each from its own session. Its result reaches the session that launched it.
634
+
635
+ Starting Atomic and resuming a session recover children; a reload, new session, or fork does not. Only children launched by the session being started or resumed are affected; workflow-stage children are never resumed this way. Any other value is reported and treated as `never`.
636
+
623
637
  ### `defaultSessionDir`
624
638
 
625
639
  ```json
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.40-alpha.2",
3
+ "version": "0.9.41-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [
@@ -8467,6 +8467,7 @@ var SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
8467
8467
  var SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
8468
8468
  var SUBAGENT_TERMINAL_ORDERING_BARRIER_EVENT = "subagent:terminal-ordering-barrier";
8469
8469
  var SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT = "subagent:result-intercom-delivery";
8470
+ var RESUME_IN_FLIGHT_MODES = ["ask", "auto", "never"];
8470
8471
  // dist/builtin/subagents/src/shared/types-depth.ts
8471
8472
  function isWorkflowStageOrchestrationContext(ctx) {
8472
8473
  return ctx.orchestrationContext?.kind === "workflow-stage";
@@ -10558,7 +10559,11 @@ function retainedTaskOutput(ownerId, taskId) {
10558
10559
 
10559
10560
  // dist/builtin/subagents/src/runs/foreground/task-execution.ts
10560
10561
  function subagentTaskResultLabel(result) {
10561
- return result.kind === "cancelled" && result.cause === "user" ? "killed (non-resumable)" : result.kind;
10562
+ if (result.kind === "cancelled" && result.cause === "user")
10563
+ return "killed (non-resumable)";
10564
+ if (result.kind === "cancelled" && (result.cause === "pause" || result.cause === "quit"))
10565
+ return "paused · awaiting resume";
10566
+ return result.kind;
10562
10567
  }
10563
10568
  function subagentTaskResponseText(response) {
10564
10569
  const outcomes = response.kind === "parallel" ? response.slots.map((slot) => slot.outcome) : [response];
@@ -10887,7 +10892,7 @@ ${launch.message}` : input.task,
10887
10892
  });
10888
10893
  const stopped = takeSubagentChildStop(context.ref.taskId);
10889
10894
  const stoppedByControl = stopped !== undefined && child.status === "interrupted";
10890
- const stoppedByStagePause = !stoppedByControl && child.status === "interrupted" && context.signal.aborted && context.signal.reason === "parent-handoff";
10895
+ const stoppedByStagePause = !stoppedByControl && child.status === "interrupted" && context.signal.aborted && context.signal.reason === "pause";
10891
10896
  const endedForGood = ownerClosed() && input.recordChild?.ownerEndedForGood?.() === true;
10892
10897
  if (stopped !== undefined && !stoppedByControl)
10893
10898
  unparkRunWorktree(runId, index);
@@ -10921,7 +10926,7 @@ ${launch.message}` : input.task,
10921
10926
  if (child.interrupted)
10922
10927
  return {
10923
10928
  kind: "cancelled",
10924
- cause: stoppedByControl || stoppedByStagePause || input.options.interruptSignal?.aborted ? "parent-handoff" : "owner-close",
10929
+ cause: stoppedByControl ? stopped === "quit" ? "quit" : "pause" : stoppedByStagePause ? "pause" : input.options.interruptSignal?.aborted ? "parent-handoff" : "owner-close",
10925
10930
  output
10926
10931
  };
10927
10932
  return child.status === "ok" ? { kind: "completed", output } : {
@@ -17474,7 +17479,7 @@ async function stopHostChild(deps, host, record, status) {
17474
17479
  const taskId = record.taskId;
17475
17480
  requestSubagentChildStop(taskId, status);
17476
17481
  parkRunWorktree(record.runId, record.index);
17477
- const cancelled = await host.cancelTask(taskId, "parent-handoff");
17482
+ const cancelled = await host.cancelTask(taskId, status === "quit" ? "quit" : "pause");
17478
17483
  if (!cancelled.ok) {
17479
17484
  unparkRunWorktree(record.runId, record.index);
17480
17485
  return cancelled.error.message;
@@ -17550,7 +17555,7 @@ async function stopChildren(deps, ctx, request) {
17550
17555
  continue;
17551
17556
  }
17552
17557
  children.push(childDetails(record, status));
17553
- lines.push(action === "pause" ? `Paused ${label(record)}. Its queued messages are held until resume; resume it with { action: "resume", id: "${record.childId}", message? }.` : `Quit ${label(record)}. It stays resumable with { action: "resume", id: "${record.childId}", message? }.`);
17558
+ lines.push(action === "pause" ? `Paused ${label(record)} · awaiting resume. Its queued messages are held until resume; resume it with { action: "resume", id: "${record.childId}", message? }.` : `Quit ${label(record)}: paused · awaiting resume, as a quit workflow run is. It stays resumable with { action: "resume", id: "${record.childId}", message? }.`);
17554
17559
  continue;
17555
17560
  }
17556
17561
  const stopped = stoppedAs(record);
@@ -17559,7 +17564,7 @@ async function stopChildren(deps, ctx, request) {
17559
17564
  releasePausedChildHold(key);
17560
17565
  await recordSubagentChildStatus(deps.pi, record, "quit");
17561
17566
  children.push(childDetails(record, "quit"));
17562
- lines.push(`Quit paused ${label(record)}. It stays resumable.`);
17567
+ lines.push(`Quit paused ${label(record)}: paused · awaiting resume. It stays resumable with { action: "resume", id: "${record.childId}", message? }.`);
17563
17568
  continue;
17564
17569
  }
17565
17570
  children.push(childDetails(record, stopped));
@@ -17605,6 +17610,18 @@ async function resumeChild(deps, ctx, request) {
17605
17610
  ...message ? { message } : {}
17606
17611
  });
17607
17612
  }
17613
+ function awaitingResumeLine(record) {
17614
+ const how = record.terminalStatus === "quit" ? "quit · paused · awaiting resume" : record.terminalStatus === SUBAGENT_CHILD_STAGE_PAUSED_STATUS ? "paused with its workflow stage · awaiting resume" : "paused · awaiting resume";
17615
+ return `${label(record)} ${how}. Resume it with { action: "resume", id: "${record.childId}", message? }.`;
17616
+ }
17617
+ function subagentChildrenAwaitingResume(ctx, id) {
17618
+ const records = ownedRecords(ctx);
17619
+ if (id?.trim()) {
17620
+ const resolved = resolveRecord(records, id);
17621
+ return typeof resolved === "object" && stoppedAs(resolved) ? [awaitingResumeLine(resolved)] : [];
17622
+ }
17623
+ return [...records.values()].filter((record) => stoppedAs(record)).map(awaitingResumeLine);
17624
+ }
17608
17625
  function controlSubagentChildren(deps, ctx, request) {
17609
17626
  if (request.all && request.id)
17610
17627
  return Promise.resolve(errorResult(request.action, "Pass either id or all: true, not both."));
@@ -17612,6 +17629,42 @@ function controlSubagentChildren(deps, ctx, request) {
17612
17629
  return Promise.resolve(errorResult(request.action, `${request.action} needs the id of a child, or all: true.`));
17613
17630
  return request.action === "resume" ? resumeChild(deps, ctx, request) : stopChildren(deps, ctx, { ...request, action: request.action });
17614
17631
  }
17632
+ async function resumeAwaitingSubagentChildren(deps, ctx, mode, isCurrent) {
17633
+ if (mode === "never" || ctx.isPresentationOnly === true)
17634
+ return;
17635
+ if (isSubagentChildSession(ctx) || isWorkflowStageOrchestrationContext(ctx))
17636
+ return;
17637
+ if (mode === "ask" && (ctx.hasUI === false || typeof ctx.ui?.confirm !== "function"))
17638
+ return;
17639
+ const notify = (message, type) => {
17640
+ try {
17641
+ ctx.ui?.notify?.(message, type);
17642
+ } catch {
17643
+ return;
17644
+ }
17645
+ };
17646
+ try {
17647
+ const awaiting = [...ownedRecords(ctx).values()].filter((record) => record.owner.kind === "session" && stoppedAs(record));
17648
+ if (awaiting.length === 0)
17649
+ return;
17650
+ if (mode === "ask" && !await ctx.ui.confirm("Resume interrupted subagents?", `${awaiting.length} interrupted subagent(s) can resume from their own sessions:
17651
+ ${awaiting.map((record) => `- ${label(record)}`).join(`
17652
+ `)}
17653
+ Resume now? Choose No to leave them awaiting resume; resume one later with subagent({ action: "resume", id }).`))
17654
+ return;
17655
+ for (const record of awaiting) {
17656
+ if (!isCurrent())
17657
+ return;
17658
+ const result = await controlSubagentChildren(deps, ctx, { action: "resume", id: record.childId });
17659
+ notify(result.content.map((part) => part.type === "text" ? part.text : "").join(`
17660
+ `), result.isError ? "warning" : "info");
17661
+ }
17662
+ } catch (error) {
17663
+ if (!isCurrent())
17664
+ return;
17665
+ notify(`Subagent startup resume failed: ${String(error)}. Use subagent({ action: "resume", id }) to retry.`, "warning");
17666
+ }
17667
+ }
17615
17668
 
17616
17669
  // dist/builtin/subagents/src/runs/foreground/subagent-executor.ts
17617
17670
  var MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete"]);
@@ -17693,6 +17746,7 @@ async function handleManagementRequest(input) {
17693
17746
  });
17694
17747
  }
17695
17748
  const targetTaskId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
17749
+ const awaitingResume = action === "status" ? subagentChildrenAwaitingResume(ctx, targetTaskId) : [];
17696
17750
  if (action === "status" && ctx.getAgentTaskHost && targetTaskId) {
17697
17751
  const host = ctx.getAgentTaskHost();
17698
17752
  const taskId = targetTaskId;
@@ -17706,7 +17760,9 @@ async function handleManagementRequest(input) {
17706
17760
  content: [
17707
17761
  {
17708
17762
  type: "text",
17709
- text: `${records.some((task) => task.execution.kind === "settled" && subagentTaskResultLabel(task.execution.result) === "killed (non-resumable)") ? `Killed. This child cannot be resumed. Underlying host records:
17763
+ text: `${awaitingResume.length > 0 ? `${awaitingResume.join(`
17764
+ `)}
17765
+ ` : ""}${records.some((task) => task.execution.kind === "settled" && subagentTaskResultLabel(task.execution.result) === "killed (non-resumable)") ? `Killed. This child cannot be resumed. Underlying host records:
17710
17766
  ` : ""}${JSON.stringify(records)}${settledOutput}`
17711
17767
  }
17712
17768
  ],
@@ -17720,14 +17776,28 @@ async function handleManagementRequest(input) {
17720
17776
  };
17721
17777
  }
17722
17778
  }
17779
+ if (targetTaskId && awaitingResume.length > 0)
17780
+ return {
17781
+ content: [{ type: "text", text: awaitingResume.join(`
17782
+ `) }],
17783
+ details: { mode: "management", results: [] }
17784
+ };
17723
17785
  if (action === "status") {
17724
17786
  const targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
17725
- const inProcess = inspectInProcessChildStatus(targetRunId);
17726
- if (inProcess)
17727
- return inProcess;
17728
17787
  const foreground = getForegroundControl(deps.state, targetRunId);
17729
- if (foreground)
17730
- return foregroundStatusResult(foreground);
17788
+ const live = inspectInProcessChildStatus(targetRunId) ?? (foreground ? foregroundStatusResult(foreground) : undefined);
17789
+ if (awaitingResume.length > 0) {
17790
+ const liveText = live?.content.map((part) => part.type === "text" ? part.text : "").join(`
17791
+ `);
17792
+ const text = [liveText, `Awaiting resume:
17793
+ ${awaitingResume.join(`
17794
+ `)}`].filter(Boolean).join(`
17795
+
17796
+ `);
17797
+ return { details: live?.details ?? { mode: "management", results: [] }, content: [{ type: "text", text }] };
17798
+ }
17799
+ if (live)
17800
+ return live;
17731
17801
  return {
17732
17802
  content: [
17733
17803
  {
@@ -19371,11 +19441,19 @@ function renderSubagentResult(result, options, theme) {
19371
19441
  // dist/builtin/subagents/src/extension/config.ts
19372
19442
  import * as fs19 from "node:fs";
19373
19443
  import { getAgentConfigPaths as getAgentConfigPaths5 } from "@bastani/atomic";
19444
+ function withoutInvalidResumeInFlight(config, configPath) {
19445
+ const value = config.resumeInFlight;
19446
+ if (value === undefined || RESUME_IN_FLIGHT_MODES.some((mode) => mode === value))
19447
+ return config;
19448
+ console.error(`Invalid subagent config '${configPath}': "resumeInFlight" must be "ask", "auto", or "never", got ${JSON.stringify(value)}`);
19449
+ const { resumeInFlight: _ignored, ...rest } = config;
19450
+ return rest;
19451
+ }
19374
19452
  function loadConfig() {
19375
19453
  for (const configPath of getAgentConfigPaths5("extensions", "subagent", "config.json")) {
19376
19454
  try {
19377
19455
  if (fs19.existsSync(configPath)) {
19378
- return JSON.parse(fs19.readFileSync(configPath, "utf-8"));
19456
+ return withoutInvalidResumeInFlight(JSON.parse(fs19.readFileSync(configPath, "utf-8")), configPath);
19379
19457
  }
19380
19458
  } catch (error) {
19381
19459
  console.error(`Failed to load subagent config from '${configPath}':`, error);
@@ -19664,9 +19742,9 @@ MANAGEMENT (use action field, omit agent/task/tasks):
19664
19742
  • { action: "update", agent: "code-analysis.custom-agent", config: { package: "analysis", ... } } - merge
19665
19743
  • { action: "delete", agent: "code-analysis.custom-agent" }
19666
19744
  CONTROL:
19667
- • { action: "status", id: "..." } - inspect an in-process run by id or prefix
19745
+ • { action: "status", id: "..." } - inspect an in-process run by id or prefix; a paused or quit child shows as paused · awaiting resume with its resume call, and { action: "status" } lists every such child
19668
19746
  • { action: "pause", id: "..." } / { action: "pause", all: true } - stop a running child and hold its queued messages until resume; it stays resumable
19669
- • { action: "quit", id: "..." } / { action: "quit", all: true } - stop a child gracefully (including a paused one); it stays resumable
19747
+ • { action: "quit", id: "..." } / { action: "quit", all: true } - stop a child gracefully (including a paused one), as a workflow quit does: it is paused · awaiting resume, not ended, and stays resumable
19670
19748
  • { action: "resume", id: "...", message?: "..." } - continue a paused, quit, interrupted, completed or failed child from its own session under the same id and Intercom name; message is delivered once as its next prompt, otherwise it continues where it left off. Children cancelled for good (owner or batch cancellation, the removed kill action), ended with their workflow stage (quit ones included), or reported gone cannot be resumed
19671
19749
  • id accepts the child id (<runId>:<index>), its task id, its Intercom name, or the run id of a single-child run. kill and interrupt were removed: use quit`;
19672
19750
 
@@ -19686,12 +19764,12 @@ function effectiveParallelTaskCount(tasks) {
19686
19764
  var SETTLED_VIEWS = {
19687
19765
  ok: { icon: "✓", label: "Completed", color: "success" },
19688
19766
  error: { icon: "✗", label: "Failed", color: "error" },
19689
- paused: { icon: "‖", label: "Paused (resumable)", color: "warning" },
19690
- quit: { icon: "■", label: "Quit (resumable)", color: "warning" },
19767
+ paused: { icon: "‖", label: "Paused · awaiting resume", color: "warning" },
19768
+ quit: { icon: "‖", label: "Quit · paused · awaiting resume", color: "warning" },
19691
19769
  interrupted: { icon: "○", label: "Interrupted (resumable)", color: "warning" },
19692
19770
  [SUBAGENT_CHILD_STAGE_PAUSED_STATUS]: {
19693
19771
  icon: "‖",
19694
- label: "Paused with its workflow stage (resumable)",
19772
+ label: "Paused with its workflow stage · awaiting resume",
19695
19773
  color: "warning"
19696
19774
  },
19697
19775
  killed: { icon: "✗", label: "Terminal · killed", color: "error" },
@@ -19797,7 +19875,7 @@ function renderSubagentToolResult(result, options, theme, context) {
19797
19875
  ${theme.fg("muted", `│ ${displayText2(line)}`)}`).join("") : ""
19798
19876
  ].join("");
19799
19877
  }
19800
- const state = observation.kind === "yielded" ? request?.action === "wait" ? "Still running in background" : "Launched in background" : observation.result.kind === "completed" ? "Completed" : observation.result.kind === "failed" ? "Failed" : subagentTaskResultLabel(observation.result) === "killed (non-resumable)" ? "Killed (non-resumable)" : "Stopped";
19878
+ const state = observation.kind === "yielded" ? request?.action === "wait" ? "Still running in background" : "Launched in background" : observation.result.kind === "completed" ? "Completed" : observation.result.kind === "failed" ? "Failed" : subagentTaskResultLabel(observation.result) === "killed (non-resumable)" ? "Killed (non-resumable)" : subagentTaskResultLabel(observation.result) === "paused · awaiting resume" ? "Paused · awaiting resume" : "Stopped";
19801
19879
  const icon = observation.kind === "yielded" ? "∀" : observation.result.kind === "completed" ? "✓" : observation.result.kind === "failed" ? "✗" : "○";
19802
19880
  const color = observation.kind === "yielded" ? "accent" : observation.result.kind === "failed" ? "error" : observation.result.kind === "completed" ? "success" : "warning";
19803
19881
  const identity = labels[index];
@@ -20326,6 +20404,8 @@ function registerSubagentExtension(pi) {
20326
20404
  holdRunningSubagentChildren(pi.events, ctx).catch(() => {
20327
20405
  return;
20328
20406
  });
20407
+ if (opened)
20408
+ resumeAwaitingSubagentChildren(executorDeps, ctx, config.resumeInFlight ?? "never", lifecycle.isCurrent);
20329
20409
  }
20330
20410
  });
20331
20411
  pi.on("session_recovery_restore", async (_event, ctx) => {
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.40] - 2026-10-20
8
+
9
+ ### Changed
10
+
11
+ - Curator summary drafts for Codex-only users now prefer `openai-codex/gpt-6.1-sol`, the `openai-codex` default, instead of `gpt-5.3-codex-spark`, which ChatGPT accounts can no longer use. `anthropic/claude-haiku-4-5` remains the first choice.
12
+
7
13
  ## [0.9.40-alpha.2] - 2026-10-20
8
14
 
9
15
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.9.40-alpha.2",
3
+ "version": "0.9.41-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
6
6
  "contributors": [
@@ -6,6 +6,50 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.9.41-alpha.1] - 2026-10-21
10
+
11
+ ### Added
12
+
13
+ - Added `schemaTimeoutMs` to workflow stage, task, chain, and parallel options: the wall-clock limit in milliseconds for each `structured_output` decision of a schema-backed item, covering its repair attempts, retries, and model fallbacks together. It defaults to the `httpIdleTimeoutMs` setting ([#3806](https://github.com/bastani-inc/atomic/issues/3806))
14
+
15
+ ### Changed
16
+
17
+ - Reopening `/workflow resume` is faster: the run list is kept between opens and rereads only the runs whose journal changed since the last open, including changes made by other Atomic processes. Whether another session still owns a run is checked when you select it.
18
+ - `/workflow connect` and `/workflow status` now list runs the way `/tasks` does. Active runs come before ended ones, with runs waiting for your input or blocked first, then running, then paused; ended runs follow with failed, cancelled, then completed. Within each group the newest run comes first, where before the `/workflow connect` list showed the oldest running run first ([#3824](https://github.com/bastani-inc/atomic/issues/3824)).
19
+
20
+ ### Fixed
21
+
22
+ - A workflow stage no longer stays stuck selecting its model when many workflows run at once. A stage with `model: "auto"` now waits at most five minutes for model selection, counting any wait for one of eight routing slots shared by every stage, so a burst of stages queues instead of overloading the router provider. When the wait ends, the stage runs on the current chat model if that model satisfies every routing constraint; otherwise it fails with an error that names the stage and the `model-resolution` startup phase, and its startup status reads `failed` instead of staying active. A failed selection is no longer remembered, so the next prompt on the same stage selects a model again, without launching a replacement workflow.
23
+ - After a blocked workflow run is resumed, Intercom sends to `workflow:<rootRunId>/**`, to stage patterns, and to stages that have not started yet are accepted and delivered again instead of failing with `Workflow execution for <runId> is retired`.
24
+ - In a long-running session, starting a workflow from a turn that an Intercom message started no longer fails with `Workflow execution for <runId> is retired; startup cleanup failed: …` after an earlier workflow run in the session has ended or been quit. The session's Intercom connection is now opened outside the workflow run that first needed it. The `is retired` error now names the run whose execution actually ended, not the run being started.
25
+ - A workflow stage whose fallback session fails to start because an extension's `session_start` failed under load, for example Intercom's `Broker failed to start within timeout` or `connect ECONNREFUSED`, now retries that session with the same-model retry budget and then moves on to its next fallback model, instead of failing the stage and letting fail-fast skip its sibling stages. Any other extension startup error still fails the stage at once. The stage error, model attempts, and fallback warnings now name each failing extension and its error rather than only `Extension startup failed`.
26
+ - When a workflow stage falls back to another model and that fallback session cannot start, the stage now closes the session it was replacing. Before, that session kept its session database open after the stage failed, and on Windows the file could not be deleted until the process exited.
27
+ - Workflow stage sessions now provide `ctx.ui.theme` and the other default UI members, so extensions that read `ctx.ui.theme.fg(...)` in `session_start`, such as `examples/extensions/status-line.ts`, no longer fail stage startup with `Extension startup failed` ([#3801](https://github.com/bastani-inc/atomic/issues/3801))
28
+ - Workflow inputs now reject integer and number values outside the `minimum`/`maximum` declared in the input schema, such as `count: 0` for `Type.Integer({ minimum: 1, maximum: 8 })`, when the run is started, instead of passing them to the workflow body. The error names the input and the violated bound ([#3812](https://github.com/bastani-inc/atomic/issues/3812)).
29
+ - A `ctx.parallel(..., { failFast: false })` call that has a failing step no longer loses the results of the steps that succeeded. The `AggregateError` it rejects with now carries `partialResults`, one entry per step in step order, holding each completed step's result and `undefined` for a step that failed. The `WorkflowParallelFailure` type describes it ([#3809](https://github.com/bastani-inc/atomic/issues/3809))
30
+ - A workflow stage's corrective prompt after a rejected `structured_output` result now names the failing paths and expected types, or reports that the tool arguments were not valid JSON, instead of only saying the response does not match the decision schema ([#3802](https://github.com/bastani-inc/atomic/issues/3802))
31
+ - Disposing a session right after a workflow run reports that it ended no longer leaves the run `running` in the workflow journal, with its lease released, for readers to report as crashed. `session.dispose()` now waits up to 10 seconds for runs that have ended but are still recording their ending, before it closes the journal, and it rejects naming the run when that ending still cannot be recorded. A run whose journal rejects the write of its `completed` status now retries it once, and reports it with an error notice and a rejected `waitForSettled` when it still fails, instead of failing in silence ([#3811](https://github.com/bastani-inc/atomic/issues/3811))
32
+ - A schema-backed workflow stage no longer stays `running` for hours inside one `structured_output` call when a slow model keeps generating without calling the tool. The decision now stops after the `httpIdleTimeoutMs` deadline (10 minutes by default) or the stage's `schemaTimeoutMs`, and the error that names the deadline and each attempt's duration reaches the model and the failed stage unchanged instead of being treated as a structured-output contract failure ([#3806](https://github.com/bastani-inc/atomic/issues/3806))
33
+
34
+ ## [0.9.40] - 2026-10-20
35
+
36
+ ### Added
37
+
38
+ - The workflow journal can be selected for one process with `ATOMIC_WORKFLOWS_JOURNAL`, `ATOMIC_STORAGE`, or Atomic's `--storage` and `--storage-file` flags, using the same JSON as the `workflows.journal` and `storage` settings. Setting `ATOMIC_WORKFLOWS_JOURNAL` together with `ATOMIC_WORKFLOW_JOURNAL_PATH` is rejected as a conflict ([#3783](https://github.com/bastani-inc/atomic/issues/3783)).
39
+
40
+ ### Changed
41
+
42
+ - Updated the bundled Impeccable skill to 4.7.0 with engine 0.1.16. Critique and audit can scan a running Electron, NW.js, CEF, or WebView2 app window through its debugging port (`impeccable detect --cdp 9222`), and critique runs its design review on iOS, Android, and adaptive projects instead of reporting an empty web scan as clean. New `straggler` and `unbalanced-heading` typography checks flag a paragraph ending on one word and a heading whose last line is a stub, and the detector raises fewer false alarms on hidden, screen-reader-only, and layered content. Decision and review pages follow the OS dark mode, `context` offers only workspaces that render a UI as targets, and the Claude Code design hook can be installed in your user settings instead of the project's. Live Mode now starts on LAN and Tailscale addresses over plain HTTP, copying works there when the clipboard API is unavailable, and an interrupted engine download cleans up after itself. Atomic's launcher still turns off the engine's choice reports and update check by default.
43
+
44
+ ### Fixed
45
+
46
+ - Resuming a workflow restores the background subagents its stages launched and delivers the stages' interrupted messages before the stage continues. Both happen visibly in the stage, and stages stay addressable at the same `workflow:<rootRunId>/...` targets ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
47
+ - An interrupted workflow run stays addressable after the session that launched it restarts, before you run `/workflow resume`. Sends to `workflow:<rootRunId>/<stage>` and `workflow:<rootRunId>/**` are queued in the run's own journal instead of failing with `Session not found`, and `intercom list` shows the run's stages as pending. Each queued message is delivered exactly once when its stage is live again, including messages sent while resume is starting. A queued message no longer makes a resume that started at the same time fail as stale. The background subagents that the run's stages launched stay addressable in the same interval: sends to them wait and are delivered once after the resumed stage restores them. If another Atomic session resumes the run instead, that session takes over the run's Intercom targets and the sends still waiting for the subagents get an error saying so ([#3760](https://github.com/bastani-inc/atomic/issues/3760)).
48
+ - A session created with its own `agentDir` now keeps its workflow runs in the same storage as its sessions. Relative paths, `{ file }` secrets, and storage adapters in a shared `storage` selection, from settings or from `ATOMIC_STORAGE`/`--storage`, previously resolved against the default Atomic home for workflow runs, and the default journal ignored the custom `agentDir` ([#3783](https://github.com/bastani-inc/atomic/issues/3783)).
49
+ - On Windows, removing a workflow's temporary worktree now deletes the worktree directory and leaves the main checkout's `node_modules` alone. Atomic unlinks the worktree's `node_modules` junction, and any other directory it linked, before asking Git to remove the worktree. Current Git for Windows left these worktrees behind, and older releases could delete the main checkout's `node_modules` through the junction. If Atomic cannot inspect or unlink one of these links, it leaves the worktree and its branch in place rather than risk Git following the link.
50
+ - Killing a workflow run while it waits, after Atomic restarts, for `/workflow resume` now ends the background subagents its stages launched. Their launch cards no longer show them as resumable, and reopening a stage's session no longer restores them ([#3784](https://github.com/bastani-inc/atomic/pull/3784)).
51
+ - Quitting Atomic after opening the workflow graph or `/workflow` run picker no longer prints an `AbortError: The operation was aborted.` trace. The graph overlay also remounts cleanly when it is opened again after a reload.
52
+
9
53
  ## [0.9.40-alpha.2] - 2026-10-20
10
54
 
11
55
  ### Fixed
@@ -449,6 +449,8 @@ const decision = await ctx.stage("review-gate", { schema: Decision }).prompt(
449
449
 
450
450
  Atomic registers the canonical `structured_output` tool only for schema-enabled items and automatically adds it to explicit `tools` allowlists. The schema is used directly as the tool argument contract. A schema-backed `StageContext` supports one `prompt()` call because the final-answer tool is a single result contract; create another `ctx.stage(..., { schema })` for another structured prompt. If a turn completes without calling `structured_output`, or the tool call fails schema validation, Atomic sends up to three corrective follow-up prompts that include the exact contract/validation error before failing the item. `ctx.task`/`ctx.chain`/`ctx.parallel` results expose the captured value as `result.structured` and keep `result.text` as formatted JSON for handoffs.
451
451
 
452
+ Each `structured_output` decision has a wall-clock limit that covers its repair attempts, retries, and model fallbacks together. It defaults to the session's `httpIdleTimeoutMs` setting (10 minutes unless changed); set `schemaTimeoutMs` (a positive integer in milliseconds) beside `schema` to change it for one item. An overrun stops the in-flight generation and fails the call with `Structured output decision exceeded its <n>ms deadline; no decision was accepted.` plus how long each attempt took. That is an execution failure, not a structured-output contract failure, and the error text reaches the model unchanged.
453
+
452
454
  When an item configures both `schema` and `output`, its successful `structured_output` turn has two separate channels: all ordinary assistant text blocks from that exact message, in order, form the human-readable artifact written to `output`, while the successful tool arguments remain the typed machine-readable workflow result. Atomic never serializes those arguments into the artifact. The runner snapshots the result together with the exact successful tool-call id, so corrective attempts, another call with the same tool name, and later admitted turns cannot replace either side of the pairing. When the successful message has no ordinary text — including after a model-fallback session recreation that leaves the live session without that message — Atomic falls back to the most recent earlier assistant text that made no `structured_output` call; only when no such text exists is the artifact written empty, with the standard empty-artifact warning in the receipt. Items with `schema` but no `output` keep their existing result-text behavior.
453
455
 
454
456
  `subagent` is available as a default workflow-stage tool on the same terms as main chat: a stage is a top-level session, so it can delegate once, and the children it launches cannot delegate further. Delegation is one level deep and nothing configures it. `tools` allowlists apply to bundled extension tools as well as built-ins; if a stage sets `tools`, list every non-mandatory tool it should see. Ordinary `intercom` remains registered and active in every workflow model stage even under `noTools: "all"`, restrictive allowlists, or exclusions. Restrictions on `subagent`, `web_search`, `fetch_content`, and every other tool are unchanged. Bundled `@bastani/subagents` agent definitions are available to the `subagent` tool in workflow stages, including workflows launched from a subagent child process.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.9.40-alpha.2",
3
+ "version": "0.9.41-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [
@@ -8,7 +8,7 @@ export type { RunJournalOption, RunJournalSettings } from "./durable/journal/res
8
8
  export { resolveRunJournal } from "./durable/journal/resolution.js";
9
9
  export { openSqlRunJournal, SqlRunJournal } from "./durable/journal/sqlite-run-journal.js";
10
10
  export * from "./durable/journal/types.js";
11
- export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, EffectiveBudget, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageContext, StageExecutionMeta, StageMcpOptions, StageOptions, StageOutputOptions, StagePromptOptions, StageSendUserMessageOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionEvent, StageSessionRuntime, StageSnapshot, StageStatus, StageUserMessageContent, StageUserMessageDelivery, ToolNodeSnapshot, WorkflowAction, WorkflowArtifact, WorkflowBudget, WorkflowChainOptions, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowCustomUiComponent, WorkflowCustomUiFactory, WorkflowCustomUiKeybindings, WorkflowCustomUiOptions, WorkflowCustomUiOverlayHandle, WorkflowCustomUiOverlayOptions, WorkflowCustomUiTheme, WorkflowCustomUiTui, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowExitOptions, WorkflowExitStatus, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildArgs, WorkflowRunChildOptions, WorkflowRunChildOptionsArgument, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowToolContext, WorkflowToolError, WorkflowToolFailure, WorkflowToolOptions, WorkflowToolOutcome, WorkflowToolPrimitive, WorkflowToolReturnOptions, WorkflowToolSuccess, WorkflowToolThrowOptions, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
11
+ export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, EffectiveBudget, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageContext, StageExecutionMeta, StageMcpOptions, StageOptions, StageOutputOptions, StagePromptOptions, StageSendUserMessageOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionEvent, StageSessionRuntime, StageSnapshot, StageStatus, StageUserMessageContent, StageUserMessageDelivery, ToolNodeSnapshot, WorkflowAction, WorkflowArtifact, WorkflowBudget, WorkflowChainOptions, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowCustomUiComponent, WorkflowCustomUiFactory, WorkflowCustomUiKeybindings, WorkflowCustomUiOptions, WorkflowCustomUiOverlayHandle, WorkflowCustomUiOverlayOptions, WorkflowCustomUiTheme, WorkflowCustomUiTui, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowExitOptions, WorkflowExitStatus, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelFailure, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildArgs, WorkflowRunChildOptions, WorkflowRunChildOptionsArgument, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowToolContext, WorkflowToolError, WorkflowToolFailure, WorkflowToolOptions, WorkflowToolOutcome, WorkflowToolPrimitive, WorkflowToolReturnOptions, WorkflowToolSuccess, WorkflowToolThrowOptions, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
12
12
  import type * as AuthoringContract from "./shared/authoring-contract.js";
13
13
  import type { AuthoredWorkflowSpec as SharedAuthoredWorkflowSpec, WorkflowInputsFromSchemas, WorkflowOutputsFromSchemas, WorkflowProvidedInputsFromSchemas } from "./shared/workflow-authoring-types.js";
14
14
  export type { WorkflowInputsFromSchemas, WorkflowOutputsFromSchemas, WorkflowProvidedInputsFromSchemas, } from "./shared/workflow-authoring-types.js";
@@ -1 +1,17 @@
1
+ import type { RunJournal } from "./types.js";
1
2
  export declare const JOURNAL_READ_PAGE_SIZE = 256;
3
+ /** A run's latest event. A run whose history was deleted and recorded again ends with a different event. */
4
+ export interface RunVersion {
5
+ readonly seq: number;
6
+ readonly at: number;
7
+ }
8
+ /** Lets a durable backend re-read only the runs that changed; kept off the public journal shape. */
9
+ export interface RunJournalVersions {
10
+ /** Moves whenever any connection, in this process or another, commits a change to the journal's store. */
11
+ changeToken(): Promise<string>;
12
+ /** Every listed run with its latest event; a run with no events has version `{ seq: 0, at: 0 }`. */
13
+ runVersions(): Promise<ReadonlyMap<string, RunVersion>>;
14
+ }
15
+ export declare function registerRunJournalVersions(journal: RunJournal, versions: RunJournalVersions): void;
16
+ /** Change tracking for a journal that registered it; other journals are re-read in full. */
17
+ export declare function runJournalVersions(journal: RunJournal): RunJournalVersions | undefined;
@@ -14,6 +14,13 @@ type LegacyEventRow = SqliteRow & {
14
14
  [c.payload]: string;
15
15
  [c.at]: number;
16
16
  };
17
+ export type RunVersionRow = SqliteRow & {
18
+ [c.runId]: string;
19
+ [c.seq]: number;
20
+ [c.at]: number;
21
+ };
22
+ /** `seq` and `at` of the latest event of `${runs}.run_id`, through the `(run_id, seq)` primary key. */
23
+ export declare function latestEventColumns(events: string, runs: string): string;
17
24
  /**
18
25
  * Runs recorded before #3682, kept in the unprefixed `meta`/`runs`/`events`/`leases` tables.
19
26
  *
@@ -32,6 +39,8 @@ export declare class LegacyJournalRuns {
32
39
  cwd?: string;
33
40
  }): Promise<LegacyRunRow[]>;
34
41
  find(executor: SqliteExecutor, runId: string): Promise<LegacyRunRow | undefined>;
42
+ /** Latest event of each pending legacy run; the legacy tables are never modified. */
43
+ versions(executor: SqliteExecutor): Promise<RunVersionRow[]>;
35
44
  /** Events of an unconverted legacy run, read in place. */
36
45
  events(executor: SqliteExecutor, runId: string, fromSeq: number, limit: number): Promise<LegacyEventRow[]>;
37
46
  eventByKey(executor: SqliteExecutor, runId: string, key: string): Promise<LegacyEventRow | undefined>;