@bastani/atomic 0.9.45 → 0.9.46

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 (214) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +22 -0
  3. package/dist/builtin/intercom/broker/broker.ts +124 -10
  4. package/dist/builtin/intercom/broker/client.ts +177 -25
  5. package/dist/builtin/intercom/broker/multinode-router.ts +228 -27
  6. package/dist/builtin/intercom/broker/multinode-state-store.ts +10 -0
  7. package/dist/builtin/intercom/broker/recipient-receipts.ts +38 -4
  8. package/dist/builtin/intercom/broker/send-handler.ts +9 -2
  9. package/dist/builtin/intercom/broker/sql-outbox-store.ts +29 -4
  10. package/dist/builtin/intercom/group.ts +25 -0
  11. package/dist/builtin/intercom/index.bundle.mjs +177 -35
  12. package/dist/builtin/intercom/package.json +1 -1
  13. package/dist/builtin/intercom/retry-policy.ts +7 -0
  14. package/dist/builtin/intercom/types.ts +21 -0
  15. package/dist/builtin/mcp/package.json +1 -1
  16. package/dist/builtin/subagents/CHANGELOG.md +21 -0
  17. package/dist/builtin/subagents/package.json +1 -1
  18. package/dist/builtin/subagents/src/extension/index.bundle.mjs +152 -56
  19. package/dist/builtin/web-access/package.json +1 -1
  20. package/dist/builtin/workflows/CHANGELOG.md +79 -0
  21. package/dist/builtin/workflows/builtin/{chunk-6901nsd6.js → chunk-6jpwc09k.js} +1 -1
  22. package/dist/builtin/workflows/builtin/{chunk-vwx023ge.js → chunk-qhm35ntx.js} +1 -1
  23. package/dist/builtin/workflows/builtin/{chunk-jvna28mq.js → chunk-zhyqnf5g.js} +331 -68
  24. package/dist/builtin/workflows/builtin/goal.js +2 -2
  25. package/dist/builtin/workflows/builtin/index.js +3 -3
  26. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  27. package/dist/builtin/workflows/package.json +1 -1
  28. package/dist/builtin/workflows/skills/prompt-engineer/SKILL.md +1 -0
  29. package/dist/builtin/workflows/skills/prompt-engineer/references/gpt_6.md +2 -2
  30. package/dist/builtin/workflows/skills/prompt-engineer/references/gpt_6_1_sol.md +2 -2
  31. package/dist/builtin/workflows/skills/prompt-engineer/references/gpt_6_1_terra.md +77 -0
  32. package/dist/builtin/workflows/src/authoring.d.ts +1 -1
  33. package/dist/builtin/workflows/src/durable/journal/internal.d.ts +2 -0
  34. package/dist/builtin/workflows/src/extension/index.bundle.mjs +7104 -3387
  35. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +11105 -7264
  36. package/dist/builtin/workflows/src/index.js +6796 -3606
  37. package/dist/builtin/workflows/src/local-worker-entry.mjs +11105 -7264
  38. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +19 -0
  39. package/dist/core/agent-session-boundaries.d.ts.map +1 -1
  40. package/dist/core/agent-session-boundaries.js +1 -0
  41. package/dist/core/agent-session-boundaries.js.map +1 -1
  42. package/dist/core/agent-session-events.d.ts.map +1 -1
  43. package/dist/core/agent-session-events.js +2 -1
  44. package/dist/core/agent-session-events.js.map +1 -1
  45. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  46. package/dist/core/agent-session-extension-bindings.js +15 -2
  47. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  48. package/dist/core/agent-session-methods.d.ts +3 -2
  49. package/dist/core/agent-session-methods.d.ts.map +1 -1
  50. package/dist/core/agent-session-methods.js.map +1 -1
  51. package/dist/core/agent-session-prompt.d.ts +4 -2
  52. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  53. package/dist/core/agent-session-prompt.js +13 -8
  54. package/dist/core/agent-session-prompt.js.map +1 -1
  55. package/dist/core/agent-session-recovery.d.ts.map +1 -1
  56. package/dist/core/agent-session-recovery.js +92 -1
  57. package/dist/core/agent-session-recovery.js.map +1 -1
  58. package/dist/core/agent-session-tasks.d.ts.map +1 -1
  59. package/dist/core/agent-session-tasks.js +8 -1
  60. package/dist/core/agent-session-tasks.js.map +1 -1
  61. package/dist/core/agent-session-transfer.d.ts.map +1 -1
  62. package/dist/core/agent-session-transfer.js +5 -0
  63. package/dist/core/agent-session-transfer.js.map +1 -1
  64. package/dist/core/agent-session.d.ts +2 -0
  65. package/dist/core/agent-session.d.ts.map +1 -1
  66. package/dist/core/agent-session.js +2 -0
  67. package/dist/core/agent-session.js.map +1 -1
  68. package/dist/core/copilot-errors.d.ts +6 -0
  69. package/dist/core/copilot-errors.d.ts.map +1 -0
  70. package/dist/core/copilot-errors.js +17 -0
  71. package/dist/core/copilot-errors.js.map +1 -0
  72. package/dist/core/execution-model-router.d.ts.map +1 -1
  73. package/dist/core/execution-model-router.js +12 -2
  74. package/dist/core/execution-model-router.js.map +1 -1
  75. package/dist/core/extensions/context-types.d.ts +7 -0
  76. package/dist/core/extensions/context-types.d.ts.map +1 -1
  77. package/dist/core/extensions/context-types.js.map +1 -1
  78. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  79. package/dist/core/extensions/runner-context.js +6 -0
  80. package/dist/core/extensions/runner-context.js.map +1 -1
  81. package/dist/core/extensions/ui-types.d.ts +9 -1
  82. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  83. package/dist/core/extensions/ui-types.js.map +1 -1
  84. package/dist/core/extensions/workflow-activity-hub.d.ts +4 -0
  85. package/dist/core/extensions/workflow-activity-hub.d.ts.map +1 -1
  86. package/dist/core/extensions/workflow-activity-hub.js +26 -5
  87. package/dist/core/extensions/workflow-activity-hub.js.map +1 -1
  88. package/dist/core/extensions/workflow-events.d.ts +5 -0
  89. package/dist/core/extensions/workflow-events.d.ts.map +1 -1
  90. package/dist/core/extensions/workflow-events.js.map +1 -1
  91. package/dist/core/messages.d.ts +5 -0
  92. package/dist/core/messages.d.ts.map +1 -1
  93. package/dist/core/messages.js +1 -1
  94. package/dist/core/messages.js.map +1 -1
  95. package/dist/core/model-fallback-failures.d.ts +1 -1
  96. package/dist/core/model-fallback-failures.d.ts.map +1 -1
  97. package/dist/core/model-fallback-failures.js +37 -3
  98. package/dist/core/model-fallback-failures.js.map +1 -1
  99. package/dist/core/model-resolver-defaults.js +2 -2
  100. package/dist/core/model-resolver-defaults.js.map +1 -1
  101. package/dist/core/model-runtime-streaming.js +2 -2
  102. package/dist/core/model-runtime-streaming.js.map +1 -1
  103. package/dist/core/package-manager-npm.d.ts.map +1 -1
  104. package/dist/core/package-manager-npm.js +7 -3
  105. package/dist/core/package-manager-npm.js.map +1 -1
  106. package/dist/core/provider-composer.d.ts.map +1 -1
  107. package/dist/core/provider-composer.js +19 -11
  108. package/dist/core/provider-composer.js.map +1 -1
  109. package/dist/core/provider-rate-limits.d.ts +55 -6
  110. package/dist/core/provider-rate-limits.d.ts.map +1 -1
  111. package/dist/core/provider-rate-limits.js +182 -29
  112. package/dist/core/provider-rate-limits.js.map +1 -1
  113. package/dist/core/provider-request-admission.d.ts.map +1 -1
  114. package/dist/core/provider-request-admission.js +42 -18
  115. package/dist/core/provider-request-admission.js.map +1 -1
  116. package/dist/core/storage/node-sqlite.d.ts.map +1 -1
  117. package/dist/core/storage/node-sqlite.js +176 -19
  118. package/dist/core/storage/node-sqlite.js.map +1 -1
  119. package/dist/core/storage/provider.d.ts +4 -2
  120. package/dist/core/storage/provider.d.ts.map +1 -1
  121. package/dist/core/storage/provider.js +94 -5
  122. package/dist/core/storage/provider.js.map +1 -1
  123. package/dist/core/structured-output/index.d.ts.map +1 -1
  124. package/dist/core/structured-output/index.js +15 -8
  125. package/dist/core/structured-output/index.js.map +1 -1
  126. package/dist/core/structured-output/provider-failure.d.ts +17 -0
  127. package/dist/core/structured-output/provider-failure.d.ts.map +1 -0
  128. package/dist/core/structured-output/provider-failure.js +28 -0
  129. package/dist/core/structured-output/provider-failure.js.map +1 -0
  130. package/dist/core/tasks/completion.d.ts +6 -1
  131. package/dist/core/tasks/completion.d.ts.map +1 -1
  132. package/dist/core/tasks/completion.js +33 -18
  133. package/dist/core/tasks/completion.js.map +1 -1
  134. package/dist/core/tasks/pause.d.ts +2 -1
  135. package/dist/core/tasks/pause.d.ts.map +1 -1
  136. package/dist/core/tasks/pause.js +3 -2
  137. package/dist/core/tasks/pause.js.map +1 -1
  138. package/dist/core/tools/bash.d.ts.map +1 -1
  139. package/dist/core/tools/bash.js +13 -7
  140. package/dist/core/tools/bash.js.map +1 -1
  141. package/dist/core/tools/grep.d.ts.map +1 -1
  142. package/dist/core/tools/grep.js +6 -4
  143. package/dist/core/tools/grep.js.map +1 -1
  144. package/dist/core/tools/shell-task-render.d.ts +1 -0
  145. package/dist/core/tools/shell-task-render.d.ts.map +1 -1
  146. package/dist/core/tools/shell-task-render.js +7 -2
  147. package/dist/core/tools/shell-task-render.js.map +1 -1
  148. package/dist/core/tools/shell-task-status.d.ts.map +1 -1
  149. package/dist/core/tools/shell-task-status.js +2 -1
  150. package/dist/core/tools/shell-task-status.js.map +1 -1
  151. package/dist/extensions/tool-search/tool.d.ts +5 -0
  152. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  153. package/dist/extensions/tool-search/tool.js +38 -5
  154. package/dist/extensions/tool-search/tool.js.map +1 -1
  155. package/dist/index.d.ts +1 -1
  156. package/dist/index.d.ts.map +1 -1
  157. package/dist/index.js +1 -1
  158. package/dist/index.js.map +1 -1
  159. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  160. package/dist/modes/interactive/components/assistant-message.js +20 -12
  161. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  162. package/dist/modes/interactive/components/chat-session-host-actions.js +3 -2
  163. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  164. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  165. package/dist/modes/interactive/components/login-dialog.js +42 -14
  166. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  167. package/dist/modes/interactive/interactive-extension-context.js +2 -1
  168. package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
  169. package/dist/modes/interactive/interactive-extension-custom-ui.js +1 -1
  170. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  171. package/dist/modes/interactive/interactive-extension-dialogs.js +10 -4
  172. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  173. package/dist/modes/interactive/interactive-mode-surface.d.ts +1 -0
  174. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  175. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  176. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  177. package/dist/modes/interactive/interactive-startup.js +5 -6
  178. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  179. package/dist/modes/interactive-engine/engine-custom-ui.d.ts +3 -0
  180. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
  181. package/dist/modes/interactive-engine/engine-custom-ui.js +1 -0
  182. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  183. package/dist/modes/interactive-engine/protocol.d.ts +6 -0
  184. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  185. package/dist/modes/interactive-engine/protocol.js +9 -0
  186. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  187. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
  188. package/dist/modes/interactive-engine/remote-component.js +3 -2
  189. package/dist/modes/interactive-engine/remote-component.js.map +1 -1
  190. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
  191. package/dist/modes/rpc/rpc-client-process.js +8 -1
  192. package/dist/modes/rpc/rpc-client-process.js.map +1 -1
  193. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  194. package/dist/modes/rpc/rpc-client.js +7 -1
  195. package/dist/modes/rpc/rpc-client.js.map +1 -1
  196. package/dist/utils/ansi.d.ts +2 -0
  197. package/dist/utils/ansi.d.ts.map +1 -1
  198. package/dist/utils/ansi.js +5 -0
  199. package/dist/utils/ansi.js.map +1 -1
  200. package/docs/codemode.md +1 -1
  201. package/docs/intercom/reference.md +3 -3
  202. package/docs/llama-cpp.md +25 -14
  203. package/docs/models/evals.md +31 -12
  204. package/docs/models/reference.md +23 -51
  205. package/docs/models.md +3 -4
  206. package/docs/providers.md +5 -15
  207. package/docs/settings.md +1 -1
  208. package/docs/storage.md +2 -2
  209. package/docs/tools.md +1 -1
  210. package/docs/tui.md +2 -0
  211. package/docs/workflows/api-reference.md +20 -1
  212. package/docs/workflows/operations.md +17 -4
  213. package/npm-shrinkwrap.json +64 -44
  214. package/package.json +4 -4
