@bastani/atomic 0.9.41 → 0.9.42-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 (270) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +13 -0
  3. package/dist/builtin/intercom/README.md +7 -3
  4. package/dist/builtin/intercom/broker/broker-status.ts +48 -0
  5. package/dist/builtin/intercom/broker/broker.ts +90 -9
  6. package/dist/builtin/intercom/broker/client.ts +112 -12
  7. package/dist/builtin/intercom/broker/control.ts +225 -0
  8. package/dist/builtin/intercom/broker/multinode-router.ts +32 -39
  9. package/dist/builtin/intercom/broker/paths.ts +4 -0
  10. package/dist/builtin/intercom/broker/pending-send-registry.ts +27 -5
  11. package/dist/builtin/intercom/broker/shared-storage-setting.ts +60 -0
  12. package/dist/builtin/intercom/broker/spawn.ts +13 -4
  13. package/dist/builtin/intercom/broker/sql-lease-store.ts +23 -0
  14. package/dist/builtin/intercom/broker/watchdog.ts +105 -0
  15. package/dist/builtin/intercom/index.bundle.mjs +200 -22
  16. package/dist/builtin/intercom/package.json +1 -1
  17. package/dist/builtin/intercom/types.ts +34 -2
  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 +1 -0
  21. package/dist/builtin/web-access/package.json +1 -1
  22. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  23. package/dist/builtin/workflows/README.md +10 -0
  24. package/dist/builtin/workflows/builtin/{chunk-txbc93t6.js → chunk-3s95f7ry.js} +1 -1
  25. package/dist/builtin/workflows/builtin/{chunk-n2gkzkty.js → chunk-edhf30ef.js} +1 -1
  26. package/dist/builtin/workflows/builtin/{chunk-8x61e0s7.js → chunk-frqxd4d1.js} +18 -9
  27. package/dist/builtin/workflows/builtin/goal.js +2 -2
  28. package/dist/builtin/workflows/builtin/index.js +3 -3
  29. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  30. package/dist/builtin/workflows/package.json +6 -1
  31. package/dist/builtin/workflows/src/authoring.d.ts +3 -1
  32. package/dist/builtin/workflows/src/durable/journal/internal.d.ts +13 -0
  33. package/dist/builtin/workflows/src/durable/journal/resolution.d.ts +2 -0
  34. package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +1 -0
  35. package/dist/builtin/workflows/src/extension/index.bundle.mjs +88554 -82820
  36. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +72635 -0
  37. package/dist/builtin/workflows/src/index.js +53824 -5907
  38. package/dist/builtin/workflows/src/local-worker-entry.mjs +72635 -0
  39. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +7 -0
  40. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +2 -0
  41. package/dist/builtin/workflows/src/workers/public-options.d.ts +31 -0
  42. package/dist/bun/app-host-modules.d.ts +9 -0
  43. package/dist/bun/app-host-modules.d.ts.map +1 -0
  44. package/dist/bun/app-host-modules.js +10 -0
  45. package/dist/bun/app-host-modules.js.map +1 -0
  46. package/dist/bun/cli.d.ts +3 -1
  47. package/dist/bun/cli.d.ts.map +1 -1
  48. package/dist/bun/cli.js +15 -1
  49. package/dist/bun/cli.js.map +1 -1
  50. package/dist/bun/internal-intercom-broker.d.ts +17 -0
  51. package/dist/bun/internal-intercom-broker.d.ts.map +1 -1
  52. package/dist/bun/internal-intercom-broker.js +29 -0
  53. package/dist/bun/internal-intercom-broker.js.map +1 -1
  54. package/dist/bun/internal-workflow-worker.d.ts +4 -0
  55. package/dist/bun/internal-workflow-worker.d.ts.map +1 -0
  56. package/dist/bun/internal-workflow-worker.js +37 -0
  57. package/dist/bun/internal-workflow-worker.js.map +1 -0
  58. package/dist/bun/split-loader.js +10 -2
  59. package/dist/bun/split-loader.js.map +1 -1
  60. package/dist/cli/args.d.ts.map +1 -1
  61. package/dist/cli/args.js +3 -1
  62. package/dist/cli/args.js.map +1 -1
  63. package/dist/cli/intercom-command.d.ts +15 -0
  64. package/dist/cli/intercom-command.d.ts.map +1 -0
  65. package/dist/cli/intercom-command.js +87 -0
  66. package/dist/cli/intercom-command.js.map +1 -0
  67. package/dist/cli/storage-command.d.ts +39 -0
  68. package/dist/cli/storage-command.d.ts.map +1 -0
  69. package/dist/cli/storage-command.js +367 -0
  70. package/dist/cli/storage-command.js.map +1 -0
  71. package/dist/core/agent-session-events.d.ts.map +1 -1
  72. package/dist/core/agent-session-events.js +5 -1
  73. package/dist/core/agent-session-events.js.map +1 -1
  74. package/dist/core/agent-session-methods.d.ts +1 -0
  75. package/dist/core/agent-session-methods.d.ts.map +1 -1
  76. package/dist/core/agent-session-methods.js.map +1 -1
  77. package/dist/core/agent-session-tasks.d.ts.map +1 -1
  78. package/dist/core/agent-session-tasks.js +1 -0
  79. package/dist/core/agent-session-tasks.js.map +1 -1
  80. package/dist/core/agent-session-types.d.ts +1 -0
  81. package/dist/core/agent-session-types.d.ts.map +1 -1
  82. package/dist/core/agent-session-types.js.map +1 -1
  83. package/dist/core/agent-session.d.ts +1 -0
  84. package/dist/core/agent-session.d.ts.map +1 -1
  85. package/dist/core/agent-session.js +2 -0
  86. package/dist/core/agent-session.js.map +1 -1
  87. package/dist/core/builtin-install-layout.d.ts +6 -0
  88. package/dist/core/builtin-install-layout.d.ts.map +1 -1
  89. package/dist/core/builtin-install-layout.js +9 -0
  90. package/dist/core/builtin-install-layout.js.map +1 -1
  91. package/dist/core/child-session-options.d.ts.map +1 -1
  92. package/dist/core/child-session-options.js +3 -0
  93. package/dist/core/child-session-options.js.map +1 -1
  94. package/dist/core/exec.js +2 -2
  95. package/dist/core/exec.js.map +1 -1
  96. package/dist/core/export-html/template.css +9 -0
  97. package/dist/core/export-html/template.js +165 -45
  98. package/dist/core/extensions/loader-host-modules.d.ts +6 -0
  99. package/dist/core/extensions/loader-host-modules.d.ts.map +1 -1
  100. package/dist/core/extensions/loader-host-modules.js +12 -1
  101. package/dist/core/extensions/loader-host-modules.js.map +1 -1
  102. package/dist/core/extensions/loader-virtual-modules.d.ts +6 -0
  103. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  104. package/dist/core/extensions/loader-virtual-modules.js +18 -0
  105. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  106. package/dist/core/extensions/message-types.d.ts +4 -0
  107. package/dist/core/extensions/message-types.d.ts.map +1 -1
  108. package/dist/core/extensions/message-types.js.map +1 -1
  109. package/dist/core/fast-model-routing-transport.d.ts.map +1 -1
  110. package/dist/core/fast-model-routing-transport.js +5 -1
  111. package/dist/core/fast-model-routing-transport.js.map +1 -1
  112. package/dist/core/intercom-broker-control.d.ts +67 -0
  113. package/dist/core/intercom-broker-control.d.ts.map +1 -0
  114. package/dist/core/intercom-broker-control.js +17 -0
  115. package/dist/core/intercom-broker-control.js.map +1 -0
  116. package/dist/core/model-runtime-streaming.d.ts.map +1 -1
  117. package/dist/core/model-runtime-streaming.js +38 -1
  118. package/dist/core/model-runtime-streaming.js.map +1 -1
  119. package/dist/core/package-manager-git.d.ts +2 -2
  120. package/dist/core/package-manager-git.d.ts.map +1 -1
  121. package/dist/core/package-manager-git.js.map +1 -1
  122. package/dist/core/package-manager-manifest.d.ts.map +1 -1
  123. package/dist/core/package-manager-manifest.js +9 -1
  124. package/dist/core/package-manager-manifest.js.map +1 -1
  125. package/dist/core/package-manager-npm.d.ts +2 -2
  126. package/dist/core/package-manager-npm.d.ts.map +1 -1
  127. package/dist/core/package-manager-npm.js.map +1 -1
  128. package/dist/core/package-manager-paths.d.ts +7 -7
  129. package/dist/core/package-manager-paths.d.ts.map +1 -1
  130. package/dist/core/package-manager-paths.js.map +1 -1
  131. package/dist/core/package-manager-storage-adapters.d.ts +7 -0
  132. package/dist/core/package-manager-storage-adapters.d.ts.map +1 -0
  133. package/dist/core/package-manager-storage-adapters.js +76 -0
  134. package/dist/core/package-manager-storage-adapters.js.map +1 -0
  135. package/dist/core/package-manager-types.d.ts +4 -0
  136. package/dist/core/package-manager-types.d.ts.map +1 -1
  137. package/dist/core/package-manager-types.js.map +1 -1
  138. package/dist/core/provider-rate-limits.d.ts +23 -0
  139. package/dist/core/provider-rate-limits.d.ts.map +1 -0
  140. package/dist/core/provider-rate-limits.js +113 -0
  141. package/dist/core/provider-rate-limits.js.map +1 -0
  142. package/dist/core/provider-request-admission.d.ts +7 -0
  143. package/dist/core/provider-request-admission.d.ts.map +1 -0
  144. package/dist/core/provider-request-admission.js +91 -0
  145. package/dist/core/provider-request-admission.js.map +1 -0
  146. package/dist/core/resource-admission-scope.d.ts +4 -0
  147. package/dist/core/resource-admission-scope.d.ts.map +1 -0
  148. package/dist/core/resource-admission-scope.js +9 -0
  149. package/dist/core/resource-admission-scope.js.map +1 -0
  150. package/dist/core/sdk-types.d.ts +16 -0
  151. package/dist/core/sdk-types.d.ts.map +1 -1
  152. package/dist/core/sdk-types.js.map +1 -1
  153. package/dist/core/sdk.d.ts +2 -1
  154. package/dist/core/sdk.d.ts.map +1 -1
  155. package/dist/core/sdk.js +18 -2
  156. package/dist/core/sdk.js.map +1 -1
  157. package/dist/core/session-lifecycle-work.d.ts +1 -0
  158. package/dist/core/session-lifecycle-work.d.ts.map +1 -1
  159. package/dist/core/session-lifecycle-work.js +1 -0
  160. package/dist/core/session-lifecycle-work.js.map +1 -1
  161. package/dist/core/settings-manager-basic-accessors.d.ts +3 -0
  162. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  163. package/dist/core/settings-manager-basic-accessors.js +6 -0
  164. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  165. package/dist/core/settings-schema.d.ts +22 -0
  166. package/dist/core/settings-schema.d.ts.map +1 -1
  167. package/dist/core/settings-schema.js +18 -1
  168. package/dist/core/settings-schema.js.map +1 -1
  169. package/dist/core/storage/index.d.ts +1 -0
  170. package/dist/core/storage/index.d.ts.map +1 -1
  171. package/dist/core/storage/index.js +1 -0
  172. package/dist/core/storage/index.js.map +1 -1
  173. package/dist/core/storage/node-sqlite.d.ts +2 -1
  174. package/dist/core/storage/node-sqlite.d.ts.map +1 -1
  175. package/dist/core/storage/node-sqlite.js +5 -4
  176. package/dist/core/storage/node-sqlite.js.map +1 -1
  177. package/dist/core/storage/provider.d.ts +6 -0
  178. package/dist/core/storage/provider.d.ts.map +1 -1
  179. package/dist/core/storage/provider.js +27 -7
  180. package/dist/core/storage/provider.js.map +1 -1
  181. package/dist/core/storage/sqlite-facade.d.ts +49 -0
  182. package/dist/core/storage/sqlite-facade.d.ts.map +1 -0
  183. package/dist/core/storage/sqlite-facade.js +180 -0
  184. package/dist/core/storage/sqlite-facade.js.map +1 -0
  185. package/dist/core/storage/storage-status.d.ts +81 -0
  186. package/dist/core/storage/storage-status.d.ts.map +1 -0
  187. package/dist/core/storage/storage-status.js +409 -0
  188. package/dist/core/storage/storage-status.js.map +1 -0
  189. package/dist/core/tasks/supervisor.d.ts +2 -1
  190. package/dist/core/tasks/supervisor.d.ts.map +1 -1
  191. package/dist/core/tasks/supervisor.js +105 -4
  192. package/dist/core/tasks/supervisor.js.map +1 -1
  193. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  194. package/dist/core/tools/bash-pty-native.js +1 -1
  195. package/dist/core/tools/bash-pty-native.js.map +1 -1
  196. package/dist/index.d.ts +2 -1
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +2 -1
  199. package/dist/index.js.map +1 -1
  200. package/dist/main.d.ts.map +1 -1
  201. package/dist/main.js +28 -2
  202. package/dist/main.js.map +1 -1
  203. package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  204. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  205. package/dist/modes/interactive/components/assistant-message.js +7 -3
  206. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  207. package/dist/modes/interactive/components/chat-message-renderer.d.ts +9 -1
  208. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  209. package/dist/modes/interactive/components/chat-message-renderer.js +16 -8
  210. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  211. package/dist/modes/interactive/components/login-dialog.d.ts +5 -0
  212. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  213. package/dist/modes/interactive/components/login-dialog.js +69 -2
  214. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  215. package/dist/modes/interactive/components/markdown-transform.d.ts +1 -1
  216. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  217. package/dist/modes/interactive/components/markdown-transform.js +2 -2
  218. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  219. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  220. package/dist/modes/interactive/components/session-selector-search.js +80 -22
  221. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  222. package/dist/modes/interactive/components/user-message.d.ts +3 -1
  223. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  224. package/dist/modes/interactive/components/user-message.js +6 -2
  225. package/dist/modes/interactive/components/user-message.js.map +1 -1
  226. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  227. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  228. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  229. package/dist/modes/interactive/interactive-render-chat.js +6 -2
  230. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  231. package/dist/modes/interactive-engine/engine-health.d.ts +8 -4
  232. package/dist/modes/interactive-engine/engine-health.d.ts.map +1 -1
  233. package/dist/modes/interactive-engine/engine-health.js +41 -6
  234. package/dist/modes/interactive-engine/engine-health.js.map +1 -1
  235. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  236. package/dist/modes/interactive-engine/isolated-runtime.js +19 -17
  237. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  238. package/dist/modes/interactive-engine/remote-queue-pause.js +1 -1
  239. package/dist/modes/interactive-engine/remote-queue-pause.js.map +1 -1
  240. package/dist/modes/rpc/rpc-input-scheduler.d.ts +1 -0
  241. package/dist/modes/rpc/rpc-input-scheduler.d.ts.map +1 -1
  242. package/dist/modes/rpc/rpc-input-scheduler.js +4 -1
  243. package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -1
  244. package/dist/modes/rpc/rpc-input.d.ts.map +1 -1
  245. package/dist/modes/rpc/rpc-input.js +29 -7
  246. package/dist/modes/rpc/rpc-input.js.map +1 -1
  247. package/dist/utils/shell.d.ts.map +1 -1
  248. package/dist/utils/shell.js +14 -0
  249. package/dist/utils/shell.js.map +1 -1
  250. package/docs/custom-provider/oauth.md +8 -1
  251. package/docs/extensions/api-reference.md +2 -0
  252. package/docs/intercom/operations.md +17 -8
  253. package/docs/intercom/reference.md +1 -1
  254. package/docs/keybindings.md +1 -1
  255. package/docs/packages/authoring.md +15 -0
  256. package/docs/packages.md +3 -2
  257. package/docs/providers.md +2 -0
  258. package/docs/reference/cli.md +17 -0
  259. package/docs/sdk.md +37 -0
  260. package/docs/settings.md +33 -2
  261. package/docs/storage.md +191 -219
  262. package/docs/usage.md +1 -1
  263. package/docs/workflows/api-reference.md +50 -0
  264. package/docs/workflows/operations.md +44 -1
  265. package/docs/workflows.md +25 -0
  266. package/examples/extensions/gondolin/package-lock.json +14 -24
  267. package/examples/extensions/gondolin/package.json +1 -1
  268. package/npm-shrinkwrap.json +35 -35
  269. package/package.json +4 -4
  270. package/schemas/settings.schema.json +87 -1