@@ -190,13 +190,14 @@ var init_recoverable_disconnect = __esm(() => {
190
190
  });
191
191
 
192
192
  // dist/builtin/intercom/retry-policy.ts
193
- var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, RECONNECT_DELAYS_MS, SEND_RESPONSE_TIMEOUT_MS = 1e4;
193
+ var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, RECONNECT_DELAYS_MS, SEND_RESPONSE_TIMEOUT_MS = 1e4, RECIPIENT_RECEIPT_TIMEOUT_MS = 8000, RECIPIENT_SAVING_REPORT_INTERVAL_MS;
194
194
  var init_retry_policy = __esm(() => {
195
195
  ASK_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
196
196
  RETRY_IDENTITY_RETRY_OPPORTUNITY_MS = 60 * 1000;
197
197
  RETRY_IDENTITY_TTL_MS = ASK_REPLY_TIMEOUT_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
198
198
  DELIVERED_MESSAGE_TTL_MS = RETRY_IDENTITY_TTL_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
199
199
  RECONNECT_DELAYS_MS = [1000, 2000, 5000];
200
+ RECIPIENT_SAVING_REPORT_INTERVAL_MS = RECIPIENT_RECEIPT_TIMEOUT_MS / 4;
200
201
  });
201
202
 
202
203
  // dist/builtin/intercom/reconnect-backoff.ts