@@ -585,6 +585,32 @@ function createMessageReader(onMessage, onError) {
585
585
  };
586
586
  }
587
587
 
588
+ // dist/builtin/intercom/broker/broker-status.ts
589
+ function isObject(value) {
590
+ return typeof value === "object" && value !== null && !Array.isArray(value);
591
+ }
592
+ function isOptionalString(value) {
593
+ return value === undefined || typeof value === "string";
594
+ }
595
+ function isBrokerStatusReport(value) {
596
+ if (!isObject(value) || typeof value.pid !== "number" || typeof value.sessions !== "number")
597
+ return false;
598
+ const { storage, multiNode } = value;
599
+ if (storage !== undefined && (!isObject(storage) || typeof storage.digest !== "string" || storage.source !== "env" && storage.source !== "settings"))
600
+ return false;
601
+ return isObject(multiNode) && (multiNode.status === "off" || multiNode.status === "starting" || multiNode.status === "on" || multiNode.status === "unavailable") && isOptionalString(multiNode.reason) && isOptionalString(multiNode.adapter) && isOptionalString(multiNode.prefix) && (multiNode.peers === undefined || Array.isArray(multiNode.peers) && multiNode.peers.every((peer) => typeof peer === "string"));
602
+ }
603
+ function describeMultiNodeStatus(multiNode) {
604
+ const storage = multiNode.adapter === undefined ? "" : ` (adapter ${multiNode.adapter}, prefix ${multiNode.prefix ?? "none"})`;
605
+ if (multiNode.status === "off" || multiNode.status === "unavailable") {
606
+ return `${multiNode.status}${storage}${multiNode.reason === undefined ? "" : `: ${multiNode.reason}`}`;
607
+ }
608
+ if (multiNode.status === "starting" || multiNode.peers === undefined)
609
+ return `${multiNode.status}${storage}`;
610
+ const count = `${multiNode.peers.length} peer broker${multiNode.peers.length === 1 ? "" : "s"} live`;
611
+ return `on${storage}, ${count}${multiNode.peers.length === 0 ? "" : ` (${[...new Set(multiNode.peers)].join(", ")})`}`;
612
+ }
613
+
588
614
  // dist/builtin/intercom/broker/paths.ts