@@ -923,6 +924,29 @@ var init_group = __esm(() => {
923
924
  import { EventEmitter } from "events";
924
925
  import net from "net";
925
926
  import { randomUUID as randomUUID2 } from "crypto";
927
+ function connectAborted() {
928
+ return new IntercomClientDisconnectedError({ cause: new Error("Disconnected before the broker connection registered") });
929
+ }
930
+ function abortableDelay(ms, signal) {
931
+ return new Promise((resolveDelay, rejectDelay) => {
932
+ const timer = setTimeout(() => {
933
+ signal.removeEventListener("abort", onAbort);
934
+ resolveDelay();
935
+ }, ms);
936
+ const onAbort = () => {
937
+ clearTimeout(timer);
938
+ rejectDelay(connectAborted());
939
+ };
940
+ if (signal.aborted)
941
+ onAbort();
942
+ else
943
+ signal.addEventListener("abort", onAbort, { once: true });
944
+ });
945
+ }
946
+ function isBacklogRefusal(error) {
947
+ const code = error.code;
948
+ return code === "ECONNREFUSED" || code === "EAGAIN";
949
+ }
926
950
  function toError(error) {
927
951
  return error instanceof Error ? error : new Error(String(error));
928
952
  }
@@ -932,7 +956,7 @@ function isWorkflowFutureStageRosterEntries(value) {
932
956
  function isWorkflowStageRosterEntries(value) {
933
957
  return Array.isArray(value) && value.every((entry) => typeof entry === "object" && entry !== null && entry.kind === "workflow-stage" && typeof entry.runId === "string" && typeof entry.stageId === "string" && typeof entry.stageName === "string" && typeof entry.target === "string" && (entry.lifecycle === "pending" || entry.lifecycle === "running") && typeof entry.group === "string" && (entry.sessionId === undefined || typeof entry.sessionId === "string"));
934
958
  }
935
- var BROKER_SOCKET, BROKER_CONNECT_TIMEOUT_MS = 1e4, PENDING_STAGE_ROUTE_ACK_TIMEOUT_MS = 1e4, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS = 5000, HELD_SEND_GRACE_MS = 5000, IntercomPendingStageRouteRefusedError, PENDING_STAGE_ROUTE_REFUSAL_CODES, IntercomClient;
959
+ var BROKER_SOCKET, BROKER_CONNECT_TIMEOUT_MS = 1e4, PENDING_STAGE_ROUTE_ACK_TIMEOUT_MS = 1e4, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS = 5000, BROKER_BACKLOG_RETRIES = 6, BROKER_BACKLOG_RETRY_BASE_MS = 25, HELD_SEND_GRACE_MS = 5000, IntercomPendingStageRouteRefusedError, PENDING_STAGE_ROUTE_REFUSAL_CODES, IntercomClient;
936
960
  var init_client = __esm(() => {
937
961
  init_paths();
938
962
  init_pending_send_registry();
@@ -966,6 +990,9 @@ var init_client = __esm(() => {
966
990
  multiplexesPendingStageRoutes;
967
991
  brokerRefusesPendingStageRoutesInPlace = false;
968
992
  brokerAnswersStatus = false;
993
+ brokerClaimsWorkflowInvocations = false;
994
+ connectAttempt;
995
+ brokerExtendsSaves = false;
969
996
  socket = null;
970
997
  _sessionId = null;
971
998
  _supervisorSessionId = null;
@@ -980,6 +1007,7 @@ var init_client = __esm(() => {
980
1007
  pendingBrokerStatus = new Map;
981
1008
  _groups = normalizeGroups();
982
1009
  pendingLiveWorkflowStageRoutes = new Map;
1010
+ pendingWorkflowInvocationClaims = new Map;
983
1011
  pendingStageRouteRegistrations = new Map;
984
1012
  pendingSupervisorAuthorizations = new Map;
985
1013
  pendingRestoringRecipientRequests = new Map;
@@ -1048,6 +1076,8 @@ var init_client = __esm(() => {
1048
1076
  pending.reject(error);
1049
1077
  for (const pending of this.pendingLiveWorkflowStageRoutes.values())
1050
1078
  pending.reject(error);
1079
+ for (const pending of this.pendingWorkflowInvocationClaims.values())
1080
+ pending.reject(error);
1051
1081
  for (const pending of this.pendingStageRouteRegistrations.values())
1052
1082
  pending.reject(error);
1053
1083
  for (const pending of this.pendingBrokerStatus.values())
@@ -1059,6 +1089,7 @@ var init_client = __esm(() => {
1059
1089
  this.pendingPresence.clear();
1060
1090
  this.pendingMemberships.clear();
1061
1091
  this.pendingLiveWorkflowStageRoutes.clear();
1092
+ this.pendingWorkflowInvocationClaims.clear();
1062
1093
  this.pendingStageRouteRegistrations.clear();
1063
1094
  this.pendingBrokerStatus.clear();
1064
1095
  }
@@ -1088,7 +1119,31 @@ var init_client = __esm(() => {
1088
1119
  }
1089
1120
  return socket;
1090
1121
  }
1091
- connect(session, supervisor, supervisorOwnerToken, messageSource, registrationGroup) {
1122
+ async connect(session, supervisor, supervisorOwnerToken, messageSource, registrationGroup) {
1123
+ const attempt = new AbortController;
1124
+ this.connectAttempt = attempt;
1125
+ try {
1126
+ for (let retry = 0;; retry++) {
1127
+ if (attempt.signal.aborted)
1128
+ throw connectAborted();
1129
+ try {
1130
+ await this.connectOnce(attempt.signal, session, supervisor, supervisorOwnerToken, messageSource, registrationGroup);
1131
+ return;
1132
+ } catch (error) {
1133
+ if (attempt.signal.aborted)
1134
+ throw connectAborted();
1135
+ if (!(error instanceof Error) || !isBacklogRefusal(error) || retry >= BROKER_BACKLOG_RETRIES)
1136
+ throw error;
1137
+ const backoff = BROKER_BACKLOG_RETRY_BASE_MS * 2 ** retry;
1138
+ await abortableDelay(backoff * (0.5 + Math.random() / 2), attempt.signal);
1139
+ }
1140
+ }
1141
+ } finally {
1142
+ if (this.connectAttempt === attempt)
1143
+ this.connectAttempt = undefined;
1144
+ }
1145
+ }
1146
+ connectOnce(signal, session, supervisor, supervisorOwnerToken, messageSource, registrationGroup) {
1092
1147
  if (this.socket) {
1093
1148
  return Promise.reject(new Error("Already connected"));
1094
1149
  }
@@ -1145,6 +1200,8 @@ var init_client = __esm(() => {
1145
1200
  this.brokerAcknowledgesPendingStageRoutes = false;
1146
1201
  this.brokerRefusesPendingStageRoutesInPlace = false;
1147
1202
  this.brokerAnswersStatus = false;
1203
+ this.brokerClaimsWorkflowInvocations = false;
1204
+ this.brokerExtendsSaves = false;
1148
1205
  this._messageSource = undefined;
1149
1206
  this.disconnectError = null;
1150
1207
  if (connectionEstablished && !wasDisconnecting) {
@@ -1173,7 +1230,36 @@ var init_client = __esm(() => {
1173
1230
  const reader = createMessageReader((msg) => {
1174
1231
  this.handleBrokerMessage(msg);
1175
1232
  }, onReaderError);
1233
+ const onConnect = () => {
1234
+ if (signal.aborted) {
1235
+ onAbort();
1236
+ return;
1237
+ }
1238
+ try {
1239
+ writeMessage(socket, {
1240
+ type: "register",
1241
+ session,
1242
+ ...registrationGroup !== undefined ? { registrationGroup } : {},
1243
+ returnAddress: this.returnAddress,
1244
+ ...this.preferredSessionId === undefined ? {} : { preferredSessionId: this.preferredSessionId },
1245
+ ...this.acknowledgesReceipt ? { acknowledgesReceipt: true } : {},
1246
+ ...supervisor ? { supervisor } : {},
1247
+ ...supervisorOwnerToken ? { supervisorOwnerToken } : {}
1248
+ });
1249
+ } catch (error) {
1250
+ cleanupConnectionAttempt();
1251
+ cleanupSocketListeners();
1252
+ if (this.socket === socket) {
1253
+ this.socket = null;
1254
+ }
1255
+ socket.destroy();
1256
+ reject(toError(error));
1257
+ }
1258
+ };
1259
+ const onAbort = () => onError(connectAborted());
1176
1260
  const cleanupConnectionAttempt = () => {
1261
+ signal.removeEventListener("abort", onAbort);
1262
+ socket.off("connect", onConnect);
1177
1263
  this.off("_registered", onRegistered);
1178
1264
  this.off("_registration_failed", onRegistrationFailed);
1179
1265
  socket.off("error", onError);
@@ -1190,26 +1276,8 @@ var init_client = __esm(() => {
1190
1276
  socket.on("error", onSocketError);
1191
1277
  this.once("_registered", onRegistered);
1192
1278
  this.once("_registration_failed", onRegistrationFailed);
1193
- try {
1194
- writeMessage(socket, {
1195
- type: "register",
1196
- session,
1197
- ...registrationGroup !== undefined ? { registrationGroup } : {},
1198
- returnAddress: this.returnAddress,
1199
- ...this.preferredSessionId === undefined ? {} : { preferredSessionId: this.preferredSessionId },
1200
- ...this.acknowledgesReceipt ? { acknowledgesReceipt: true } : {},
1201
- ...supervisor ? { supervisor } : {},
1202
- ...supervisorOwnerToken ? { supervisorOwnerToken } : {}
1203
- });
1204
- } catch (error) {
1205
- cleanupConnectionAttempt();
1206
- cleanupSocketListeners();
1207
- if (this.socket === socket) {
1208
- this.socket = null;
1209
- }
1210
- socket.destroy();
1211
- reject(toError(error));
1212
- }
1279
+ signal.addEventListener("abort", onAbort, { once: true });
1280
+ socket.once("connect", onConnect);
1213
1281
  });
1214
1282
  }
1215
1283
  handleBrokerMessage(msg) {
@@ -1222,7 +1290,7 @@ var init_client = __esm(() => {
1222
1290
  }
1223
1291
  switch (brokerMessage.type) {
1224
1292
  case "registered": {
1225
- 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.refusesPendingStageRoutesInPlace !== undefined && brokerMessage.refusesPendingStageRoutesInPlace !== true || brokerMessage.brokerStatus !== undefined && brokerMessage.brokerStatus !== true) {
1293
+ 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.refusesPendingStageRoutesInPlace !== undefined && brokerMessage.refusesPendingStageRoutesInPlace !== true || brokerMessage.brokerStatus !== undefined && brokerMessage.brokerStatus !== true || brokerMessage.claimsWorkflowInvocations !== undefined && brokerMessage.claimsWorkflowInvocations !== true || brokerMessage.extendsSaves !== undefined && brokerMessage.extendsSaves !== true) {
1226
1294
  throw new Error("Invalid registered message");
1227
1295
  }
1228
1296
  if (this._sessionId !== null) {
@@ -1234,6 +1302,8 @@ var init_client = __esm(() => {
1234
1302
  this.brokerAcknowledgesPendingStageRoutes = brokerMessage.acknowledgesPendingStageRoutes === true;
1235
1303
  this.brokerRefusesPendingStageRoutesInPlace = brokerMessage.refusesPendingStageRoutesInPlace === true;
1236
1304
  this.brokerAnswersStatus = brokerMessage.brokerStatus === true;
1305
+ this.brokerClaimsWorkflowInvocations = brokerMessage.claimsWorkflowInvocations === true;
1306
+ this.brokerExtendsSaves = this.brokerAcknowledgesReceipt && brokerMessage.extendsSaves === true;
1237
1307
  this.emit("_registered", { type: "registered", sessionId: brokerMessage.sessionId });
1238
1308
  break;
1239
1309
  }
@@ -1328,8 +1398,8 @@ var init_client = __esm(() => {
1328
1398
  break;
1329
1399
  }
1330
1400
  case "pending_stage_message": {
1331
- const { requestId, from, senderRegistrationName, senderReturnAddress, runId, target, message, live } = brokerMessage;
1332
- if (typeof requestId !== "string" || !isSessionInfo(from) || senderRegistrationName !== undefined && typeof senderRegistrationName !== "string" || senderReturnAddress !== undefined && typeof senderReturnAddress !== "string" || typeof runId !== "string" || typeof target !== "string" || !isMessage(message) || live !== undefined && typeof live !== "boolean") {
1401
+ const { requestId, from, senderRegistrationName, senderReturnAddress, runId, target, message, live, invocationControl } = brokerMessage;
1402
+ if (typeof requestId !== "string" || !isSessionInfo(from) || senderRegistrationName !== undefined && typeof senderRegistrationName !== "string" || senderReturnAddress !== undefined && typeof senderReturnAddress !== "string" || typeof runId !== "string" || typeof target !== "string" || !isMessage(message) || live !== undefined && typeof live !== "boolean" || invocationControl !== undefined && invocationControl !== true) {
1333
1403
  throw new Error("Invalid pending-stage message event");
1334
1404
  }
1335
1405
  this.emit("pending_stage_message", {
@@ -1340,7 +1410,8 @@ var init_client = __esm(() => {
1340
1410
  runId,
1341
1411
  target,
1342
1412
  message,
1343
- ...live === true ? { live: true } : {}
1413
+ ...live === true ? { live: true } : {},
1414
+ ...invocationControl === true ? { invocationControl: true } : {}
1344
1415
  });
1345
1416
  break;
1346
1417
  }
@@ -1402,6 +1473,17 @@ var init_client = __esm(() => {
1402
1473
  pending.resolve();
1403
1474
  break;
1404
1475
  }
1476
+ case "workflow_invocation_claimed": {
1477
+ const { requestId, claimed } = brokerMessage;
1478
+ if (typeof requestId !== "string" || typeof claimed !== "boolean")
1479
+ throw new Error("Invalid workflow invocation claim answer");
1480
+ const pending = this.pendingWorkflowInvocationClaims.get(requestId);
1481
+ if (!pending)
1482
+ return;
1483
+ this.pendingWorkflowInvocationClaims.delete(requestId);
1484
+ pending.resolve(claimed);
1485
+ break;
1486
+ }
1405
1487
  case "live_workflow_stage_route_registered": {
1406
1488
  const { requestId } = brokerMessage;
1407
1489
  if (typeof requestId !== "string")
@@ -1572,6 +1654,10 @@ var init_client = __esm(() => {
1572
1654
  }
1573
1655
  }
1574
1656
  async disconnect() {
1657
+ if (this.connectAttempt !== undefined && this._sessionId === null) {
1658
+ this.connectAttempt.abort();
1659
+ return;
1660
+ }
1575
1661
  const socket = this.socket;
1576
1662
  if (!socket) {
1577
1663
  return;
@@ -1838,7 +1924,7 @@ var init_client = __esm(() => {
1838
1924
  }
1839
1925
  });
1840
1926
  }
1841
- registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent, dormant) {
1927
+ registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent, dormant, launcherCapability) {
1842
1928
  writeMessage(this.requireActiveSocket(), {
1843
1929
  type: "register_pending_stage_route",
1844
1930
  runId,
@@ -1847,10 +1933,11 @@ var init_client = __esm(() => {
1847
1933
  stages,
1848
1934
  possibleStages,
1849
1935
  ...parent === undefined ? {} : { parent },
1850
- ...dormant === true ? { dormant: true } : {}
1936
+ ...dormant === true ? { dormant: true } : {},
1937
+ ...launcherCapability === undefined || !this.brokerClaimsWorkflowInvocations ? {} : { launcherCapability }
1851
1938
  });
1852
1939
  }
1853
- registerPendingStageRouteAcknowledged(runId, group, capability, stages, possibleStages, parent, dormant) {
1940
+ registerPendingStageRouteAcknowledged(runId, group, capability, stages, possibleStages, parent, dormant, launcherCapability) {
1854
1941
  let socket;
1855
1942
  try {
1856
1943
  socket = this.requireActiveSocket();
@@ -1859,7 +1946,7 @@ var init_client = __esm(() => {
1859
1946
  }
1860
1947
  if (!this.brokerAcknowledgesPendingStageRoutes) {
1861
1948
  try {
1862
- this.registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent, dormant);
1949
+ this.registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent, dormant, launcherCapability);
1863
1950
  } catch (error) {
1864
1951
  return Promise.reject(toError(error));
1865
1952
  }
@@ -1895,6 +1982,7 @@ var init_client = __esm(() => {
1895
1982
  possibleStages,
1896
1983
  ...parent === undefined ? {} : { parent },
1897
1984
  ...dormant === true ? { dormant: true } : {},
1985
+ ...launcherCapability === undefined || !this.brokerClaimsWorkflowInvocations ? {} : { launcherCapability },
1898
1986
  ...this.multiplexesPendingStageRoutes && this.brokerRefusesPendingStageRoutesInPlace ? { refusalKeepsConnection: true } : {}
1899
1987
  });
1900
1988
  } catch (error) {
@@ -1904,6 +1992,26 @@ var init_client = __esm(() => {
1904
1992
  }
1905
1993
  });
1906
1994
  }
1995
+ claimWorkflowInvocation(runId, launcherCapability) {
1996
+ let socket;
1997
+ try {
1998
+ socket = this.requireActiveSocket();
1999
+ } catch (error) {
2000
+ return Promise.reject(toError(error));
2001
+ }
2002
+ if (!this.brokerClaimsWorkflowInvocations)
2003
+ return Promise.resolve(false);
2004
+ const requestId = randomUUID2();
2005
+ return new Promise((resolve, reject) => {
2006
+ this.pendingWorkflowInvocationClaims.set(requestId, { resolve, reject });
2007
+ try {
2008
+ writeMessage(socket, { type: "claim_workflow_invocation", requestId, runId, capability: launcherCapability });
2009
+ } catch (error) {
2010
+ this.pendingWorkflowInvocationClaims.delete(requestId);
2011
+ reject(toError(error));
2012
+ }
2013
+ });
2014
+ }
1907
2015
  registerLiveWorkflowStageRoute(runId, stageKeys, capability) {
1908
2016
  let socket;
1909
2017
  try {
@@ -1956,6 +2064,11 @@ var init_client = __esm(() => {
1956
2064
  return;
1957
2065
  writeMessage(this.requireActiveSocket(), { type: "received", messageId });
1958
2066
  }
2067
+ reportSaving(messageId) {
2068
+ if (!this.brokerExtendsSaves || !this.socket || this.socket.destroyed)
2069
+ return;
2070
+ writeMessage(this.socket, { type: "saving", messageId });
2071
+ }
1959
2072
  sendPendingStageNotification(runId, capability, to, senderRegistrationName, options, senderReturnAddress) {
1960
2073
  return this.sendFrame("send_pending_stage_notification", to, options, {
1961
2074
  runId,
@@ -7598,6 +7711,7 @@ __export(exports_index_heavy, {
7598
7711
  default: () => piIntercomExtension
7599
7712
  });
7600
7713
  import { APP_NAME, sessionScopedExtensionState } from "@bastani/atomic";
7714
+ import { randomUUID as randomUUID7 } from "node:crypto";
7601
7715
  import { appendFileSync as appendFileSync2 } from "node:fs";
7602
7716
  import { setTimeout as delay3 } from "node:timers/promises";
7603
7717
  function isPendingStageUndeliverableEvent(value) {
@@ -7670,6 +7784,16 @@ function piIntercomExtension(pi, testOverrides = {}) {
7670
7784
  });
7671
7785
  const inboundDeliveries = new InboundMessageAdmission;
7672
7786
  const pendingStageRoutes = new Map;
7787
+ const launcherCapabilities = new Map;
7788
+ const launcherCapabilityFor = (runId) => {
7789
+ let capability = launcherCapabilities.get(runId);
7790
+ if (capability === undefined) {
7791
+ capability = randomUUID7();
7792
+ launcherCapabilities.set(runId, capability);
7793
+ }
7794
+ return capability;
7795
+ };
7796
+ const launchedRunClaims = new Map;
7673
7797
  const pendingStageRouteClients = new Map;
7674
7798
  const pendingStageRouteConnections = new Map;
7675
7799
  const routeClientConnectGate = createConcurrencyGate(ROUTE_CLIENT_CONNECT_CONCURRENCY);
@@ -7869,7 +7993,14 @@ function piIntercomExtension(pi, testOverrides = {}) {
7869
7993
  }
7870
7994
  function receiveIncomingMessage(receiver, from, message, channel) {
7871
7995
  const generation = runtimeGeneration;
7872
- durableInbox.receive(from, message, channel, () => receiver.acknowledgeReceived(message.id)).then((arrival) => {
7996
+ const saving = setInterval(() => receiver.reportSaving(message.id), RECIPIENT_SAVING_REPORT_INTERVAL_MS);
7997
+ saving.unref?.();
7998
+ const saved = durableInbox.receive(from, message, channel, () => {
7999
+ clearInterval(saving);
8000
+ receiver.acknowledgeReceived(message.id);
8001
+ });
8002
+ saved.finally(() => clearInterval(saving)).catch(() => {});
8003
+ saved.then((arrival) => {
7873
8004
  if (arrival !== "fresh")
7874
8005
  return;
7875
8006
  const liveContext = getLiveContext(runtimeContext, generation);
@@ -8392,7 +8523,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
8392
8523
  pendingStageRouteClients.set(runId, state);
8393
8524
  state.route = route;
8394
8525
  if (state.client?.isConnected()) {
8395
- await state.client.registerPendingStageRouteAcknowledged(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent, route.dormant === true).catch((error) => {
8526
+ await state.client.registerPendingStageRouteAcknowledged(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent, route.dormant === true, launcherCapabilityFor(runId)).catch((error) => {
8396
8527
  if (error instanceof IntercomPendingStageRouteRefusedError) {
8397
8528
  if (!error.connectionKept)
8398
8529
  state.isolated = true;
@@ -8421,7 +8552,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
8421
8552
  throw supersededPendingStageRouteError(contextAtStart, generationAtStart);
8422
8553
  }
8423
8554
  state.client = nextClient;
8424
- await nextClient.registerPendingStageRouteAcknowledged(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent, route.dormant === true);
8555
+ await nextClient.registerPendingStageRouteAcknowledged(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent, route.dormant === true, launcherCapabilityFor(runId));
8425
8556
  if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
8426
8557
  throw supersededPendingStageRouteError(contextAtStart, generationAtStart);
8427
8558
  }
@@ -8475,6 +8606,16 @@ function piIntercomExtension(pi, testOverrides = {}) {
8475
8606
  return;
8476
8607
  }
8477
8608
  await ensurePendingStageRouteClient(runId, { ...route, group: normalizeGroup(route.group) });
8609
+ await claimLaunchedRun(activeClient, runId).catch(() => {});
8610
+ }
8611
+ async function claimLaunchedRun(activeClient, runId) {
8612
+ const capability = launcherCapabilityFor(runId);
8613
+ const claimed = launchedRunClaims.get(runId);
8614
+ if (claimed?.client === activeClient && claimed.capability === capability)
8615
+ return;
8616
+ if (await activeClient.claimWorkflowInvocation(runId, capability)) {
8617
+ launchedRunClaims.set(runId, { client: activeClient, capability });
8618
+ }
8478
8619
  }
8479
8620
  function registersOnMainClient(route) {
8480
8621
  return clientRegistrationGroup === normalizeGroup(route.group) && route.dormant !== true;
@@ -8540,7 +8681,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
8540
8681
  await registerPendingStageRoute(nextClient, runId, route);
8541
8682
  continue;
8542
8683
  }
8543
- ensurePendingStageRouteClient(runId, { ...route, group: normalizeGroup(route.group) }).catch(() => {});
8684
+ ensurePendingStageRouteClient(runId, { ...route, group: normalizeGroup(route.group) }).then(() => claimLaunchedRun(nextClient, runId)).catch(() => {});
8544
8685
  }
8545
8686
  const orchestration = contextAtStart.orchestrationContext;
8546
8687
  if (orchestration?.kind === "workflow-stage" && orchestration.pendingStageDelivery !== undefined) {
@@ -8866,6 +9007,7 @@ var init_index_heavy = __esm(() => {
8866
9007
  init_session_recovery();
8867
9008
  init_client();
8868
9009
  init_spawn();
9010
+ init_retry_policy();
8869
9011
  init_inline_message();
8870
9012
  init_config();
8871
9013
  init_reply_tracker();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.45",
3
+ "version": "0.9.46",
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": [
@@ -12,3 +12,10 @@ export const RECONNECT_DELAYS_MS = [1_000, 2_000, 5_000] as const;
12
12
  export const SEND_RESPONSE_TIMEOUT_MS = 10_000;
13
13
  /** The broker answers an unconfirmed save before the sender's own wait ends, so the sender learns the outcome is uncertain. */
14
14
  export const RECIPIENT_RECEIPT_TIMEOUT_MS = 8_000;
15
+ /**
16
+ * #3983: a recipient still saving a message (a pooled stage's journal commit waiting behind other writers) reports
17
+ * progress this often, each report extending the sender's wait by another `RECIPIENT_RECEIPT_TIMEOUT_MS`.
18
+ */
19
+ export const RECIPIENT_SAVING_REPORT_INTERVAL_MS = RECIPIENT_RECEIPT_TIMEOUT_MS / 4;
20
+ /** No save holds its sender longer than this, however long the recipient keeps reporting progress. */
21
+ export const RECIPIENT_SAVE_MAX_WAIT_MS = 120_000;
@@ -183,6 +183,8 @@ export type ClientMessage =
183
183
  | { type: "unregister" }
184
184
  /** #3761: the recipient saved this message; it ignores a copy of it sent again. */
185
185
  | { type: "received"; messageId: string }
186
+ /** #3983: the recipient is still saving this message; its sender keeps waiting. Sent only to a broker that advertised `extendsSaves`. */
187
+ | { type: "saving"; messageId: string }
186
188
  | { type: "list"; requestId: string; group?: string }
187
189
  | { type: "list_groups"; requestId: string }
188
190
  | { type: "join_group"; requestId: string; group: string }
@@ -236,6 +238,11 @@ export type ClientMessage =
236
238
  parent?: WorkflowRunParentAnnouncement;
237
239
  /** Interrupted run queued by its restarted owner before resume; yields to the process that resumes it (#3760). */
238
240
  dormant?: true;
241
+ /**
242
+ * #4006: a secret held only by the process that launched the run, never given to its stages. The launching
243
+ * session presents it in `claim_workflow_invocation`.
244
+ */
245
+ launcherCapability?: string;
239
246
  /**
240
247
  * #3906: the connection carries the routes of many runs, so a refusal of this one is answered with
241
248
  * `pending_stage_route_refused` and leaves the connection open. Honoured only with a `requestId`, and sent only to
@@ -250,6 +257,13 @@ export type ClientMessage =
250
257
  stageKeys: string[];
251
258
  capability: string;
252
259
  }
260
+ /**
261
+ * #4006: the session that launched a run proves it with the run's launcher capability (not the route
262
+ * capability its stages hold) and gains the invocation's send authority without joining
263
+ * `workflow:<rootRunId>`. Sent only to a broker that advertised `claimsWorkflowInvocations`; the broker
264
+ * answers with `workflow_invocation_claimed`.
265
+ */
266
+ | { type: "claim_workflow_invocation"; requestId: string; runId: string; capability: string }
253
267
  | {
254
268
  type: "pending_stage_message_result";
255
269
  requestId: string;
@@ -292,7 +306,12 @@ export type BrokerMessage =
292
306
  refusesPendingStageRoutesInPlace?: true;
293
307
  /** This broker answers `broker_status`; absent on older brokers, which drop a client that sends it. */
294
308
  brokerStatus?: true;
309
+ /** #4006: this broker accepts `claim_workflow_invocation`; absent on older brokers, which drop a client that sends it. */
310
+ claimsWorkflowInvocations?: true;
311
+ /** #3983: this broker accepts `saving`; absent on older brokers, which drop a client that sends it. */
312
+ extendsSaves?: true;
295
313
  }
314
+ | { type: "workflow_invocation_claimed"; requestId: string; claimed: boolean }
296
315
  | { type: "registration_failed"; reason: string; code?: LiveWorkflowStageRouteRefusalCode; requestId?: string }
297
316
  | { type: "question_target"; messageId: string; attemptId: string; sessionId: string }
298
317
  | { type: "sessions"; requestId: string; sessions: SessionInfo[]; workflowStages?: WorkflowStageRosterEntry[]; workflowFutureStages?: WorkflowFutureStageRosterEntry[]; restricted?: true }
@@ -311,6 +330,8 @@ export type BrokerMessage =
311
330
  target: string;
312
331
  message: Message;
313
332
  live?: boolean;
333
+ /** #4006: the broker authorized the sender as the session that launched this run, not by membership. */
334
+ invocationControl?: true;
314
335
  }
315
336
  | { type: "live_workflow_stage_route_registered"; requestId: string }
316
337
  | { type: "pending_stage_route_registered"; requestId: string }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.45",
3
+ "version": "0.9.46",
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,27 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.46] - 2026-10-27
6
+
7
+ ### Fixed
8
+
9
+ - A subagent that waited for a free slot (`concurrency`, or a burst of launches) or was restored, and that starts after its parent workflow stage's session was replaced by model fallback, now launches instead of failing with `This extension ctx is stale after session replacement or reload`. It takes its settings from the replacement session, and starts in the directory it was launched for ([#3981](https://github.com/bastani-inc/atomic/issues/3981))
10
+ - A detached subagent that exits after its parent workflow stage's session was replaced by model fallback still sends its completion notice. Before, the notice was lost and the workflow run failed with `This extension ctx is stale after session replacement or reload` ([#3981](https://github.com/bastani-inc/atomic/issues/3981))
11
+ - A resumed subagent child now receives its resume message and the messages it had queued and not read exactly as written. They used to go through `prompt()` or `followUp()` depending on whether the child had held messages, so `/review …` was replaced by a prompt template's contents, a registered command such as `/workflow` either ran or failed the child with `Extension command "/workflow" cannot be queued`, and text the child had already received was expanded a second time. Only an original task the child never read is still prompted the way a fresh launch prompts it ([#4027](https://github.com/bastani-inc/atomic/pull/4027)).
12
+ - A subagent child paused, quit or stopped by its owner while it waited for its run's running capacity, before its session existed, can be resumed and restored again: it used to report `could not be resumed: no session was recorded for it`. A child admitted behind its run's concurrency limit and stopped that way no longer receives its task twice when it is restored. Resuming or restoring a child that had not started now says it started fresh with its task instead of claiming it resumed from its own session ([#4027](https://github.com/bastani-inc/atomic/pull/4027)).
13
+ - A subagent whose model is pinned with a thinking suffix (such as `provider/model:low`) no longer shows that suffix as part of its model on its launch and status cards once its session has started; the cards show `provider/model` and the thinking level beside it, as they do before the session starts ([#4009](https://github.com/bastani-inc/atomic/issues/4009))
14
+ - A paused subagent child resumed without a message, and a child restored after a restart, are now told to redo or continue a command or step the pause or restart interrupted, as a resumed workflow stage is ([#3996](https://github.com/bastani-inc/atomic/issues/3996))
15
+
16
+ ## [0.9.46-alpha.1] - 2026-10-27
17
+
18
+ ### Fixed
19
+
20
+ - A subagent that waited for a free slot (`concurrency`, or a burst of launches) or was restored, and that starts after its parent workflow stage's session was replaced by model fallback, now launches instead of failing with `This extension ctx is stale after session replacement or reload`. It takes its settings from the replacement session, and starts in the directory it was launched for ([#3981](https://github.com/bastani-inc/atomic/issues/3981))
21
+ - A detached subagent that exits after its parent workflow stage's session was replaced by model fallback still sends its completion notice. Before, the notice was lost and the workflow run failed with `This extension ctx is stale after session replacement or reload` ([#3981](https://github.com/bastani-inc/atomic/issues/3981))
22
+ - A resumed subagent child now receives its resume message and the messages it had queued and not read exactly as written. They used to go through `prompt()` or `followUp()` depending on whether the child had held messages, so `/review …` was replaced by a prompt template's contents, a registered command such as `/workflow` either ran or failed the child with `Extension command "/workflow" cannot be queued`, and text the child had already received was expanded a second time. Only an original task the child never read is still prompted the way a fresh launch prompts it ([#4027](https://github.com/bastani-inc/atomic/pull/4027)).
23
+ - A subagent child paused, quit or stopped by its owner while it waited for its run's running capacity, before its session existed, can be resumed and restored again: it used to report `could not be resumed: no session was recorded for it`. A child admitted behind its run's concurrency limit and stopped that way no longer receives its task twice when it is restored. Resuming or restoring a child that had not started now says it started fresh with its task instead of claiming it resumed from its own session ([#4027](https://github.com/bastani-inc/atomic/pull/4027)).
24
+ - A subagent whose model is pinned with a thinking suffix (such as `provider/model:low`) no longer shows that suffix as part of its model on its launch and status cards once its session has started; the cards show `provider/model` and the thinking level beside it, as they do before the session starts ([#4009](https://github.com/bastani-inc/atomic/issues/4009))
25
+
5
26
  ## [0.9.44] - 2026-10-25
6
27
 
7
28
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.45",
3
+ "version": "0.9.46",
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": [