589
615
  import { homedir } from "os";
590
616
  import { join } from "path";
@@ -730,14 +756,14 @@ class PendingSendRegistry {
730
756
  generation
731
757
  };
732
758
  attempt.timer = setTimeout(() => {
733
- this.reject(attempt, new Error("Send timeout"));
759
+ this.expire(attempt);
734
760
  }, timeoutMs);
735
761
  this.attempts.set(messageId, attempt);
736
762
  return { attempt, owner: true };
737
763
  }
738
764
  resolve(messageId, attemptId, result) {
739
765
  const attempt = this.attempts.get(messageId);
740
- if (!attempt || attempt.attemptId !== attemptId)
766
+ if (!attempt || attempt.timedOut || attempt.attemptId !== attemptId)
741
767
  return false;
742
768
  this.attempts.delete(messageId);
743
769
  if (attempt.timer)
@@ -748,21 +774,36 @@ class PendingSendRegistry {
748
774
  }
749
775
  extend(messageId, attemptId, timeoutMs) {
750
776
  const attempt = this.attempts.get(messageId);
751
- if (!attempt || (attemptId === undefined ? !attempt.legacyEligible : attempt.attemptId !== attemptId))
777
+ if (!attempt || attempt.timedOut || (attemptId === undefined ? !attempt.legacyEligible : attempt.attemptId !== attemptId))
752
778
  return false;
753
779
  if (attempt.timer)
754
780
  clearTimeout(attempt.timer);
755
781
  attempt.timer = setTimeout(() => {
756
- this.reject(attempt, new Error("Send timeout"));
782
+ this.expire(attempt);
757
783
  }, timeoutMs);
758
784
  return true;
759
785
  }
760
786
  resolveLegacy(messageId, result) {
761
787
  const attempt = this.attempts.get(messageId);
762
- if (!attempt?.legacyEligible)
788
+ if (!attempt?.legacyEligible || attempt.timedOut)
763
789
  return false;
764
790
  return this.resolve(messageId, attempt.attemptId, result);
765
791
  }
792
+ expire(attempt) {
793
+ if (this.attempts.get(attempt.messageId) !== attempt)
794
+ return;
795
+ attempt.timedOut = true;
796
+ attempt.timer = undefined;
797
+ attempt.reject(new PendingSendTimeoutError);
798
+ }
799
+ release(attempt) {
800
+ const current = this.attempts.get(attempt.messageId);
801
+ if (current !== attempt || !current.timedOut)
802
+ return false;
803
+ this.attempts.delete(attempt.messageId);
804
+ this.touchGeneration(current);
805
+ return true;
806
+ }
766
807
  reject(attempt, error) {
767
808
  const current = this.attempts.get(attempt.messageId);
768
809
  if (current !== attempt)
@@ -779,9 +820,14 @@ class PendingSendRegistry {
779
820
  this.reject(attempt, error);
780
821
  }
781
822
  }
782
- var DEFAULT_GENERATION_TTL_MS, DEFAULT_MAX_GENERATIONS = 1e4;
823
+ var DEFAULT_GENERATION_TTL_MS, DEFAULT_MAX_GENERATIONS = 1e4, PendingSendTimeoutError;
783
824
  var init_pending_send_registry = __esm(() => {
784
825
  DEFAULT_GENERATION_TTL_MS = 10 * 60 * 1000;
826
+ PendingSendTimeoutError = class PendingSendTimeoutError extends Error {
827
+ constructor() {
828
+ super("Send timeout");
829
+ }
830
+ };
785
831
  });
786
832
 
787
833
  // dist/builtin/intercom/source-ownership.ts
@@ -878,16 +924,19 @@ var init_client = __esm(() => {
878
924
  connectTimeoutMs;
879
925
  brokerAcknowledgesReceipt = false;
880
926
  brokerAcknowledgesPendingStageRoutes = false;
927
+ brokerAnswersStatus = false;
881
928
  socket = null;
882
929
  _sessionId = null;
883
930
  _supervisorSessionId = null;
884
931
  _messageSource;
885
932
  pendingSends = new PendingSendRegistry;
933
+ sendResults = new WeakMap;
886
934
  pendingReplyTargets = new Map;
887
935
  pendingGroupLists = new Map;
888
936
  pendingLists = new Map;
889
937
  pendingPresence = new Map;
890
938
  pendingMemberships = new Map;
939
+ pendingBrokerStatus = new Map;
891
940
  _groups = normalizeGroups();
892
941
  pendingLiveWorkflowStageRoutes = new Map;
893
942
  pendingStageRouteRegistrations = new Map;
@@ -895,6 +944,43 @@ var init_client = __esm(() => {
895
944
  pendingRestoringRecipientRequests = new Map;
896
945
  disconnecting = false;
897
946
  disconnectError = null;
947
+ healthCheck;
948
+ async requestTimeout(socket, error) {
949
+ if (this.socket !== socket || socket.destroyed)
950
+ return this.disconnectError ?? new IntercomClientDisconnectedError;
951
+ if (this.healthCheck?.socket !== socket) {
952
+ const requestId = randomUUID2();
953
+ const result = new Promise((resolve) => {
954
+ const finish = (failure) => {
955
+ clearTimeout(timer);
956
+ this.pendingGroupLists.delete(requestId);
957
+ resolve(failure);
958
+ };
959
+ const timer = setTimeout(() => finish(new IntercomBrokerTimeoutError("Broker health check timed out")), GROUP_REQUEST_TIMEOUT_MS);
960
+ this.pendingGroupLists.set(requestId, { resolve: () => finish(), reject: finish });
961
+ try {
962
+ writeMessage(socket, { type: "list_groups", requestId });
963
+ } catch (cause) {
964
+ finish(new IntercomClientDisconnectedError({ cause }));
965
+ }
966
+ });
967
+ this.healthCheck = { socket, result };
968
+ }
969
+ const check = this.healthCheck;
970
+ const failure = await check.result;
971
+ if (this.healthCheck === check)
972
+ this.healthCheck = undefined;
973
+ if (failure === undefined)
974
+ return error;
975
+ const reported = failure instanceof IntercomBrokerTimeoutError ? new IntercomBrokerTimeoutError(error.message, { cause: failure }) : failure;
976
+ if (this.socket === socket && !this.disconnecting) {
977
+ this.disconnectError ??= reported;
978
+ this.failPending(this.disconnectError);
979
+ socket.destroy();
980
+ return this.disconnectError;
981
+ }
982
+ return reported;
983
+ }
898
984
  constructor(returnAddress = randomUUID2(), options = {}) {
899
985
  super();
900
986
  if (returnAddress.length === 0)
@@ -922,6 +1008,8 @@ var init_client = __esm(() => {
922
1008
  pending.reject(error);
923
1009
  for (const pending of this.pendingStageRouteRegistrations.values())
924
1010
  pending.reject(error);
1011
+ for (const pending of this.pendingBrokerStatus.values())
1012
+ pending.reject(error);
925
1013
  this.pendingLists.clear();
926
1014
  this.pendingGroupLists.clear();
927
1015
  this.pendingSupervisorAuthorizations.clear();
@@ -930,6 +1018,7 @@ var init_client = __esm(() => {
930
1018
  this.pendingMemberships.clear();
931
1019
  this.pendingLiveWorkflowStageRoutes.clear();
932
1020
  this.pendingStageRouteRegistrations.clear();
1021
+ this.pendingBrokerStatus.clear();
933
1022
  }
934
1023
  get sessionId() {
935
1024
  return this._sessionId;
@@ -1012,6 +1101,7 @@ var init_client = __esm(() => {
1012
1101
  this._supervisorSessionId = null;
1013
1102
  this.brokerAcknowledgesReceipt = false;
1014
1103
  this.brokerAcknowledgesPendingStageRoutes = false;
1104
+ this.brokerAnswersStatus = false;
1015
1105
  this._messageSource = undefined;
1016
1106
  this.disconnectError = null;
1017
1107
  if (connectionEstablished && !wasDisconnecting) {
@@ -1089,7 +1179,7 @@ var init_client = __esm(() => {
1089
1179
  }
1090
1180
  switch (brokerMessage.type) {
1091
1181
  case "registered": {
1092
- if (typeof brokerMessage.sessionId !== "string" || brokerMessage.supervisorSessionId !== undefined && typeof brokerMessage.supervisorSessionId !== "string" || brokerMessage.acknowledgesReceipt !== undefined && brokerMessage.acknowledgesReceipt !== true || brokerMessage.acknowledgesPendingStageRoutes !== undefined && brokerMessage.acknowledgesPendingStageRoutes !== true) {
1182
+ if (typeof brokerMessage.sessionId !== "string" || brokerMessage.supervisorSessionId !== undefined && typeof brokerMessage.supervisorSessionId !== "string" || brokerMessage.acknowledgesReceipt !== undefined && brokerMessage.acknowledgesReceipt !== true || brokerMessage.acknowledgesPendingStageRoutes !== undefined && brokerMessage.acknowledgesPendingStageRoutes !== true || brokerMessage.brokerStatus !== undefined && brokerMessage.brokerStatus !== true) {
1093
1183
  throw new Error("Invalid registered message");
1094
1184
  }
1095
1185
  if (this._sessionId !== null) {
@@ -1099,6 +1189,7 @@ var init_client = __esm(() => {
1099
1189
  this._supervisorSessionId = typeof brokerMessage.supervisorSessionId === "string" ? brokerMessage.supervisorSessionId : null;
1100
1190
  this.brokerAcknowledgesReceipt = this.acknowledgesReceipt && brokerMessage.acknowledgesReceipt === true;
1101
1191
  this.brokerAcknowledgesPendingStageRoutes = brokerMessage.acknowledgesPendingStageRoutes === true;
1192
+ this.brokerAnswersStatus = brokerMessage.brokerStatus === true;
1102
1193
  this.emit("_registered", { type: "registered", sessionId: brokerMessage.sessionId });
1103
1194
  break;
1104
1195
  }
@@ -1154,6 +1245,18 @@ var init_client = __esm(() => {
1154
1245
  pending.resolve(groups);
1155
1246
  break;
1156
1247
  }
1248
+ case "broker_status": {
1249
+ const { requestId } = brokerMessage;
1250
+ const report = brokerMessage.report;
1251
+ if (typeof requestId !== "string" || !isBrokerStatusReport(report))
1252
+ throw new Error("Invalid broker_status message");
1253
+ const pending = this.pendingBrokerStatus.get(requestId);
1254
+ if (!pending)
1255
+ return;
1256
+ this.pendingBrokerStatus.delete(requestId);
1257
+ pending.resolve(report);
1258
+ break;
1259
+ }
1157
1260
  case "supervisor_authorized": {
1158
1261
  const { requestId, capability, supervisorSessionId, childName } = brokerMessage;
1159
1262
  if (typeof requestId !== "string" || typeof capability !== "string" || typeof supervisorSessionId !== "string" || typeof childName !== "string") {
@@ -1455,7 +1558,7 @@ var init_client = __esm(() => {
1455
1558
  const timeout = setTimeout(() => {
1456
1559
  if (!this.pendingLists.delete(requestId))
1457
1560
  return;
1458
- reject(new Error("List sessions timeout"));
1561
+ this.requestTimeout(socket, new Error("List sessions timeout")).then(reject);
1459
1562
  }, 5000);
1460
1563
  this.pendingLists.set(requestId, {
1461
1564
  resolve: (directory) => {
@@ -1488,7 +1591,7 @@ var init_client = __esm(() => {
1488
1591
  const timeout = setTimeout(() => {
1489
1592
  if (!this.pendingGroupLists.delete(requestId))
1490
1593
  return;
1491
- reject(new Error("List groups timeout"));
1594
+ this.requestTimeout(socket, new Error("List groups timeout")).then(reject);
1492
1595
  }, GROUP_REQUEST_TIMEOUT_MS);
1493
1596
  this.pendingGroupLists.set(requestId, {
1494
1597
  resolve: (groups) => {
@@ -1509,6 +1612,41 @@ var init_client = __esm(() => {
1509
1612
  }
1510
1613
  });
1511
1614
  }
1615
+ brokerStatus() {
1616
+ let socket;
1617
+ try {
1618
+ socket = this.requireActiveSocket();
1619
+ } catch (error) {
1620
+ return Promise.reject(toError(error));
1621
+ }
1622
+ if (!this.brokerAnswersStatus)
1623
+ return Promise.resolve(undefined);
1624
+ const requestId = randomUUID2();
1625
+ return new Promise((resolve, reject) => {
1626
+ const timeout = setTimeout(() => {
1627
+ if (!this.pendingBrokerStatus.delete(requestId))
1628
+ return;
1629
+ reject(new Error("Broker status timeout"));
1630
+ }, GROUP_REQUEST_TIMEOUT_MS);
1631
+ this.pendingBrokerStatus.set(requestId, {
1632
+ resolve: (report) => {
1633
+ clearTimeout(timeout);
1634
+ resolve(report);
1635
+ },
1636
+ reject: (error) => {
1637
+ clearTimeout(timeout);
1638
+ reject(error);
1639
+ }
1640
+ });
1641
+ try {
1642
+ writeMessage(socket, { type: "broker_status", requestId });
1643
+ } catch (error) {
1644
+ clearTimeout(timeout);
1645
+ this.pendingBrokerStatus.delete(requestId);
1646
+ reject(toError(error));
1647
+ }
1648
+ });
1649
+ }
1512
1650
  joinGroup(group) {
1513
1651
  return this.updateMembership("join_group", group);
1514
1652
  }
@@ -1527,7 +1665,7 @@ var init_client = __esm(() => {
1527
1665
  const timeout = setTimeout(() => {
1528
1666
  if (!this.pendingMemberships.delete(requestId))
1529
1667
  return;
1530
- reject(new Error("Membership update timeout"));
1668
+ this.requestTimeout(socket, new Error("Membership update timeout")).then(reject);
1531
1669
  }, GROUP_REQUEST_TIMEOUT_MS);
1532
1670
  this.pendingMemberships.set(requestId, {
1533
1671
  resolve: (groups) => {
@@ -1563,7 +1701,7 @@ var init_client = __esm(() => {
1563
1701
  const timeout = setTimeout(() => {
1564
1702
  if (!this.pendingSupervisorAuthorizations.delete(requestId))
1565
1703
  return;
1566
- reject(new Error("Supervisor authorization timeout"));
1704
+ this.requestTimeout(socket, new Error("Supervisor authorization timeout")).then(reject);
1567
1705
  }, 5000);
1568
1706
  this.pendingSupervisorAuthorizations.set(requestId, {
1569
1707
  resolve: (authorization) => {
@@ -1614,7 +1752,7 @@ var init_client = __esm(() => {
1614
1752
  const timeout = setTimeout(() => {
1615
1753
  if (!this.pendingRestoringRecipientRequests.delete(requestId))
1616
1754
  return;
1617
- reject(new Error("Restoring-recipient request timeout"));
1755
+ this.requestTimeout(socket, new Error("Restoring-recipient request timeout")).then(reject);
1618
1756
  }, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS);
1619
1757
  this.pendingRestoringRecipientRequests.set(requestId, {
1620
1758
  resolve: () => {
@@ -1669,7 +1807,7 @@ var init_client = __esm(() => {
1669
1807
  const timeout = setTimeout(() => {
1670
1808
  if (!this.pendingStageRouteRegistrations.delete(requestId))
1671
1809
  return;
1672
- reject(new IntercomBrokerTimeoutError("Pending-stage route registration timeout"));
1810
+ this.requestTimeout(socket, new IntercomBrokerTimeoutError("Pending-stage route registration timeout")).then(reject);
1673
1811
  }, PENDING_STAGE_ROUTE_ACK_TIMEOUT_MS);
1674
1812
  this.pendingStageRouteRegistrations.set(requestId, {
1675
1813
  resolve: () => {
@@ -1783,8 +1921,22 @@ var init_client = __esm(() => {
1783
1921
  } catch (error) {
1784
1922
  return Promise.reject(toError(error));
1785
1923
  }
1924
+ let result = this.sendResults.get(acquired.attempt.promise);
1925
+ if (result === undefined) {
1926
+ result = acquired.attempt.promise.catch(async (error) => {
1927
+ if (error instanceof PendingSendTimeoutError) {
1928
+ try {
1929
+ throw await this.requestTimeout(socket, error);
1930
+ } finally {
1931
+ this.pendingSends.release(acquired.attempt);
1932
+ }
1933
+ }
1934
+ throw error;
1935
+ });
1936
+ this.sendResults.set(acquired.attempt.promise, result);
1937
+ }
1786
1938
  if (!acquired.owner)
1787
- return acquired.attempt.promise;
1939
+ return result;
1788
1940
  const message = {
1789
1941
  id: messageId,
1790
1942
  timestamp: Date.now(),
@@ -1817,7 +1969,7 @@ var init_client = __esm(() => {
1817
1969
  this.pendingReplyTargets.delete(acquired.attempt.attemptId);
1818
1970
  };
1819
1971
  acquired.attempt.promise.then(clearReplyTarget, clearReplyTarget);
1820
- return acquired.attempt.promise;
1972
+ return result;
1821
1973
  }
1822
1974
  updatePresence(updates) {
1823
1975
  if (this.disconnecting) {
@@ -1854,7 +2006,7 @@ var init_client = __esm(() => {
1854
2006
  const timeout = setTimeout(() => {
1855
2007
  if (!this.pendingPresence.delete(requestId))
1856
2008
  return;
1857
- reject(new Error("Presence update timeout"));
2009
+ this.requestTimeout(socket, new Error("Presence update timeout")).then(reject);
1858
2010
  }, PRESENCE_ACK_TIMEOUT_MS);
1859
2011
  this.pendingPresence.set(requestId, {
1860
2012
  resolve: wrappedResolve,
@@ -2039,7 +2191,16 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore")
2039
2191
  function resetBrokerLog(logPath = BROKER_LOG) {
2040
2192
  ensurePrivateDirectory(dirname(logPath));
2041
2193
  try {
2194
+ const previous = readBrokerLogTail(logPath);
2042
2195
  closeSync(openSync(logPath, "w"));
2196
+ if (previous.length > 0) {
2197
+ try {
2198
+ const previousPath = `${logPath}.previous`;
2199
+ writeFileSync(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
2200
+ if (process.platform !== "win32")
2201
+ chmodSync(previousPath, 384);
2202
+ } catch {}
2203
+ }
2043
2204
  return true;
2044
2205
  } catch (error) {
2045
2206
  const code = error.code;
@@ -2080,7 +2241,7 @@ ${tail}`;
2080
2241
  function toError2(error) {
2081
2242
  return error instanceof Error ? error : new Error(String(error));
2082
2243
  }
2083
- async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = BROKER_READY_TIMEOUT_MS) {
2244
+ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = BROKER_READY_TIMEOUT_MS, extensionDir = EXTENSION_DIR) {
2084
2245
  ensurePrivateDirectory(INTERCOM_DIR);
2085
2246
  if (await isBrokerRunning()) {
2086
2247
  return;
@@ -2095,8 +2256,8 @@ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = B
2095
2256
  if (await isBrokerRunning()) {
2096
2257
  return;
2097
2258
  }
2098
- const brokerPath = resolveBrokerEntrypoint(EXTENSION_DIR);
2099
- const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs);
2259
+ const brokerPath = resolveBrokerEntrypoint(extensionDir);
2260
+ const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir);
2100
2261
  if (launch.kind === "windows-launcher") {
2101
2262
  writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);
2102
2263
  }
@@ -2107,7 +2268,7 @@ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = B
2107
2268
  const logFd = launch.kind === "direct" ? openSync(BROKER_LOG, "a") : undefined;
2108
2269
  let child;
2109
2270
  try {
2110
- child = spawn(launch.command, launch.args, getBrokerSpawnOptions(EXTENSION_DIR, logFd ?? "ignore"));
2271
+ child = spawn(launch.command, launch.args, getBrokerSpawnOptions(extensionDir, logFd ?? "ignore"));
2111
2272
  } finally {
2112
2273
  if (logFd !== undefined)
2113
2274
  closeSync(logFd);
@@ -3753,6 +3914,19 @@ function retainInconclusiveRetry(reservations, attempt) {
3753
3914
  remainingRetries: reservations.remainingRetries(attempt)
3754
3915
  };
3755
3916
  }
3917
+ async function multiNodeStatus(client) {
3918
+ if (typeof client.brokerStatus !== "function")
3919
+ return;
3920
+ try {
3921
+ const report = await client.brokerStatus();
3922
+ if (report === undefined) {
3923
+ return { line: "unknown (the running broker predates status reporting; `atomic intercom restart` replaces it)" };
3924
+ }
3925
+ return { line: describeMultiNodeStatus(report.multiNode), multiNode: report.multiNode };
3926
+ } catch (error) {
3927
+ return { line: `unknown (${getErrorMessage(error)})` };
3928
+ }
3929
+ }
3756
3930
  async function listDirectory(client, group) {
3757
3931
  if (typeof client.listDirectory === "function")
3758
3932
  return client.listDirectory(group);
@@ -4750,6 +4924,9 @@ ${lines.join(`
4750
4924
  const selectedGroupSessions = selectedGroup === undefined ? undefined : await connectedClient.listSessions(selectedGroup);
4751
4925
  const selectedSection = selectedGroupSessions === undefined ? "" : `
4752
4926
  Selected group [${selectedGroup}]: ${selectedGroupSessions.length} session(s)`;
4927
+ const multiNode = await multiNodeStatus(connectedClient);
4928
+ const multiNodeSection = multiNode === undefined ? "" : `
4929
+ Multi-node routing: ${multiNode.line}`;
4753
4930
  return {
4754
4931
  content: [{
4755
4932
  type: "text",
@@ -4757,13 +4934,14 @@ Selected group [${selectedGroup}]: ${selectedGroupSessions.length} session(s)`;
4757
4934
  Connected: Yes
4758
4935
  Session ID: ${mySessionId}
4759
4936
  Groups: ${ownGroups.join(", ")}
4760
- Active visible sessions: ${sessions.length}${selectedSection}`
4937
+ Active visible sessions: ${sessions.length}${selectedSection}${multiNodeSection}`
4761
4938
  }],
4762
4939
  isError: false,
4763
4940
  details: {
4764
4941
  group: ownGroups.at(-1),
4765
4942
  groups: ownGroups,
4766
- ...selectedGroup === undefined ? {} : { selectedGroup, selectedGroupSessionCount: selectedGroupSessions?.length ?? 0 }
4943
+ ...selectedGroup === undefined ? {} : { selectedGroup, selectedGroupSessionCount: selectedGroupSessions?.length ?? 0 },
4944
+ ...multiNode?.multiNode === undefined ? {} : { multiNode: multiNode.multiNode }
4767
4945
  }
4768
4946
  };
4769
4947
  } catch (error) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.41",
3
+ "version": "0.9.42-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
6
6
  "contributors": [
@@ -93,6 +93,28 @@ export interface GroupSummary {
93
93
  member: boolean;
94
94
  }
95
95
 
96
+ /** A broker's multi-node routing state, as `broker_status` reports it. */
97
+ export interface BrokerMultiNodeStatus {
98
+ status: "off" | "starting" | "on" | "unavailable";
99
+ /** Why routing is off or unavailable. */
100
+ reason?: string;
101
+ /** The shared selection's adapter module, or `sqlite` for a `path` selection. */
102
+ adapter?: string;
103
+ prefix?: string;
104
+ /** Host names of the other brokers whose membership lease is live, while routing is on. */
105
+ peers?: string[];
106
+ }
107
+
108
+ /** What a broker reports about itself; read before registering by `atomic intercom restart` and `atomic storage status`. */
109
+ export interface BrokerStatusReport {
110
+ pid: number;
111
+ /** Sessions connected to this broker. */
112
+ sessions: number;
113
+ /** The shared storage selection the broker read, as a digest of its JSON, and where it read it; absent without one. */
114
+ storage?: { digest: string; source: "env" | "settings" };
115
+ multiNode: BrokerMultiNodeStatus;
116
+ }
117
+
96
118
  export interface Message {
97
119
  id: string;
98
120
  timestamp: number;
@@ -125,6 +147,7 @@ export interface SupervisorRegistration {
125
147
 
126
148
 
127
149
  export type ClientMessage =
150
+ | { type: "health"; requestId: string }
128
151
  | {
129
152
  type: "register";
130
153
  session: Omit<SessionInfo, "id">;
@@ -225,9 +248,14 @@ export type ClientMessage =
225
248
  /** Legacy single-group membership; accepted alongside `groups` for compatibility. */
226
249
  group?: string;
227
250
  requestId?: string;
228
- };
251
+ }
252
+ /** Allowed before `register`: the broker's own status. */
253
+ | { type: "broker_status"; requestId: string }
254
+ /** Allowed before `register`: shut the broker down; its sessions reconnect to a new broker. */
255
+ | { type: "shutdown"; requestId: string };
229
256
 
230
257
  export type BrokerMessage =
258
+ | { type: "health"; requestId: string; instanceId: string }
231
259
  | {
232
260
  type: "registered";
233
261
  sessionId: string;
@@ -236,6 +264,8 @@ export type BrokerMessage =
236
264
  acknowledgesReceipt?: true;
237
265
  /** This broker acknowledges a `register_pending_stage_route` that carries a `requestId`; absent on older brokers. */
238
266
  acknowledgesPendingStageRoutes?: true;
267
+ /** This broker answers `broker_status`; absent on older brokers, which drop a client that sends it. */
268
+ brokerStatus?: true;
239
269
  }
240
270
  | { type: "registration_failed"; reason: string; code?: LiveWorkflowStageRouteRefusalCode }
241
271
  | { type: "question_target"; messageId: string; attemptId: string; sessionId: string }
@@ -272,4 +302,6 @@ export type BrokerMessage =
272
302
  /** #3760: the send is held for a subagent that is being restored; wait up to `timeoutMs` for its outcome. */
273
303
  | { type: "send_held"; messageId: string; attemptId?: string; timeoutMs: number }
274
304
  | { type: "restoring_recipient_ack"; requestId: string; error?: string }
275
- | { type: "delivery_failed"; messageId: string; reason: string; reasonCode?: "message_id_conflict" | "session_not_found"; attemptId?: string };
305
+ | { type: "delivery_failed"; messageId: string; reason: string; reasonCode?: "message_id_conflict" | "session_not_found"; attemptId?: string }
306
+ | { type: "broker_status"; requestId: string; report: BrokerStatusReport }
307
+ | { type: "shutdown_ack"; requestId: string };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.41",
3
+ "version": "0.9.42-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": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.41",
3
+ "version": "0.9.42-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": [
@@ -13205,6 +13205,7 @@ class SubagentControlRuntime {
13205
13205
  ...inherited,
13206
13206
  customTools: admitted.policy.customTools ?? inherited.customTools,
13207
13207
  resourceLoader,
13208
+ resourceAdmissionSignal: AbortSignal.any([signals.abort, signals.interrupt]),
13208
13209
  subagentPolicy: {
13209
13210
  ...admitted.policy,
13210
13211
  executionEnded: executionEnded.signal,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.9.41",
3
+ "version": "0.9.42-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,18 @@ 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.42-alpha.1] - 2026-10-23
10
+
11
+ ### Added
12
+
13
+ - Local workflow pools can be enabled per run through SDK options or workflow settings, with root and optional user-wide admission limits. A root stays local while registered child workflow subtrees run in local worker processes; unsupported process containment and incompatible worker definitions fail closed ([#3869](https://github.com/bastani-inc/atomic/issues/3869)).
14
+
15
+ ### Fixed
16
+
17
+ - Workflow model chains now share provider-account cooldowns after rate limits, honor `Retry-After`, and wait for the earliest eligible account instead of exhausting a cooling chain. Retries remain bounded, including retries within each session; waits can be paused or cancelled, and workflow status and task results report provider counts and cooldown deadlines. Retrying a follow-up on the same model preserves its conversation history. Follow-ups keep each model's retry allowance across account switches and can return to an earlier account when its cooldown expires ([#3864](https://github.com/bastani-inc/atomic/issues/3864)).
18
+ - Workflow stages now reload resources up to four at a time per Atomic process instead of one at a time, so a slow reload no longer blocks every other stage at startup. Cancelling a stage waiting for a reload slot removes it from the queue immediately; an active reload retains its slot until it finishes ([#3861](https://github.com/bastani-inc/atomic/issues/3861)).
19
+ - Standalone `run()` now owns Intercom routes for eligible workflow stages until the run settles, so stages can use Intercom without an interactive workflow host. An installed SDK reuses an Intercom owner the extension bundle already registered for the store instead of starting a second one. When a route-update acknowledgement times out, the update retries without disconnecting a healthy owner ([#3863](https://github.com/bastani-inc/atomic/issues/3863))
20
+
9
21
  ## [0.9.41] - 2026-10-22
10
22
 
11
23
  ### Added
@@ -504,6 +504,16 @@ For authored workflows, choose thinking effort by stage role and failure cost ra
504
504
 
505
505
  When pi exposes its model registry, workflow runs validate user-specified `model` / `fallbackModels` before starting model-backed work and report all unavailable or ambiguous IDs together. Bare model IDs are accepted only when they resolve uniquely or match the current provider; otherwise use `provider/model`. Fallback attempts may send the same prompt/context to a different provider, so choose fallbacks that fit your cost, privacy, and data-handling requirements.
506
506
 
507
+ ### Rate-limit-aware fallback
508
+
509
+ A 429 puts its configured provider account on a cooldown shared by every stage in the process. The chain prefers a ready candidate; when all eligible candidates are cooling down, it waits for the earliest deadline and rechecks. `Retry-After` seconds and HTTP dates take precedence over local exponential backoff with jitter. Local backoff is capped at 60 seconds, but a longer server deadline is respected.
510
+
511
+ Retries remain bounded by the session's `retry.enabled` and `retry.maxRetries`. Custom adapters without retry settings allow two rate-limit retries per candidate. Pausing, quitting, or cancelling interrupts a cooldown wait. Workflow and structured-output time limits still include time spent waiting.
512
+
513
+ Stage metadata and task results expose `rateLimits`: configured provider IDs, process-wide `rateLimitCount`, `cooldownUntil`, and `waitingUntil` while the fallback scheduler waits. The model-facing `workflow status` listing names waiting stages and their provider counts. Timestamps use Unix milliseconds; historical records do not restore active cooldowns after restart.
514
+
515
+ For optional per-provider rolling request budgets, call `configureProviderRequestBudget(provider, { maxRequests, intervalMs })` from `@bastani/atomic` before model work. Pass `undefined` to remove a budget. Budgets apply across model runtimes in the same process. HTTP-based OpenAI, Anthropic, Azure, Mistral, pi-messages, and explicit Codex SSE transports count each HTTP attempt; other transports count stream starts rather than their internal retries. Separate configured provider IDs have independent budgets even when they point to the same account. See [provider rate limits](../coding-agent/docs/workflows.md#provider-rate-limits) for an example and limitations.
516
+
507
517
  ### `createRegistry` — grouping workflows
508
518
 
509
519
  ```typescript
@@ -37,7 +37,7 @@ import {
37
37
  parseFailureDiagnostics,
38
38
  summarizeReviewConvergence,
39
39
  reverify_consolidated_batch
40
- } from "./chunk-8x61e0s7.js";
40
+ } from "./chunk-frqxd4d1.js";
41
41
  import {
42
42
  VERIFICATION_SCALE
43
43
  } from "./chunk-n1910xc4.js";
@@ -39,7 +39,7 @@ import {
39
39
  reviewerFailureText,
40
40
  summarizeReviewConvergence,
41
41
  reverify_consolidated_batch
42
- } from "./chunk-8x61e0s7.js";
42
+ } from "./chunk-frqxd4d1.js";
43
43
  import {
44
44
  fold_usage
45
45
  } from "./chunk-tgt0s5e5.js";