@athenaintel/react 0.41.2 → 0.42.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 (451) hide show
  1. package/README.md +108 -9
  2. package/dist/agent-runtime/src/asset-attachment.d.ts +98 -0
  3. package/dist/agent-runtime/src/athena-asset-drag.d.ts +32 -0
  4. package/dist/agent-runtime/src/auth-denial.d.ts +29 -0
  5. package/dist/agent-runtime/src/chat-outbox-attachments.cjs +41 -0
  6. package/dist/agent-runtime/src/chat-outbox-attachments.cjs.map +1 -0
  7. package/dist/agent-runtime/src/chat-outbox-attachments.d.ts +38 -0
  8. package/dist/agent-runtime/src/chat-outbox-attachments.js +41 -0
  9. package/dist/agent-runtime/src/chat-outbox-attachments.js.map +1 -0
  10. package/dist/agent-runtime/src/chat-outbox-signals.cjs +63 -0
  11. package/dist/agent-runtime/src/chat-outbox-signals.cjs.map +1 -0
  12. package/dist/agent-runtime/src/chat-outbox-signals.d.ts +12 -0
  13. package/dist/agent-runtime/src/chat-outbox-signals.js +63 -0
  14. package/dist/agent-runtime/src/chat-outbox-signals.js.map +1 -0
  15. package/dist/agent-runtime/src/chat-outbox-store.cjs +509 -0
  16. package/dist/agent-runtime/src/chat-outbox-store.cjs.map +1 -0
  17. package/dist/agent-runtime/src/chat-outbox-store.d.ts +203 -0
  18. package/dist/agent-runtime/src/chat-outbox-store.js +509 -0
  19. package/dist/agent-runtime/src/chat-outbox-store.js.map +1 -0
  20. package/dist/agent-runtime/src/chat-outbox-thread.cjs +136 -0
  21. package/dist/agent-runtime/src/chat-outbox-thread.cjs.map +1 -0
  22. package/dist/agent-runtime/src/chat-outbox-thread.d.ts +118 -0
  23. package/dist/agent-runtime/src/chat-outbox-thread.js +136 -0
  24. package/dist/agent-runtime/src/chat-outbox-thread.js.map +1 -0
  25. package/dist/agent-runtime/src/chat-outbox.cjs +696 -0
  26. package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -0
  27. package/dist/agent-runtime/src/chat-outbox.d.ts +285 -0
  28. package/dist/agent-runtime/src/chat-outbox.js +696 -0
  29. package/dist/agent-runtime/src/chat-outbox.js.map +1 -0
  30. package/dist/agent-runtime/src/chat-socket-reachability.d.ts +45 -0
  31. package/dist/agent-runtime/src/client-tool-bridge.d.ts +152 -0
  32. package/dist/agent-runtime/src/client-tools.d.ts +133 -0
  33. package/dist/agent-runtime/src/composer-markdown.cjs +10 -0
  34. package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
  35. package/dist/agent-runtime/src/composer-markdown.d.ts +108 -0
  36. package/dist/agent-runtime/src/composer-markdown.js +10 -0
  37. package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
  38. package/dist/agent-runtime/src/config-mutations.d.ts +51 -0
  39. package/dist/agent-runtime/src/conversation-index.d.ts +110 -0
  40. package/dist/agent-runtime/src/conversation-list.d.ts +343 -0
  41. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +3 -2
  42. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
  43. package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +166 -0
  44. package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -2
  45. package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
  46. package/dist/agent-runtime/src/desktop-handoff.d.ts +139 -0
  47. package/dist/agent-runtime/src/durable-thread-snapshot-cache.cjs +158 -0
  48. package/dist/agent-runtime/src/durable-thread-snapshot-cache.cjs.map +1 -0
  49. package/dist/agent-runtime/src/durable-thread-snapshot-cache.d.ts +60 -0
  50. package/dist/agent-runtime/src/durable-thread-snapshot-cache.js +158 -0
  51. package/dist/agent-runtime/src/durable-thread-snapshot-cache.js.map +1 -0
  52. package/dist/agent-runtime/src/edit-command.d.ts +156 -0
  53. package/dist/agent-runtime/src/errors.d.ts +174 -0
  54. package/dist/agent-runtime/src/execute-output.d.ts +31 -0
  55. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +16 -2
  56. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  57. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +202 -0
  58. package/dist/agent-runtime/src/generated/runconfig-contract.js +16 -2
  59. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  60. package/dist/agent-runtime/src/github-wake-event.d.ts +77 -0
  61. package/dist/agent-runtime/src/index.d.ts +74 -0
  62. package/dist/agent-runtime/src/interrupts.cjs +17 -0
  63. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  64. package/dist/agent-runtime/src/interrupts.d.ts +348 -0
  65. package/dist/agent-runtime/src/interrupts.js +17 -0
  66. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  67. package/dist/agent-runtime/src/lane-follow.d.ts +121 -0
  68. package/dist/agent-runtime/src/lane-history.cjs +209 -0
  69. package/dist/agent-runtime/src/lane-history.cjs.map +1 -0
  70. package/dist/agent-runtime/src/lane-history.d.ts +175 -0
  71. package/dist/agent-runtime/src/lane-history.js +209 -0
  72. package/dist/agent-runtime/src/lane-history.js.map +1 -0
  73. package/dist/agent-runtime/src/lane-images.d.ts +184 -0
  74. package/dist/agent-runtime/src/message-author.d.ts +43 -0
  75. package/dist/agent-runtime/src/message-text.cjs +15 -0
  76. package/dist/agent-runtime/src/message-text.cjs.map +1 -0
  77. package/dist/agent-runtime/src/message-text.d.ts +47 -0
  78. package/dist/agent-runtime/src/message-text.js +15 -0
  79. package/dist/agent-runtime/src/message-text.js.map +1 -0
  80. package/dist/agent-runtime/src/message-window.cjs +15 -1
  81. package/dist/agent-runtime/src/message-window.cjs.map +1 -1
  82. package/dist/agent-runtime/src/message-window.d.ts +159 -0
  83. package/dist/agent-runtime/src/message-window.js +16 -2
  84. package/dist/agent-runtime/src/message-window.js.map +1 -1
  85. package/dist/agent-runtime/src/messages.cjs +88 -4
  86. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  87. package/dist/agent-runtime/src/messages.d.ts +603 -0
  88. package/dist/agent-runtime/src/messages.js +88 -4
  89. package/dist/agent-runtime/src/messages.js.map +1 -1
  90. package/dist/agent-runtime/src/model-context.d.ts +22 -0
  91. package/dist/agent-runtime/src/offline-status.d.ts +157 -0
  92. package/dist/agent-runtime/src/optimistic-content.d.ts +21 -0
  93. package/dist/agent-runtime/src/protocol.cjs +12 -4
  94. package/dist/agent-runtime/src/protocol.cjs.map +1 -1
  95. package/dist/agent-runtime/src/protocol.d.ts +119 -0
  96. package/dist/agent-runtime/src/protocol.js +13 -5
  97. package/dist/agent-runtime/src/protocol.js.map +1 -1
  98. package/dist/agent-runtime/src/ptc-subcalls.d.ts +51 -0
  99. package/dist/agent-runtime/src/queue.d.ts +138 -0
  100. package/dist/agent-runtime/src/quota-safe-local-storage-session.d.ts +154 -0
  101. package/dist/agent-runtime/src/running-tool-placeholder.cjs +11 -0
  102. package/dist/agent-runtime/src/running-tool-placeholder.cjs.map +1 -0
  103. package/dist/agent-runtime/src/running-tool-placeholder.d.ts +25 -0
  104. package/dist/agent-runtime/src/running-tool-placeholder.js +11 -0
  105. package/dist/agent-runtime/src/running-tool-placeholder.js.map +1 -0
  106. package/dist/agent-runtime/src/runtime-messages.d.ts +104 -0
  107. package/dist/agent-runtime/src/screen-point.d.ts +151 -0
  108. package/dist/agent-runtime/src/sealed-idb.cjs +112 -0
  109. package/dist/agent-runtime/src/sealed-idb.cjs.map +1 -0
  110. package/dist/agent-runtime/src/sealed-idb.d.ts +106 -0
  111. package/dist/agent-runtime/src/sealed-idb.js +112 -0
  112. package/dist/agent-runtime/src/sealed-idb.js.map +1 -0
  113. package/dist/agent-runtime/src/send-recovery.d.ts +40 -0
  114. package/dist/agent-runtime/src/statewire-attach-observer.d.ts +194 -0
  115. package/dist/agent-runtime/src/statewire-diagnostics.d.ts +74 -0
  116. package/dist/agent-runtime/src/statewire-state.d.ts +29 -0
  117. package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  118. package/dist/agent-runtime/src/statewire-suspended.d.ts +27 -0
  119. package/dist/agent-runtime/src/statewire-suspended.js.map +1 -1
  120. package/dist/agent-runtime/src/statewire-transport.d.ts +40 -0
  121. package/dist/agent-runtime/src/streaming-markdown.d.ts +46 -0
  122. package/dist/agent-runtime/src/subagent-transcripts.cjs +209 -0
  123. package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -0
  124. package/dist/agent-runtime/src/subagent-transcripts.d.ts +71 -0
  125. package/dist/agent-runtime/src/subagent-transcripts.js +209 -0
  126. package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -0
  127. package/dist/agent-runtime/src/subagents.cjs +253 -0
  128. package/dist/agent-runtime/src/subagents.cjs.map +1 -0
  129. package/dist/agent-runtime/src/subagents.d.ts +311 -0
  130. package/dist/agent-runtime/src/subagents.js +253 -0
  131. package/dist/agent-runtime/src/subagents.js.map +1 -0
  132. package/dist/agent-runtime/src/subscription-wake-event.d.ts +111 -0
  133. package/dist/agent-runtime/src/thread-extras.d.ts +43 -0
  134. package/dist/agent-runtime/src/thread-handoff.d.ts +364 -0
  135. package/dist/agent-runtime/src/thread-prewarm-controller.d.ts +76 -0
  136. package/dist/agent-runtime/src/thread-prewarm.d.ts +118 -0
  137. package/dist/agent-runtime/src/thread-snapshot-cache.d.ts +99 -0
  138. package/dist/agent-runtime/src/thread-snapshot-mirror.cjs +329 -0
  139. package/dist/agent-runtime/src/thread-snapshot-mirror.cjs.map +1 -0
  140. package/dist/agent-runtime/src/thread-snapshot-mirror.d.ts +101 -0
  141. package/dist/agent-runtime/src/thread-snapshot-mirror.js +329 -0
  142. package/dist/agent-runtime/src/thread-snapshot-mirror.js.map +1 -0
  143. package/dist/agent-runtime/src/thread-status.d.ts +53 -0
  144. package/dist/agent-runtime/src/tool-metadata.d.ts +146 -0
  145. package/dist/agent-runtime/src/tool-names.cjs +67 -0
  146. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  147. package/dist/agent-runtime/src/tool-names.d.ts +60 -0
  148. package/dist/agent-runtime/src/tool-names.js +68 -1
  149. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  150. package/dist/agent-runtime/src/tool-outputs.d.ts +35 -0
  151. package/dist/agent-runtime/src/tool-result.cjs +1 -0
  152. package/dist/agent-runtime/src/tool-result.cjs.map +1 -1
  153. package/dist/agent-runtime/src/tool-result.d.ts +126 -0
  154. package/dist/agent-runtime/src/tool-result.js +1 -0
  155. package/dist/agent-runtime/src/tool-result.js.map +1 -1
  156. package/dist/agent-runtime/src/types.d.ts +159 -0
  157. package/dist/agent-runtime/src/use-conversation-list.d.ts +76 -0
  158. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +136 -0
  159. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -0
  160. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +64 -0
  161. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +136 -0
  162. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -0
  163. package/dist/agent-runtime/src/use-deep-agent-config.d.ts +169 -0
  164. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +13 -0
  165. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  166. package/dist/agent-runtime/src/use-deep-agent-edit-submit.d.ts +22 -0
  167. package/dist/agent-runtime/src/use-deep-agent-edit-submit.js +13 -0
  168. package/dist/agent-runtime/src/use-deep-agent-edit-submit.js.map +1 -1
  169. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +20 -2
  170. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  171. package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +168 -0
  172. package/dist/agent-runtime/src/use-deep-agent-runtime.js +20 -2
  173. package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
  174. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +12 -4
  175. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  176. package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +320 -0
  177. package/dist/agent-runtime/src/use-deep-agent-thread.js +12 -4
  178. package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  179. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +999 -0
  180. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -0
  181. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +409 -0
  182. package/dist/agent-runtime/src/use-deep-agent-voice.js +999 -0
  183. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -0
  184. package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +102 -0
  185. package/dist/agent-runtime/src/use-historical-edit-attachments.d.ts +2 -0
  186. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +84 -0
  187. package/dist/agent-runtime/src/voice-presentation.d.ts +80 -0
  188. package/dist/agent-runtime/src/voice-turn-grouping.d.ts +28 -0
  189. package/dist/agent-runtime/src/voice-wire-types.d.ts +15 -0
  190. package/dist/agent-runtime/src/withdrawn-turns.d.ts +97 -0
  191. package/dist/chat/AthenaChat.cjs +77 -6
  192. package/dist/chat/AthenaChat.cjs.map +1 -1
  193. package/dist/chat/AthenaChat.js +78 -7
  194. package/dist/chat/AthenaChat.js.map +1 -1
  195. package/dist/chat/StatewireApprovalCard.d.ts +1 -1
  196. package/dist/chat/StatewireClientToolBridge.d.ts +1 -1
  197. package/dist/chat/StatewireQueuedMessages.cjs +11 -4
  198. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  199. package/dist/chat/StatewireQueuedMessages.d.ts +1 -1
  200. package/dist/chat/StatewireQueuedMessages.js +11 -4
  201. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  202. package/dist/chat/chat-outbox-rows.cjs +223 -0
  203. package/dist/chat/chat-outbox-rows.cjs.map +1 -0
  204. package/dist/chat/chat-outbox-rows.d.ts +29 -0
  205. package/dist/chat/chat-outbox-rows.js +223 -0
  206. package/dist/chat/chat-outbox-rows.js.map +1 -0
  207. package/dist/chat/statewire-approval.d.ts +1 -1
  208. package/dist/chat/statewire-client-tools.d.ts +1 -1
  209. package/dist/chat/super-grouping/SuperGroupingCard.cjs +3 -1
  210. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  211. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +7 -1
  212. package/dist/chat/super-grouping/SuperGroupingCard.js +3 -1
  213. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  214. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +7 -2
  215. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  216. package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +2 -2
  217. package/dist/chat/super-grouping/SuperGroupingTranscript.js +7 -2
  218. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  219. package/dist/chat/super-grouping/activity-timeline.cjs +19 -11
  220. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  221. package/dist/chat/super-grouping/activity-timeline.d.ts +25 -9
  222. package/dist/chat/super-grouping/activity-timeline.js +19 -11
  223. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  224. package/dist/chat/use-statewire-approval-request.cjs +36 -0
  225. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  226. package/dist/chat/use-statewire-approval-request.d.ts +49 -1
  227. package/dist/chat/use-statewire-approval-request.js +39 -3
  228. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  229. package/dist/chat-ui/composer/tiptap-composer.cjs +102 -3
  230. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  231. package/dist/chat-ui/composer/tiptap-composer.d.ts +32 -1
  232. package/dist/chat-ui/composer/tiptap-composer.js +103 -4
  233. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  234. package/dist/chat-ui/header/conversation-history-panel.d.ts +1 -1
  235. package/dist/chat-ui/index.d.ts +1 -1
  236. package/dist/chat-ui/messages/message-components.cjs +15 -0
  237. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  238. package/dist/chat-ui/messages/message-components.js +15 -0
  239. package/dist/chat-ui/messages/message-components.js.map +1 -1
  240. package/dist/chat-ui/messages/runtime-message.d.ts +1 -1
  241. package/dist/chat-ui/messages/statewire-continue-run.d.ts +1 -1
  242. package/dist/chat-ui/messages/user-edit-composer.cjs +15 -2
  243. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  244. package/dist/chat-ui/messages/user-edit-composer.d.ts +4 -2
  245. package/dist/chat-ui/messages/user-edit-composer.js +15 -2
  246. package/dist/chat-ui/messages/user-edit-composer.js.map +1 -1
  247. package/dist/chat-ui/messages/wake-marker.d.ts +1 -1
  248. package/dist/chat-ui/rich-text/chat-text-schema.cjs +1 -0
  249. package/dist/chat-ui/rich-text/chat-text-schema.cjs.map +1 -1
  250. package/dist/chat-ui/rich-text/chat-text-schema.d.ts +3 -0
  251. package/dist/chat-ui/rich-text/chat-text-schema.js +1 -0
  252. package/dist/chat-ui/rich-text/chat-text-schema.js.map +1 -1
  253. package/dist/chat-ui/statewire.cjs +1 -0
  254. package/dist/chat-ui/statewire.cjs.map +1 -1
  255. package/dist/chat-ui/statewire.d.ts +2 -2
  256. package/dist/chat-ui/statewire.js +2 -1
  257. package/dist/chat-ui/thread/statewire-history-edge.d.ts +1 -1
  258. package/dist/composer/AttachmentContext.cjs +8 -4
  259. package/dist/composer/AttachmentContext.cjs.map +1 -1
  260. package/dist/composer/AttachmentContext.d.ts +7 -0
  261. package/dist/composer/AttachmentContext.js +8 -4
  262. package/dist/composer/AttachmentContext.js.map +1 -1
  263. package/dist/composer/build-composed-message.cjs +34 -0
  264. package/dist/composer/build-composed-message.cjs.map +1 -1
  265. package/dist/composer/build-composed-message.d.ts +20 -0
  266. package/dist/composer/build-composed-message.js +35 -1
  267. package/dist/composer/build-composed-message.js.map +1 -1
  268. package/dist/composer/composer-handoff.cjs +39 -2
  269. package/dist/composer/composer-handoff.cjs.map +1 -1
  270. package/dist/composer/composer-handoff.d.ts +28 -3
  271. package/dist/composer/composer-handoff.js +39 -2
  272. package/dist/composer/composer-handoff.js.map +1 -1
  273. package/dist/composer/useAttachFiles.cjs +15 -2
  274. package/dist/composer/useAttachFiles.cjs.map +1 -1
  275. package/dist/composer/useAttachFiles.d.ts +11 -0
  276. package/dist/composer/useAttachFiles.js +15 -2
  277. package/dist/composer/useAttachFiles.js.map +1 -1
  278. package/dist/composer/useSendMessage.cjs.map +1 -1
  279. package/dist/composer/useSendMessage.d.ts +4 -3
  280. package/dist/composer/useSendMessage.js.map +1 -1
  281. package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
  282. package/dist/diagnostics/athena-diagnostics.d.ts +3 -1
  283. package/dist/diagnostics/athena-diagnostics.js.map +1 -1
  284. package/dist/index.cjs +18 -0
  285. package/dist/index.cjs.map +1 -1
  286. package/dist/index.d.ts +15 -6
  287. package/dist/index.js +19 -1
  288. package/dist/index.js.map +1 -1
  289. package/dist/offline/chat-outbox.cjs +57 -0
  290. package/dist/offline/chat-outbox.cjs.map +1 -0
  291. package/dist/offline/chat-outbox.d.ts +80 -0
  292. package/dist/offline/chat-outbox.js +57 -0
  293. package/dist/offline/chat-outbox.js.map +1 -0
  294. package/dist/offline/offline-history.cjs +77 -0
  295. package/dist/offline/offline-history.cjs.map +1 -0
  296. package/dist/offline/offline-history.d.ts +60 -0
  297. package/dist/offline/offline-history.js +77 -0
  298. package/dist/offline/offline-history.js.map +1 -0
  299. package/dist/provider/AthenaProvider.cjs +206 -9
  300. package/dist/provider/AthenaProvider.cjs.map +1 -1
  301. package/dist/provider/AthenaProvider.d.ts +22 -1
  302. package/dist/provider/AthenaProvider.js +207 -10
  303. package/dist/provider/AthenaProvider.js.map +1 -1
  304. package/dist/provider/statewire-window-context.d.ts +1 -1
  305. package/dist/react/package.json.cjs +1 -1
  306. package/dist/react/package.json.js +1 -1
  307. package/dist/references/src/anchors/file-line-range.d.ts +58 -0
  308. package/dist/references/src/anchors/format.d.ts +21 -0
  309. package/dist/references/src/anchors/message-anchors.d.ts +71 -0
  310. package/dist/references/src/anchors/parse.d.ts +8 -0
  311. package/dist/references/src/anchors/registry-contract.d.ts +24 -0
  312. package/dist/references/src/anchors/registry.d.ts +19 -0
  313. package/dist/references/src/anchors/schemas.d.ts +194 -0
  314. package/dist/references/src/anchors/serialize.d.ts +8 -0
  315. package/dist/references/src/anchors/time.d.ts +78 -0
  316. package/dist/references/src/anchors/types.d.ts +474 -0
  317. package/dist/references/src/asset-bounds.d.ts +27 -0
  318. package/dist/references/src/asset-links.d.ts +23 -0
  319. package/dist/references/src/asset-reference.d.ts +16 -0
  320. package/dist/references/src/formats/format-catalog.d.ts +79 -0
  321. package/dist/references/src/formats/markdown/parse-reference-markdown.d.ts +28 -0
  322. package/dist/references/src/formats/markdown/reference-display-name.d.ts +6 -0
  323. package/dist/references/src/formats/object/asset-object.d.ts +9 -0
  324. package/dist/references/src/formats/object/callable-object.d.ts +6 -0
  325. package/dist/references/src/formats/object/decode-reference-object-payload.d.ts +3 -0
  326. package/dist/references/src/formats/object/external-url-object.d.ts +9 -0
  327. package/dist/references/src/formats/object/group-object.d.ts +9 -0
  328. package/dist/references/src/formats/object/navigation-object.d.ts +9 -0
  329. package/dist/references/src/formats/object/parse-reference-object.d.ts +11 -0
  330. package/dist/references/src/formats/object/person-object.d.ts +9 -0
  331. package/dist/references/src/formats/uri/asset-mention-uri.d.ts +9 -0
  332. package/dist/references/src/formats/uri/asset-spaces-url.d.ts +9 -0
  333. package/dist/references/src/formats/uri/callable-mention-uris.d.ts +9 -0
  334. package/dist/references/src/formats/uri/detect-uri-wire.d.ts +9 -0
  335. package/dist/references/src/formats/uri/group-mention-uri.d.ts +12 -0
  336. package/dist/references/src/formats/uri/navigation-spaces-url.d.ts +14 -0
  337. package/dist/references/src/formats/uri/parse-reference-uri.d.ts +20 -0
  338. package/dist/references/src/formats/uri/person-mention-uri.d.ts +9 -0
  339. package/dist/references/src/formats/uri/template-placeholder.d.ts +12 -0
  340. package/dist/references/src/index.d.ts +47 -0
  341. package/dist/references/src/legacy/index.d.ts +14 -0
  342. package/dist/references/src/legacy/pre-reference-asset-url.d.ts +57 -0
  343. package/dist/references/src/legacy/pre-reference-citation-bridge.d.ts +22 -0
  344. package/dist/references/src/legacy/pre-reference-citation.d.ts +138 -0
  345. package/dist/references/src/legacy/pre-reference-external-url.d.ts +31 -0
  346. package/dist/references/src/legacy/pre-reference-format.d.ts +8 -0
  347. package/dist/references/src/legacy/pre-reference-mention.d.ts +27 -0
  348. package/dist/references/src/legacy/pre-reference-object.d.ts +8 -0
  349. package/dist/references/src/legacy/pre-reference-uri.d.ts +12 -0
  350. package/dist/references/src/legacy.d.ts +2 -0
  351. package/dist/references/src/mention-href-patterns.d.ts +19 -0
  352. package/dist/references/src/mention-node/index.d.ts +5 -0
  353. package/dist/references/src/mention-node/mention-node.d.ts +31 -0
  354. package/dist/references/src/mention-node/resolve-node-attrs.d.ts +27 -0
  355. package/dist/references/src/parse-reference.d.ts +23 -0
  356. package/dist/references/src/schemas.d.ts +463 -0
  357. package/dist/references/src/serialize-reference.d.ts +50 -0
  358. package/dist/references/src/sheet-name.d.ts +10 -0
  359. package/dist/references/src/tool-option-schemas.d.ts +597 -0
  360. package/dist/references/src/types.d.ts +125 -0
  361. package/dist/references/src/version-ref.d.ts +30 -0
  362. package/dist/runtime/statewire-lifecycle.d.ts +1 -1
  363. package/dist/runtime/statewire-model-lane.d.ts +1 -1
  364. package/dist/runtime/statewire-server-lane-context.d.ts +1 -1
  365. package/dist/runtime/statewire-session-key.cjs +7 -0
  366. package/dist/runtime/statewire-session-key.cjs.map +1 -1
  367. package/dist/runtime/statewire-session-key.d.ts +16 -0
  368. package/dist/runtime/statewire-session-key.js +8 -1
  369. package/dist/runtime/statewire-session-key.js.map +1 -1
  370. package/dist/runtime/statewire-session-lane.cjs +48 -0
  371. package/dist/runtime/statewire-session-lane.cjs.map +1 -0
  372. package/dist/runtime/statewire-session-lane.d.ts +29 -0
  373. package/dist/runtime/statewire-session-lane.js +48 -0
  374. package/dist/runtime/statewire-session-lane.js.map +1 -0
  375. package/dist/runtime/statewire-thread-config-lane.d.ts +1 -1
  376. package/dist/runtime/useAthenaStatewireRuntime.cjs +16 -5
  377. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  378. package/dist/runtime/useAthenaStatewireRuntime.d.ts +15 -1
  379. package/dist/runtime/useAthenaStatewireRuntime.js +17 -6
  380. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  381. package/dist/styles.css +1 -1
  382. package/dist/threads/api.d.ts +1 -1
  383. package/dist/threads/conversation-list-fetcher.d.ts +1 -1
  384. package/dist/threads/index-triggered-refresh.cjs +164 -0
  385. package/dist/threads/index-triggered-refresh.cjs.map +1 -0
  386. package/dist/threads/index-triggered-refresh.d.ts +70 -0
  387. package/dist/threads/index-triggered-refresh.js +164 -0
  388. package/dist/threads/index-triggered-refresh.js.map +1 -0
  389. package/dist/threads/offline-session-list.cjs +75 -0
  390. package/dist/threads/offline-session-list.cjs.map +1 -0
  391. package/dist/threads/offline-session-list.d.ts +27 -0
  392. package/dist/threads/offline-session-list.js +75 -0
  393. package/dist/threads/offline-session-list.js.map +1 -0
  394. package/dist/threads/pull-request-display.d.ts +1 -1
  395. package/dist/threads/session-list-model.d.ts +1 -1
  396. package/dist/threads/session-list-tab-share.cjs +150 -0
  397. package/dist/threads/session-list-tab-share.cjs.map +1 -0
  398. package/dist/threads/session-list-tab-share.d.ts +73 -0
  399. package/dist/threads/session-list-tab-share.js +150 -0
  400. package/dist/threads/session-list-tab-share.js.map +1 -0
  401. package/dist/threads/session-row-parts.d.ts +1 -1
  402. package/dist/threads/sessions-query.d.ts +1 -1
  403. package/dist/threads/statewire-thread-list.cjs +105 -20
  404. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  405. package/dist/threads/statewire-thread-list.d.ts +31 -3
  406. package/dist/threads/statewire-thread-list.js +107 -22
  407. package/dist/threads/statewire-thread-list.js.map +1 -1
  408. package/dist/threads/thread-prefetcher.d.ts +1 -1
  409. package/dist/threads/use-athena-session-attention.d.ts +1 -1
  410. package/dist/threads/use-athena-sessions.cjs +32 -22
  411. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  412. package/dist/threads/use-athena-sessions.js +33 -23
  413. package/dist/threads/use-athena-sessions.js.map +1 -1
  414. package/dist/threads/use-rest-conversation-history.d.ts +1 -1
  415. package/dist/threads/use-statewire-conversation-history.d.ts +5 -5
  416. package/dist/tiptap-markdown-table/src/markdown-table-serializer.d.ts +56 -0
  417. package/dist/tools/NestedPtcMessages.cjs +14 -9
  418. package/dist/tools/NestedPtcMessages.cjs.map +1 -1
  419. package/dist/tools/NestedPtcMessages.d.ts +9 -0
  420. package/dist/tools/NestedPtcMessages.js +6 -1
  421. package/dist/tools/NestedPtcMessages.js.map +1 -1
  422. package/dist/tools/index.d.ts +1 -1
  423. package/dist/tools/primitives.d.ts +1 -1
  424. package/dist/tools/subagent-task-tool-ui.cjs +494 -0
  425. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -0
  426. package/dist/tools/subagent-task-tool-ui.d.ts +109 -0
  427. package/dist/tools/subagent-task-tool-ui.js +494 -0
  428. package/dist/tools/subagent-task-tool-ui.js.map +1 -0
  429. package/dist/tools/tool-fallback.d.ts +1 -1
  430. package/dist/tools/tool-icons.d.ts +1 -1
  431. package/dist/tools/tool-summary.d.ts +1 -1
  432. package/dist/tools/tool-uis.cjs +4 -0
  433. package/dist/tools/tool-uis.cjs.map +1 -1
  434. package/dist/tools/tool-uis.js +4 -0
  435. package/dist/tools/tool-uis.js.map +1 -1
  436. package/dist/voice/chat.cjs +6 -0
  437. package/dist/voice/chat.cjs.map +1 -0
  438. package/dist/voice/chat.d.ts +2 -0
  439. package/dist/voice/chat.js +6 -0
  440. package/dist/voice/chat.js.map +1 -0
  441. package/dist/voice/livekit-join.cjs +119 -0
  442. package/dist/voice/livekit-join.cjs.map +1 -0
  443. package/dist/voice/livekit-join.d.ts +8 -0
  444. package/dist/voice/livekit-join.js +119 -0
  445. package/dist/voice/livekit-join.js.map +1 -0
  446. package/dist/voice/livekit.cjs +32 -0
  447. package/dist/voice/livekit.cjs.map +1 -0
  448. package/dist/voice/livekit.d.ts +80 -0
  449. package/dist/voice/livekit.js +32 -0
  450. package/dist/voice/livekit.js.map +1 -0
  451. package/package.json +20 -10
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-outbox.cjs","sources":["../../../../agent-runtime/src/chat-outbox.ts"],"sourcesContent":["import type { ChatOutboxAttachmentCheck, ChatOutboxAttachmentVerdict } from \"./chat-outbox-attachments\";\nimport type {\n ChatOutboxAttachment,\n ChatOutboxClaim,\n ChatOutboxEntry,\n ChatOutboxFailureReason,\n ChatOutboxFile,\n ChatOutboxRecord,\n ChatOutboxStore,\n} from \"./chat-outbox-store\";\n\n/**\n * The chat outbox: a message typed while Athena can't be reached waits on this device and is sent\n * once Athena answers again, while the app is in front, after a few seconds the person can cancel\n * (decision 5 of the offline plan, `docs/plans/2026-10-27-offline-everywhere-plan.md`).\n *\n * - **Held before the conversation's journal, never inside it.** A send made while Athena can't be\n * reached does not reach statewire at all: statewire would replay it the moment its connection\n * returns (from a hidden tab too) and has no way to take a journaled statement back. The message\n * waits here instead, and reaches statewire only when this controller hands it over, under the\n * id minted when it was typed.\n * - **Sent in front, with a countdown.** Once Athena is reachable and the app is in front (a visible\n * tab, an active app, a focused desktop window), the waiting messages count down\n * ({@link CHAT_OUTBOX_COUNTDOWN_MS}) with a Cancel that gives the text back to the composer; then\n * each is handed over once. Going to the background or losing Athena stops the countdown; it\n * starts over, in full, when both are back.\n * - **A day is the limit for sending on its own.** A message that waited more than\n * {@link CHAT_OUTBOX_ASK_AFTER_MS} asks first (Send / Edit / Discard); the messages behind it wait\n * for the answer, so nothing is sent out of order.\n * - **Once per message, never a loop.** A message is handed over at most once per return of Athena.\n * A hand-off that fails before the conversation took it (anything but the conversation going\n * away) stays as \"Couldn't send\" with Retry and Discard, kept with the message so no window and\n * no later mount sends it again on its own. Once the conversation's journal took it, statewire\n * owns it: it delivers it exactly once, and a refusal lands in the conversation's own failed\n * lane (Retry / Discard there).\n * - **One sender per message.** A hand-off claims the message in the store first, atomically\n * across windows ({@link CHAT_OUTBOX_CLAIM_LEASE_MS}), so two windows on the same conversation\n * never hand the same message twice (a second hand-off of an id whose run is in flight would be\n * read as an edit of that turn). The gate is checked again once the claim is written: a tab\n * hidden (or an Athena lost) meanwhile lets the claim go, and the message waits again.\n * - **Nothing overtakes.** Until the conversation's kept messages are read, a new send waits too\n * (it goes at once if nothing older turns up), and a message the person told to go now still\n * goes after the older ones in line.\n * - **Kept until it is safe to let go.** The waiting record is removed only once statewire has the\n * statement durably (`posted`, `applied` or settled), or once the conversation shows the message\n * (a journal adopted from an earlier page, or the message already on the transcript).\n * - **Its attachments go with it, still valid.** A message keeps the files that had finished\n * uploading before Athena went out of reach (references to files already in Athena; one picked\n * while it can't be reached is never attached). Once the message is claimed they are asked about\n * ({@link ChatOutboxOptions.checkAttachments}): one Athena refuses (deleted, or no longer shared\n * with the person) keeps the message as \"Couldn't send\" with Retry, Edit and Discard, and a check\n * Athena could not answer keeps it the same way as a send error. Nothing goes unchecked, and the\n * text is never lost.\n */\n\n/** How long the countdown before a waiting message is sent lasts. */\nexport const CHAT_OUTBOX_COUNTDOWN_MS = 5_000;\n/** A message that waited longer than this asks before it is sent. */\nexport const CHAT_OUTBOX_ASK_AFTER_MS = 24 * 60 * 60 * 1000;\n/** How long a window's claim on a message holds against another window's hand-off. */\nexport const CHAT_OUTBOX_CLAIM_LEASE_MS = 30_000;\n/** How long the check of a message's attachments may take before it counts as unanswered. */\nexport const CHAT_OUTBOX_ATTACHMENT_CHECK_TIMEOUT_MS = 15_000;\n\n/**\n * Why a sent message's Edit is not offered while Athena can't be reached (its tooltip, or the hint\n * under it where there are no tooltips). An edit rewinds the conversation and re-runs it: a\n * journaled one would replay the moment the connection returns, from a hidden window too, so an\n * edit never waits the way a new message does.\n */\nexport const CHAT_EDIT_UNREACHABLE_LABEL = \"Can't edit while Athena can't be reached\";\n\n/** What an edit submitted while Athena can't be reached says: the edit stays where it was typed. */\nexport const CHAT_EDIT_KEPT_MESSAGE =\n \"Can't reach Athena right now. Your edit stays here — submit it once Athena is back.\";\n\n/** An edit submitted while Athena can't be reached: refused, never queued (its message says so). */\nexport class ChatEditUnreachableError extends Error {\n constructor() {\n super(CHAT_EDIT_KEPT_MESSAGE);\n this.name = \"ChatEditUnreachableError\";\n }\n}\n\n/** A boolean the host reports and notifies on: Athena's reachability, the app being in front. */\nexport interface ChatOutboxSignal {\n get(): boolean;\n subscribe(listener: () => void): () => void;\n}\n\n/**\n * Whether a hand-off reaches the conversation now: `ready` (attached, a never-started chat that\n * dials on its first send, or an idle channel that reattaches on demand — in each case what the\n * conversation shows is the server's, so a message missing from it never reached it),\n * `connecting` (reattaching: what it shows may be a remembered snapshot), `refused` (the host\n * refused the conversation: stopped, or parked on an authorization denial).\n */\nexport type ChatOutboxThreadReadiness = \"ready\" | \"connecting\" | \"refused\";\n\n/** The conversation the outbox hands messages to (`chat-outbox-thread.ts` adapts a statewire thread). */\nexport interface ChatOutboxThreadPort {\n readiness(): ChatOutboxThreadReadiness;\n /**\n * Message ids the conversation shows anywhere: its transcript, its queue and steer lanes, the\n * run being dispatched, its failed lane — this page's journal included (statewire folds a\n * journaled send into them, one adopted from an earlier page too).\n */\n heldIds(): ReadonlySet<string>;\n /** Hand the message to the conversation under its own id; settles with the server's verdict. */\n send(entry: ChatOutboxEntry): Promise<unknown>;\n subscribe(listener: () => void): () => void;\n}\n\nexport type ChatOutboxRowState =\n /** Not sent yet: Athena can't be reached, or the app is not in front. */\n | { kind: \"waiting\" }\n /** Athena is back: the message is sent when the countdown ends, unless cancelled. */\n | { kind: \"countdown\"; endsAt: number }\n /** It waited more than a day: Send, Edit or Discard. */\n | { kind: \"ask\" }\n /** Being handed to the conversation (by this window or another). */\n | { kind: \"sending\" }\n /** The hand-off failed for a reason other than Athena being unreachable. */\n | { kind: \"failed\"; reason: ChatOutboxFailureReason; message: string };\n\nexport interface ChatOutboxRow {\n entry: ChatOutboxEntry;\n state: ChatOutboxRowState;\n}\n\n/** Another conversation of the same person with messages waiting (the tray offers to open it). */\nexport interface ChatOutboxElsewhere {\n threadId: string;\n /** How many messages wait there. */\n count: number;\n /** The oldest of them: its text names the conversation. */\n first: ChatOutboxEntry;\n /**\n * Every message waiting there was typed into a chat that had never started, so it opens as the\n * new chat it still is (one typed after the chat started says it has a session now).\n */\n newChat: boolean;\n}\n\nexport interface ChatOutboxSnapshot {\n rows: readonly ChatOutboxRow[];\n /** When the running countdown ends (epoch ms), or `null`. */\n countdownEndsAt: number | null;\n /** Whether every waiting message is kept on this device (false: only while the page stays open). */\n durable: boolean;\n /** Whether the thread's kept messages have been read. */\n loaded: boolean;\n /** The person's other conversations with messages waiting, oldest first. */\n elsewhere: readonly ChatOutboxElsewhere[];\n}\n\n/** What a failed row says. */\nexport function chatOutboxFailureMessage(reason: ChatOutboxFailureReason): string {\n switch (reason) {\n case \"refused\":\n return \"This conversation can't be reached right now.\";\n case \"prepare\":\n return \"Couldn't prepare this message to send.\";\n case \"attachment\":\n return \"An attachment is no longer available to you.\";\n default:\n return \"Couldn't send this message.\";\n }\n}\n\nexport interface ChatOutboxInput {\n text: string;\n composerMarkdown?: string;\n /** The draft as an HTML composer holds it (the phone's), given back exactly on Cancel. */\n composerHtml?: string;\n metadata?: Record<string, unknown>;\n files?: ChatOutboxFile[];\n /** Files already in Athena the message carries, asked about before it goes. */\n attachments?: ChatOutboxAttachment[];\n}\n\nexport type ChatOutboxEvent =\n | { type: \"held\"; threadId: string; messageId: string; durable: boolean }\n | { type: \"countdown-started\"; threadId: string; count: number }\n | { type: \"asked\"; threadId: string; messageId: string; ageMs: number }\n | { type: \"handed\"; threadId: string; messageId: string; auto: boolean; ageMs: number }\n | { type: \"delivered\"; threadId: string; messageId: string; status: string }\n | { type: \"adopted\"; threadId: string; messageId: string }\n | { type: \"failed\"; threadId: string; messageId: string; message: string; reason: ChatOutboxFailureReason }\n | { type: \"cancelled\"; threadId: string; messageId: string }\n | { type: \"discarded\"; threadId: string; messageId: string };\n\n/** The command-lifecycle update statewire reports (`onCommandChange`), structurally. */\nexport interface ChatOutboxCommandUpdate {\n status: \"queued\" | \"posted\" | \"applied\" | \"settled\";\n params?: readonly unknown[];\n failure?: { fate: string; cause?: string } | undefined;\n}\n\nexport interface ChatOutbox {\n readonly threadId: string;\n getSnapshot(): ChatOutboxSnapshot;\n subscribe(listener: () => void): () => void;\n /**\n * Whether Athena can be reached, as this outbox reads it (the host's model; in the SDK the\n * conversation's own channel too). An edit of a sent message waits on it as a send does: while it\n * says no, the Edit action is not offered and a submitted edit is refused\n * ({@link CHAT_EDIT_UNREACHABLE_LABEL}, {@link ChatEditUnreachableError}).\n */\n readonly reachability: ChatOutboxSignal;\n /**\n * Whether a send made now must wait here: Athena can't be reached, or earlier messages of this\n * conversation are still waiting (a later message never overtakes them).\n */\n shouldHold(): boolean;\n /** Keep a message typed now; it waits until it can be sent. */\n hold(input: ChatOutboxInput): ChatOutboxEntry;\n /** Cancel (or the ask's Edit): the message leaves the outbox and its text goes back to the composer. */\n cancel(id: string): void;\n /** The ask's Send, a failed row's Retry: hand it over now (one attempt; waits if Athena is out of reach). */\n send(id: string): void;\n discard(id: string): void;\n /** Feed statewire's command lifecycle (`onCommandChange`). */\n observeCommand(update: ChatOutboxCommandUpdate): void;\n /** Open another conversation the tray lists as holding waiting messages (`null`: the host cannot). */\n readonly openThread: ((target: { threadId: string; newChat: boolean }) => void) | null;\n dispose(): void;\n}\n\nexport interface ChatOutboxOptions {\n threadId: string;\n /**\n * The conversation has never started (a new chat): what waits reopens with it. Read when a\n * message is held, so a chat that started since stamps its later messages as started.\n */\n isNewChat: boolean | (() => boolean);\n /** Where waiting messages are kept for this person; `null` keeps them in memory only. */\n store: ChatOutboxStore | null;\n reachability: ChatOutboxSignal;\n foreground: ChatOutboxSignal;\n thread: ChatOutboxThreadPort;\n /** Give a cancelled message's text back to the composer. */\n restore: (entry: ChatOutboxEntry) => void;\n /**\n * Open another of the person's conversations that holds waiting messages (the tray's Open);\n * omitted where the host cannot switch conversations (an embedded chat).\n */\n openThread?: (target: { threadId: string; newChat: boolean }) => void;\n onEvent?: (event: ChatOutboxEvent) => void;\n /**\n * Asks Athena whether a waiting message's attachments can still be opened, right before it goes\n * (`createChatOutboxAttachmentCheck`). `refused` keeps the message as \"Couldn't send\" (Retry,\n * Edit, Discard); `unknown` too, as a send error. Omitted: attachments go unchecked.\n */\n checkAttachments?: ChatOutboxAttachmentCheck;\n now?: () => number;\n countdownMs?: number;\n askAfterMs?: number;\n claimLeaseMs?: number;\n /** How long the attachment check may take before it counts as unanswered. */\n attachmentCheckTimeoutMs?: number;\n newMessageId?: () => string;\n /** Timer seam (tests): schedule `task` after `ms`, returning what cancels it. */\n setTimer?: (task: () => void, ms: number) => () => void;\n}\n\ntype Phase =\n /** Waiting in line. */\n | { kind: \"idle\" }\n /**\n * The countdown ended (or the person said Send) while the conversation was reattaching, or\n * while the message's own write was still landing: it goes as soon as both are done.\n */\n | { kind: \"awaiting-thread\" }\n /** Claiming it in the store before the hand-off. */\n | { kind: \"claiming\" }\n /** Handed to the conversation; `journaled` once statewire's journal took it. */\n | { kind: \"handed\"; journaled: boolean }\n | { kind: \"failed\"; reason: ChatOutboxFailureReason };\n\n/** Fates statewire settles a send with when the conversation went away under it (not a failure). */\nconst AWAY_CAUSES: ReadonlySet<string> = new Set([\"unmount\", \"stream-gone\"]);\n\n/** The message id a run send carries, off a command update's params. */\nexport function chatOutboxCommandMessageId(params: readonly unknown[] | undefined): string | null {\n const first = params?.[0] as { message?: { id?: unknown } } | undefined;\n const id = first?.message?.id;\n return typeof id === \"string\" ? id : null;\n}\n\nfunction failureOf(error: unknown): { fate?: string; cause?: string; message: string } {\n const failure = (error as { failure?: { fate?: unknown; cause?: unknown } } | null)?.failure;\n const fate = typeof failure?.fate === \"string\" ? failure.fate : undefined;\n const cause = typeof failure?.cause === \"string\" ? failure.cause : undefined;\n const message = error instanceof Error ? error.message : String(error);\n return { fate, cause, message };\n}\n\nfunction defaultMessageId(): string {\n const host = globalThis as { crypto?: { randomUUID?: () => string } };\n if (typeof host.crypto?.randomUUID === \"function\") return host.crypto.randomUUID();\n // Hosts without randomUUID (none Athena ships today): a random v4-shaped id.\n const hex = Array.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-a${hex.slice(17, 20)}-${hex.slice(20, 32)}`;\n}\n\nfunction sameChatOutboxRowState(a: ChatOutboxRowState, b: ChatOutboxRowState): boolean {\n if (a.kind !== b.kind) return false;\n switch (a.kind) {\n case \"countdown\":\n return a.endsAt === (b as typeof a).endsAt;\n case \"failed\":\n return a.reason === (b as typeof a).reason && a.message === (b as typeof a).message;\n default:\n return true;\n }\n}\n\n/** Whether two listings of a message show the same thing (another chat's preview is re-read per listing). */\nfunction sameChatOutboxEntry(a: ChatOutboxEntry, b: ChatOutboxEntry): boolean {\n return (\n a === b ||\n (a.id === b.id &&\n a.threadId === b.threadId &&\n a.text === b.text &&\n a.newChat === b.newChat &&\n a.queuedAt === b.queuedAt &&\n a.composerMarkdown === b.composerMarkdown)\n );\n}\n\n/** Whether two snapshots show the same thing (the rows' entries by identity: a listing keeps them). */\nexport function sameChatOutboxSnapshot(a: ChatOutboxSnapshot, b: ChatOutboxSnapshot): boolean {\n if (a === b) return true;\n if (a.countdownEndsAt !== b.countdownEndsAt || a.durable !== b.durable || a.loaded !== b.loaded) return false;\n if (a.rows.length !== b.rows.length || a.elsewhere.length !== b.elsewhere.length) return false;\n for (let index = 0; index < a.rows.length; index += 1) {\n const x = a.rows[index];\n const y = b.rows[index];\n if (!x || !y || x.entry !== y.entry || !sameChatOutboxRowState(x.state, y.state)) return false;\n }\n for (let index = 0; index < a.elsewhere.length; index += 1) {\n const x = a.elsewhere[index];\n const y = b.elsewhere[index];\n if (\n !x ||\n !y ||\n x.threadId !== y.threadId ||\n x.count !== y.count ||\n x.newChat !== y.newChat ||\n !sameChatOutboxEntry(x.first, y.first)\n ) {\n return false;\n }\n }\n return true;\n}\n\nexport function createChatOutbox(options: ChatOutboxOptions): ChatOutbox {\n const {\n threadId,\n isNewChat,\n store,\n reachability,\n foreground,\n thread,\n restore,\n openThread,\n onEvent,\n checkAttachments,\n now = () => Date.now(),\n countdownMs = CHAT_OUTBOX_COUNTDOWN_MS,\n askAfterMs = CHAT_OUTBOX_ASK_AFTER_MS,\n claimLeaseMs = CHAT_OUTBOX_CLAIM_LEASE_MS,\n attachmentCheckTimeoutMs = CHAT_OUTBOX_ATTACHMENT_CHECK_TIMEOUT_MS,\n newMessageId = defaultMessageId,\n setTimer = (task, ms) => {\n const timer = setTimeout(task, ms);\n return () => clearTimeout(timer);\n },\n } = options;\n\n /** This controller's name on the claims it takes. */\n const claimant = newMessageId();\n let disposed = false;\n let loaded = store === null;\n /** The thread's waiting messages, oldest first. */\n let entries: ChatOutboxEntry[] = [];\n /** The person's other conversations with messages waiting. */\n let elsewhere: readonly ChatOutboxElsewhere[] = [];\n /** Claims as the store last reported them (another window's hand-off in progress). */\n let claims = new Map<string, ChatOutboxClaim>();\n /** Messages kept on the device (absent: in the store's memory only, or no store at all). */\n const persisted = new Set<string>();\n /**\n * Messages this window wrote to the store (the message itself, or Retry's cleared failure) that\n * a listing may not show yet: how many listings had started when the write settled, or\n * `undefined` while it is pending. A listing that started before then is not believed about\n * them (it would drop a message just kept, or bring back a failure just cleared).\n */\n const unsettled = new Map<string, number | undefined>();\n let listingsStarted = 0;\n const phases = new Map<string, Phase>();\n /** Messages the person told to go now (the ask's Send, Retry): they skip the countdown. */\n const sendNow = new Set<string>();\n /** The return of Athena each message was last handed over in (one hand-off per return). */\n const handedInRegain = new Map<string, number>();\n let regain = 0;\n let wasReachable = reachability.get();\n let countdown: { endsAt: number; ids: readonly string[]; cancel: () => void } | null = null;\n let leaseTimer: (() => void) | null = null;\n /** The running attachment checks' time limits (stopped on dispose). */\n const checkTimers = new Set<() => void>();\n /**\n * Claimed messages ready to be handed over (their attachments checked, or none), each with\n * whether it goes on its own: they go in line, behind any older one still being claimed or\n * asked about ({@link releaseReady}).\n */\n const readyToGo = new Map<string, boolean>();\n let releasing = false;\n const asked = new Set<string>();\n const listeners = new Set<() => void>();\n let snapshot: ChatOutboxSnapshot = {\n rows: [],\n countdownEndsAt: null,\n durable: true,\n loaded,\n elsewhere,\n };\n\n const emit = (event: ChatOutboxEvent): void => {\n try {\n onEvent?.(event);\n } catch {\n // Telemetry never reaches the send path.\n }\n };\n\n const phaseOf = (id: string): Phase => phases.get(id) ?? { kind: \"idle\" };\n const isBusy = (phase: Phase): boolean =>\n phase.kind === \"claiming\" || phase.kind === \"handed\" || phase.kind === \"awaiting-thread\";\n /** Another window holds a live claim on it. */\n const claimedElsewhere = (id: string): boolean => {\n const claim = claims.get(id);\n return claim !== undefined && claim.by !== claimant && now() - claim.at < claimLeaseMs;\n };\n /** Whether a listing that started as listing number `listing` may speak for the message. */\n const settledFor = (id: string, listing: number): boolean => {\n if (!unsettled.has(id)) return true;\n const settledAt = unsettled.get(id);\n return settledAt !== undefined && listing > settledAt;\n };\n /** Whether this window's write of the message has not landed yet. */\n const writePending = (id: string): boolean => unsettled.has(id) && unsettled.get(id) === undefined;\n const markUnsettled = (id: string, write: Promise<unknown>): void => {\n unsettled.set(id, undefined);\n const settle = () => {\n if (!unsettled.has(id)) return;\n unsettled.set(id, listingsStarted);\n // A hand-off deferred for this write goes now.\n evaluate();\n };\n void write.then(settle, settle);\n };\n\n interface Line {\n /** The messages that would go next, in order, before any that must ask. */\n run: ChatOutboxEntry[];\n /** The head of the line when it waited more than a day. */\n askId: string | null;\n }\n\n const rowState = (entry: ChatOutboxEntry, line: Line): ChatOutboxRowState => {\n const phase = phaseOf(entry.id);\n if (phase.kind === \"failed\") {\n return { kind: \"failed\", reason: phase.reason, message: chatOutboxFailureMessage(phase.reason) };\n }\n if (isBusy(phase) || claimedElsewhere(entry.id)) return { kind: \"sending\" };\n // In line behind (or in) the running countdown: it goes when the countdown ends.\n if (countdown !== null && line.run.some((candidate) => candidate.id === entry.id)) {\n return { kind: \"countdown\", endsAt: countdown.endsAt };\n }\n if (line.askId === entry.id) return { kind: \"ask\" };\n return { kind: \"waiting\" };\n };\n\n /** The waiting messages in line to be sent, given that the gate is open. */\n const computeLine = (): Line => {\n const run: ChatOutboxEntry[] = [];\n for (const entry of entries) {\n const phase = phaseOf(entry.id);\n // A failed message is out of line until the person decides; one being handed (here or in\n // another window) is ahead of everything behind it.\n if (phase.kind === \"failed\") continue;\n if (isBusy(phase) || claimedElsewhere(entry.id)) continue;\n if (handedInRegain.get(entry.id) === regain && !sendNow.has(entry.id)) continue;\n if (!sendNow.has(entry.id) && now() - entry.queuedAt > askAfterMs) {\n return { run, askId: run.length === 0 ? entry.id : null };\n }\n run.push(entry);\n }\n return { run, askId: null };\n };\n\n const gateOpen = (): boolean => reachability.get() && foreground.get();\n\n /**\n * Re-read the snapshot; listeners hear from it only when something they would show changed.\n * The outbox re-evaluates on every notification of the thread it serves, and a host renders on\n * every snapshot it is handed (`useChatOutboxSnapshot`): a fresh object for an unchanged state\n * would send that host round again (render -> thread notification -> publish -> render).\n */\n const publish = (): void => {\n const line = gateOpen() ? computeLine() : { run: [], askId: null };\n const next: ChatOutboxSnapshot = {\n rows: entries.map((entry) => ({ entry, state: rowState(entry, line) })),\n countdownEndsAt: countdown?.endsAt ?? null,\n durable: entries.every((entry) => persisted.has(entry.id)),\n loaded,\n elsewhere,\n };\n if (sameChatOutboxSnapshot(snapshot, next)) return;\n snapshot = next;\n for (const listener of listeners) {\n try {\n listener();\n } catch {\n // A listener's fault never reaches the outbox.\n }\n }\n };\n\n const stopCountdown = (): void => {\n countdown?.cancel();\n countdown = null;\n };\n\n const dropEntry = (id: string): void => {\n entries = entries.filter((entry) => entry.id !== id);\n unsettled.delete(id);\n phases.delete(id);\n readyToGo.delete(id);\n sendNow.delete(id);\n persisted.delete(id);\n claims.delete(id);\n asked.delete(id);\n if (countdown?.ids.includes(id)) stopCountdown();\n };\n\n /** The conversation has the message now (its journal or its transcript): let the record go. */\n const letGo = (id: string, event: ChatOutboxEvent): void => {\n if (!entries.some((entry) => entry.id === id)) return;\n dropEntry(id);\n emit(event);\n if (store) void store.remove(threadId, id).catch(() => undefined);\n };\n\n /** \"Couldn't send\": kept with the message, so nothing sends it again until the person retries. */\n const fail = (id: string, reason: ChatOutboxFailureReason): void => {\n phases.set(id, { kind: \"failed\", reason });\n sendNow.delete(id);\n emit({ type: \"failed\", threadId, messageId: id, message: chatOutboxFailureMessage(reason), reason });\n if (store) {\n void store\n .markFailed({ threadId, id, claimant, failure: { reason, at: now() } })\n .catch(() => undefined);\n }\n };\n\n /** Let this window's claim go: the hand-off did not start. */\n const releaseClaim = (id: string): void => {\n if (store) void store.release({ threadId, id, claimant }).catch(() => undefined);\n };\n\n /** Statewire's journal took it, or it ended without reaching it. */\n const handOff = (entry: ChatOutboxEntry, auto: boolean): void => {\n // The conversation may have taken it since the last evaluation (an attach that just landed\n // shows a message an earlier page already delivered): never hand an id it holds.\n if (thread.heldIds().has(entry.id)) {\n letGo(entry.id, { type: \"adopted\", threadId, messageId: entry.id });\n return;\n }\n const readiness = thread.readiness();\n if (readiness === \"refused\") {\n fail(entry.id, \"refused\");\n return;\n }\n if (readiness === \"connecting\") {\n phases.set(entry.id, { kind: \"awaiting-thread\" });\n return;\n }\n // Its write (the message itself, or Retry's cleared failure) has not landed: claiming now\n // could find no record yet. It goes once the write settles (which evaluates again).\n if (writePending(entry.id)) {\n phases.set(entry.id, { kind: \"awaiting-thread\" });\n return;\n }\n sendNow.delete(entry.id);\n phases.set(entry.id, { kind: \"claiming\" });\n const claim: Promise<\"claimed\" | \"taken\" | \"gone\"> = store\n ? store.claim({ threadId, id: entry.id, claimant, now: now(), leaseMs: claimLeaseMs })\n : Promise.resolve(\"claimed\");\n void claim.then(\n (result) => {\n if (disposed || phaseOf(entry.id).kind !== \"claiming\") return;\n if (result === \"gone\") {\n // Cancelled, discarded or handed by another window meanwhile.\n dropEntry(entry.id);\n evaluate();\n return;\n }\n if (result === \"taken\") {\n phases.set(entry.id, { kind: \"idle\" });\n claims.set(entry.id, { by: \"elsewhere\", at: now() });\n evaluate();\n return;\n }\n // The claim took a moment to write: look again before anything reaches statewire.\n if (!stillGoes(entry)) return;\n checkThenDispatch(entry, auto);\n },\n () => {\n if (disposed || phaseOf(entry.id).kind !== \"claiming\") return;\n fail(entry.id, \"prepare\");\n evaluate();\n },\n );\n };\n\n /**\n * Whether a claimed hand-off goes on, looked at again once what it waited on landed (its claim,\n * its attachments' check): the conversation may show the message by now, or refuse it; the app\n * may have gone to the background or Athena out of reach (never sent from the background), or\n * the conversation be reattaching, and then the claim goes and the message waits again.\n */\n const stillGoes = (entry: ChatOutboxEntry): boolean => {\n if (thread.heldIds().has(entry.id)) {\n letGo(entry.id, { type: \"adopted\", threadId, messageId: entry.id });\n evaluate();\n return false;\n }\n const ready = thread.readiness();\n if (ready === \"refused\") {\n fail(entry.id, \"refused\");\n evaluate();\n return false;\n }\n if (!gateOpen() || ready !== \"ready\") {\n phases.set(entry.id, gateOpen() ? { kind: \"awaiting-thread\" } : { kind: \"idle\" });\n releaseClaim(entry.id);\n evaluate();\n return false;\n }\n return true;\n };\n\n /**\n * A claimed message's attachments are asked about before it is handed over: the claim holds\n * meanwhile (the row says Sending…, and no other window hands it), bounded by\n * `attachmentCheckTimeoutMs`. Only `ok` hands it over; a refusal, or a check Athena could not\n * answer, keeps it as \"Couldn't send\" until the person retries, edits or discards it.\n */\n const checkThenDispatch = (entry: ChatOutboxEntry, auto: boolean): void => {\n const attachments = entry.attachments ?? [];\n if (attachments.length === 0 || !checkAttachments) {\n readyToGo.set(entry.id, auto);\n releaseReady();\n return;\n }\n let answered = false;\n let stopTimer: () => void = () => undefined;\n const answer = (verdict: ChatOutboxAttachmentVerdict): void => {\n if (answered) return;\n answered = true;\n stopTimer();\n checkTimers.delete(stopTimer);\n if (disposed || phaseOf(entry.id).kind !== \"claiming\") return;\n if (!stillGoes(entry)) return;\n if (verdict === \"ok\") {\n readyToGo.set(entry.id, auto);\n releaseReady();\n return;\n }\n fail(entry.id, verdict === \"refused\" ? \"attachment\" : \"error\");\n evaluate();\n };\n stopTimer = setTimer(() => answer(\"unknown\"), attachmentCheckTimeoutMs);\n checkTimers.add(stopTimer);\n let checking: Promise<ChatOutboxAttachmentVerdict>;\n try {\n checking = checkAttachments(attachments);\n } catch (error) {\n checking = Promise.reject(error);\n }\n void checking.then(answer, () => answer(\"unknown\"));\n };\n\n /**\n * Hands the ready messages over in line: oldest first, and none while an older one is still\n * being claimed or asked about (a check takes a moment, and a later message must not reach the\n * conversation before it). One whose gate closed meanwhile waits again, and one that failed or\n * left lets the line move. Re-entered from `evaluate`, it runs once at a time.\n */\n function releaseReady(): void {\n if (releasing || disposed) return;\n releasing = true;\n try {\n for (const entry of [...entries]) {\n if (phaseOf(entry.id).kind !== \"claiming\") continue;\n const auto = readyToGo.get(entry.id);\n if (auto === undefined) return;\n readyToGo.delete(entry.id);\n if (stillGoes(entry)) dispatch(entry, auto);\n }\n } finally {\n releasing = false;\n }\n }\n\n const dispatch = (entry: ChatOutboxEntry, auto: boolean): void => {\n handedInRegain.set(entry.id, regain);\n phases.set(entry.id, { kind: \"handed\", journaled: false });\n emit({ type: \"handed\", threadId, messageId: entry.id, auto, ageMs: now() - entry.queuedAt });\n let sent: Promise<unknown>;\n try {\n sent = thread.send(entry);\n } catch (error) {\n sent = Promise.reject(error);\n }\n void sent.then(\n () => {\n if (disposed) return;\n letGo(entry.id, { type: \"delivered\", threadId, messageId: entry.id, status: \"accepted\" });\n evaluate();\n },\n (error: unknown) => {\n if (disposed) return;\n const phase = phaseOf(entry.id);\n // Statewire's journal took it: its own record decides what happens next (an exactly-once\n // replay, or its failed lane), and the settle update lets this record go.\n if (phase.kind === \"handed\" && phase.journaled) return;\n if (phase.kind !== \"handed\") return;\n const failure = failureOf(error);\n if (failure.cause !== undefined && AWAY_CAUSES.has(failure.cause)) {\n // The conversation went away before its journal took the message: it waits again.\n phases.set(entry.id, { kind: \"idle\" });\n handedInRegain.delete(entry.id);\n releaseClaim(entry.id);\n evaluate();\n return;\n }\n fail(entry.id, \"error\");\n evaluate();\n },\n );\n };\n\n const startCountdown = (run: readonly ChatOutboxEntry[]): void => {\n stopCountdown();\n const ids = run.map((entry) => entry.id);\n const endsAt = now() + countdownMs;\n const cancel = setTimer(() => {\n if (disposed || countdown?.endsAt !== endsAt) return;\n countdown = null;\n if (!gateOpen()) {\n evaluate();\n return;\n }\n for (const id of ids) {\n const entry = entries.find((candidate) => candidate.id === id);\n if (!entry) continue;\n const phase = phaseOf(id);\n if (phase.kind !== \"idle\" || claimedElsewhere(id)) continue;\n handOff(entry, true);\n }\n evaluate();\n }, countdownMs);\n countdown = { endsAt, ids, cancel };\n emit({ type: \"countdown-started\", threadId, count: ids.length });\n };\n\n const scheduleLeaseCheck = (): void => {\n leaseTimer?.();\n leaseTimer = null;\n let soonest = Number.POSITIVE_INFINITY;\n for (const [id, claim] of claims) {\n if (claim.by === claimant || !entries.some((entry) => entry.id === id)) continue;\n const expires = claim.at + claimLeaseMs - now();\n if (expires > 0) soonest = Math.min(soonest, expires);\n }\n if (Number.isFinite(soonest)) leaseTimer = setTimer(() => evaluate(), soonest + 1);\n };\n\n /** Re-derive everything from the inputs, then let the ready messages go in line. */\n function evaluate(): void {\n evaluateLine();\n releaseReady();\n }\n\n /** What the conversation holds, the gate, the line. */\n function evaluateLine(): void {\n if (disposed) return;\n const reachable = reachability.get();\n if (reachable && !wasReachable) regain += 1;\n wasReachable = reachable;\n\n if (loaded) {\n const held = thread.heldIds();\n for (const entry of [...entries]) {\n const phase = phaseOf(entry.id);\n if (phase.kind === \"handed\") {\n // This window's hand-off: the conversation folding it in means statewire's journal\n // took it; the record goes at `posted` (persisted before the wire) or a settle.\n if (held.has(entry.id)) phases.set(entry.id, { kind: \"handed\", journaled: true });\n continue;\n }\n if (phase.kind === \"claiming\") continue;\n // Not handed by this window, yet the conversation shows it: a journal adopted from an\n // earlier page (read back from storage, so durable), or the message already landed.\n if (held.has(entry.id)) letGo(entry.id, { type: \"adopted\", threadId, messageId: entry.id });\n }\n if (!gateOpen()) {\n // Gone to the background or out of reach before the conversation came back: those whose\n // countdown had ended go back in line, so returning starts the countdown over.\n for (const entry of entries) {\n if (phaseOf(entry.id).kind === \"awaiting-thread\") phases.set(entry.id, { kind: \"idle\" });\n }\n } else if (thread.readiness() !== \"connecting\") {\n // The conversation is back: the messages whose countdown already ended go now.\n for (const entry of entries) {\n if (phaseOf(entry.id).kind === \"awaiting-thread\") {\n phases.set(entry.id, { kind: \"idle\" });\n handOff(entry, true);\n }\n }\n }\n }\n\n if (!loaded || !gateOpen()) {\n stopCountdown();\n publish();\n return;\n }\n\n const line = computeLine();\n if (line.askId !== null && !asked.has(line.askId)) {\n asked.add(line.askId);\n const entry = entries.find((candidate) => candidate.id === line.askId);\n if (entry) emit({ type: \"asked\", threadId, messageId: entry.id, ageMs: now() - entry.queuedAt });\n }\n // Messages the person told to go now leave without a countdown, but never ahead of older\n // ones still in line: those count down first, and these follow them.\n const immediate: ChatOutboxEntry[] = [];\n for (const entry of line.run) {\n if (!sendNow.has(entry.id)) break;\n immediate.push(entry);\n }\n for (const entry of immediate) handOff(entry, false);\n const run = line.run.slice(immediate.length).filter((entry) => !sendNow.has(entry.id));\n if (run.length === 0) {\n stopCountdown();\n } else if (\n countdown === null ||\n countdown.ids.length !== run.length ||\n run.some((entry, index) => countdown?.ids[index] !== entry.id)\n ) {\n // A new countdown for a new line (a message added or cancelled starts it over).\n startCountdown(run);\n }\n scheduleLeaseCheck();\n publish();\n }\n\n const applyRecords = (records: readonly ChatOutboxRecord[], listing: number): void => {\n const mine = records.filter((record) => record.entry.threadId === threadId);\n const stored = new Map(mine.map((record) => [record.entry.id, record]));\n claims = new Map(\n mine.flatMap((record) => (record.claim ? [[record.entry.id, record.claim] as const] : [])),\n );\n for (const record of mine) {\n if (!settledFor(record.entry.id, listing)) continue;\n if (record.memoryOnly) persisted.delete(record.entry.id);\n else persisted.add(record.entry.id);\n // A hand-off that failed (in this window or another, now or before) stays failed until the\n // person retries it; this window's own failure is never cleared by a listing.\n const phase = phaseOf(record.entry.id);\n if (record.failure && phase.kind !== \"failed\" && !isBusy(phase)) {\n phases.set(record.entry.id, { kind: \"failed\", reason: record.failure.reason });\n }\n }\n // Messages the store no longer holds (sent, cancelled or discarded in another window) leave\n // this one too, unless this window is handing them or wrote them after the listing started.\n const kept = entries.filter(\n (entry) =>\n stored.has(entry.id) || !settledFor(entry.id, listing) || isBusy(phaseOf(entry.id)),\n );\n for (const entry of entries) {\n if (kept.includes(entry)) continue;\n if (countdown?.ids.includes(entry.id)) stopCountdown();\n phases.delete(entry.id);\n persisted.delete(entry.id);\n sendNow.delete(entry.id);\n }\n const known = new Set(kept.map((entry) => entry.id));\n const added = mine.filter((record) => !known.has(record.entry.id)).map((record) => record.entry);\n entries = [...kept, ...added].sort((a, b) => a.queuedAt - b.queuedAt);\n // Writes this listing has seen (it started after they settled) need no guard any more.\n for (const [id, settledAt] of unsettled) {\n if (settledAt !== undefined && listing > settledAt) unsettled.delete(id);\n }\n\n const byThread = new Map<string, { count: number; first: ChatOutboxEntry; newChat: boolean }>();\n for (const record of records) {\n if (record.entry.threadId === threadId) continue;\n const current = byThread.get(record.entry.threadId);\n if (current) {\n current.count += 1;\n current.newChat &&= record.entry.newChat;\n } else {\n byThread.set(record.entry.threadId, {\n count: 1,\n first: record.entry,\n newChat: record.entry.newChat,\n });\n }\n }\n elsewhere = [...byThread]\n .map(([otherThreadId, other]) => ({ threadId: otherThreadId, ...other }))\n .sort((a, b) => a.first.queuedAt - b.first.queuedAt);\n };\n\n let reading: Promise<void> | null = null;\n let readAgain = false;\n const reload = (): void => {\n if (!store || disposed) return;\n if (reading) {\n readAgain = true;\n return;\n }\n listingsStarted += 1;\n const listing = listingsStarted;\n reading = store\n .listAll()\n .then(\n (records) => {\n if (disposed) return;\n applyRecords(records, listing);\n loaded = true;\n },\n () => {\n loaded = true;\n },\n )\n .finally(() => {\n reading = null;\n if (disposed) return;\n evaluate();\n if (readAgain) {\n readAgain = false;\n reload();\n }\n });\n };\n\n const unsubscribers = [\n reachability.subscribe(evaluate),\n foreground.subscribe(evaluate),\n thread.subscribe(evaluate),\n ...(store ? [store.subscribe(reload)] : []),\n ];\n reload();\n publish();\n\n return {\n threadId,\n reachability,\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n shouldHold() {\n if (!reachability.get()) return true;\n // Until the conversation's kept messages are read, a new send could overtake one of them.\n if (!loaded) return true;\n // A message statewire's journal already took is ordered ahead of a new send by its seq;\n // one still waiting (or being claimed, or waiting for the conversation) is not.\n return entries.some((entry) => {\n const phase = phaseOf(entry.id);\n return phase.kind !== \"failed\" && !(phase.kind === \"handed\" && phase.journaled);\n });\n },\n hold(input) {\n const entry: ChatOutboxEntry = {\n id: newMessageId(),\n threadId,\n text: input.text,\n queuedAt: now(),\n newChat: typeof isNewChat === \"function\" ? isNewChat() : isNewChat,\n ...(input.composerMarkdown !== undefined && { composerMarkdown: input.composerMarkdown }),\n ...(input.composerHtml !== undefined && { composerHtml: input.composerHtml }),\n ...(input.metadata !== undefined && { metadata: input.metadata }),\n ...(input.files !== undefined && input.files.length > 0 && { files: input.files }),\n ...(input.attachments !== undefined &&\n input.attachments.length > 0 && { attachments: input.attachments }),\n };\n // Sent from in front while Athena answers, held only until the kept messages are read: it\n // goes at once when nothing older is waiting, after them otherwise.\n if (!loaded && gateOpen()) sendNow.add(entry.id);\n entries = [...entries, entry];\n if (store) {\n // Counted as kept from the start: a page closed before the write settles is the same\n // risk a draft has, and the row must not flash \"only while this page is open\".\n persisted.add(entry.id);\n const write = store.put(entry);\n markUnsettled(entry.id, write);\n void write.then(\n (kept) => {\n if (!kept) persisted.delete(entry.id);\n emit({ type: \"held\", threadId, messageId: entry.id, durable: kept });\n publish();\n },\n () => {\n persisted.delete(entry.id);\n emit({ type: \"held\", threadId, messageId: entry.id, durable: false });\n publish();\n },\n );\n } else {\n emit({ type: \"held\", threadId, messageId: entry.id, durable: false });\n }\n evaluate();\n return entry;\n },\n cancel(id) {\n const entry = entries.find((candidate) => candidate.id === id);\n if (!entry || isBusy(phaseOf(id))) return;\n dropEntry(id);\n emit({ type: \"cancelled\", threadId, messageId: id });\n if (store) void store.remove(threadId, id).catch(() => undefined);\n try {\n restore(entry);\n } finally {\n evaluate();\n }\n },\n send(id) {\n const entry = entries.find((candidate) => candidate.id === id);\n if (!entry || isBusy(phaseOf(id))) return;\n const wasFailed = phaseOf(id).kind === \"failed\";\n phases.set(id, { kind: \"idle\" });\n handedInRegain.delete(id);\n sendNow.add(id);\n if (wasFailed && store) {\n const write = store.clearFailure({ threadId, id });\n markUnsettled(id, write);\n void write.catch(() => undefined);\n }\n evaluate();\n },\n discard(id) {\n const entry = entries.find((candidate) => candidate.id === id);\n if (!entry || isBusy(phaseOf(id))) return;\n dropEntry(id);\n emit({ type: \"discarded\", threadId, messageId: id });\n if (store) void store.remove(threadId, id).catch(() => undefined);\n evaluate();\n },\n observeCommand(update) {\n if (disposed) return;\n const id = chatOutboxCommandMessageId(update.params);\n if (id === null) return;\n const phase = phaseOf(id);\n if (phase.kind === \"handed\") {\n if (update.status === \"queued\") {\n phases.set(id, { kind: \"handed\", journaled: true });\n return;\n }\n // Persisted before the wire (`posted`), admitted (`applied`), or settled: statewire owns\n // the message now (its exactly-once replay, or its failed lane).\n letGo(id, { type: \"delivered\", threadId, messageId: id, status: update.status });\n evaluate();\n return;\n }\n // A statement for a waiting message this window did not hand: a journal adopted from an\n // earlier page. The conversation folds it in, and the next evaluation lets the record go.\n if (entries.some((entry) => entry.id === id)) evaluate();\n },\n openThread: openThread ?? null,\n dispose() {\n if (disposed) return;\n disposed = true;\n stopCountdown();\n leaseTimer?.();\n for (const stop of checkTimers) stop();\n checkTimers.clear();\n readyToGo.clear();\n for (const unsubscribe of unsubscribers) unsubscribe();\n listeners.clear();\n // A claim taken for a hand-off that never started is released, so another window (or the\n // next mount) need not wait out the lease. One whose hand-off started stays until its lease\n // ends: statewire may still journal the statement, and the conversation then shows it.\n if (store) {\n for (const [id, phase] of phases) {\n if (phase.kind === \"claiming\") releaseClaim(id);\n }\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,285 @@
1
+ import type { ChatOutboxAttachmentCheck } from "./chat-outbox-attachments";
2
+ import type { ChatOutboxAttachment, ChatOutboxEntry, ChatOutboxFailureReason, ChatOutboxFile, ChatOutboxStore } from "./chat-outbox-store";
3
+ /**
4
+ * The chat outbox: a message typed while Athena can't be reached waits on this device and is sent
5
+ * once Athena answers again, while the app is in front, after a few seconds the person can cancel
6
+ * (decision 5 of the offline plan, `docs/plans/2026-10-27-offline-everywhere-plan.md`).
7
+ *
8
+ * - **Held before the conversation's journal, never inside it.** A send made while Athena can't be
9
+ * reached does not reach statewire at all: statewire would replay it the moment its connection
10
+ * returns (from a hidden tab too) and has no way to take a journaled statement back. The message
11
+ * waits here instead, and reaches statewire only when this controller hands it over, under the
12
+ * id minted when it was typed.
13
+ * - **Sent in front, with a countdown.** Once Athena is reachable and the app is in front (a visible
14
+ * tab, an active app, a focused desktop window), the waiting messages count down
15
+ * ({@link CHAT_OUTBOX_COUNTDOWN_MS}) with a Cancel that gives the text back to the composer; then
16
+ * each is handed over once. Going to the background or losing Athena stops the countdown; it
17
+ * starts over, in full, when both are back.
18
+ * - **A day is the limit for sending on its own.** A message that waited more than
19
+ * {@link CHAT_OUTBOX_ASK_AFTER_MS} asks first (Send / Edit / Discard); the messages behind it wait
20
+ * for the answer, so nothing is sent out of order.
21
+ * - **Once per message, never a loop.** A message is handed over at most once per return of Athena.
22
+ * A hand-off that fails before the conversation took it (anything but the conversation going
23
+ * away) stays as "Couldn't send" with Retry and Discard, kept with the message so no window and
24
+ * no later mount sends it again on its own. Once the conversation's journal took it, statewire
25
+ * owns it: it delivers it exactly once, and a refusal lands in the conversation's own failed
26
+ * lane (Retry / Discard there).
27
+ * - **One sender per message.** A hand-off claims the message in the store first, atomically
28
+ * across windows ({@link CHAT_OUTBOX_CLAIM_LEASE_MS}), so two windows on the same conversation
29
+ * never hand the same message twice (a second hand-off of an id whose run is in flight would be
30
+ * read as an edit of that turn). The gate is checked again once the claim is written: a tab
31
+ * hidden (or an Athena lost) meanwhile lets the claim go, and the message waits again.
32
+ * - **Nothing overtakes.** Until the conversation's kept messages are read, a new send waits too
33
+ * (it goes at once if nothing older turns up), and a message the person told to go now still
34
+ * goes after the older ones in line.
35
+ * - **Kept until it is safe to let go.** The waiting record is removed only once statewire has the
36
+ * statement durably (`posted`, `applied` or settled), or once the conversation shows the message
37
+ * (a journal adopted from an earlier page, or the message already on the transcript).
38
+ * - **Its attachments go with it, still valid.** A message keeps the files that had finished
39
+ * uploading before Athena went out of reach (references to files already in Athena; one picked
40
+ * while it can't be reached is never attached). Once the message is claimed they are asked about
41
+ * ({@link ChatOutboxOptions.checkAttachments}): one Athena refuses (deleted, or no longer shared
42
+ * with the person) keeps the message as "Couldn't send" with Retry, Edit and Discard, and a check
43
+ * Athena could not answer keeps it the same way as a send error. Nothing goes unchecked, and the
44
+ * text is never lost.
45
+ */
46
+ /** How long the countdown before a waiting message is sent lasts. */
47
+ export declare const CHAT_OUTBOX_COUNTDOWN_MS = 5000;
48
+ /** A message that waited longer than this asks before it is sent. */
49
+ export declare const CHAT_OUTBOX_ASK_AFTER_MS: number;
50
+ /** How long a window's claim on a message holds against another window's hand-off. */
51
+ export declare const CHAT_OUTBOX_CLAIM_LEASE_MS = 30000;
52
+ /** How long the check of a message's attachments may take before it counts as unanswered. */
53
+ export declare const CHAT_OUTBOX_ATTACHMENT_CHECK_TIMEOUT_MS = 15000;
54
+ /**
55
+ * Why a sent message's Edit is not offered while Athena can't be reached (its tooltip, or the hint
56
+ * under it where there are no tooltips). An edit rewinds the conversation and re-runs it: a
57
+ * journaled one would replay the moment the connection returns, from a hidden window too, so an
58
+ * edit never waits the way a new message does.
59
+ */
60
+ export declare const CHAT_EDIT_UNREACHABLE_LABEL = "Can't edit while Athena can't be reached";
61
+ /** What an edit submitted while Athena can't be reached says: the edit stays where it was typed. */
62
+ export declare const CHAT_EDIT_KEPT_MESSAGE = "Can't reach Athena right now. Your edit stays here \u2014 submit it once Athena is back.";
63
+ /** An edit submitted while Athena can't be reached: refused, never queued (its message says so). */
64
+ export declare class ChatEditUnreachableError extends Error {
65
+ constructor();
66
+ }
67
+ /** A boolean the host reports and notifies on: Athena's reachability, the app being in front. */
68
+ export interface ChatOutboxSignal {
69
+ get(): boolean;
70
+ subscribe(listener: () => void): () => void;
71
+ }
72
+ /**
73
+ * Whether a hand-off reaches the conversation now: `ready` (attached, a never-started chat that
74
+ * dials on its first send, or an idle channel that reattaches on demand — in each case what the
75
+ * conversation shows is the server's, so a message missing from it never reached it),
76
+ * `connecting` (reattaching: what it shows may be a remembered snapshot), `refused` (the host
77
+ * refused the conversation: stopped, or parked on an authorization denial).
78
+ */
79
+ export type ChatOutboxThreadReadiness = "ready" | "connecting" | "refused";
80
+ /** The conversation the outbox hands messages to (`chat-outbox-thread.ts` adapts a statewire thread). */
81
+ export interface ChatOutboxThreadPort {
82
+ readiness(): ChatOutboxThreadReadiness;
83
+ /**
84
+ * Message ids the conversation shows anywhere: its transcript, its queue and steer lanes, the
85
+ * run being dispatched, its failed lane — this page's journal included (statewire folds a
86
+ * journaled send into them, one adopted from an earlier page too).
87
+ */
88
+ heldIds(): ReadonlySet<string>;
89
+ /** Hand the message to the conversation under its own id; settles with the server's verdict. */
90
+ send(entry: ChatOutboxEntry): Promise<unknown>;
91
+ subscribe(listener: () => void): () => void;
92
+ }
93
+ export type ChatOutboxRowState =
94
+ /** Not sent yet: Athena can't be reached, or the app is not in front. */
95
+ {
96
+ kind: "waiting";
97
+ }
98
+ /** Athena is back: the message is sent when the countdown ends, unless cancelled. */
99
+ | {
100
+ kind: "countdown";
101
+ endsAt: number;
102
+ }
103
+ /** It waited more than a day: Send, Edit or Discard. */
104
+ | {
105
+ kind: "ask";
106
+ }
107
+ /** Being handed to the conversation (by this window or another). */
108
+ | {
109
+ kind: "sending";
110
+ }
111
+ /** The hand-off failed for a reason other than Athena being unreachable. */
112
+ | {
113
+ kind: "failed";
114
+ reason: ChatOutboxFailureReason;
115
+ message: string;
116
+ };
117
+ export interface ChatOutboxRow {
118
+ entry: ChatOutboxEntry;
119
+ state: ChatOutboxRowState;
120
+ }
121
+ /** Another conversation of the same person with messages waiting (the tray offers to open it). */
122
+ export interface ChatOutboxElsewhere {
123
+ threadId: string;
124
+ /** How many messages wait there. */
125
+ count: number;
126
+ /** The oldest of them: its text names the conversation. */
127
+ first: ChatOutboxEntry;
128
+ /**
129
+ * Every message waiting there was typed into a chat that had never started, so it opens as the
130
+ * new chat it still is (one typed after the chat started says it has a session now).
131
+ */
132
+ newChat: boolean;
133
+ }
134
+ export interface ChatOutboxSnapshot {
135
+ rows: readonly ChatOutboxRow[];
136
+ /** When the running countdown ends (epoch ms), or `null`. */
137
+ countdownEndsAt: number | null;
138
+ /** Whether every waiting message is kept on this device (false: only while the page stays open). */
139
+ durable: boolean;
140
+ /** Whether the thread's kept messages have been read. */
141
+ loaded: boolean;
142
+ /** The person's other conversations with messages waiting, oldest first. */
143
+ elsewhere: readonly ChatOutboxElsewhere[];
144
+ }
145
+ /** What a failed row says. */
146
+ export declare function chatOutboxFailureMessage(reason: ChatOutboxFailureReason): string;
147
+ export interface ChatOutboxInput {
148
+ text: string;
149
+ composerMarkdown?: string;
150
+ /** The draft as an HTML composer holds it (the phone's), given back exactly on Cancel. */
151
+ composerHtml?: string;
152
+ metadata?: Record<string, unknown>;
153
+ files?: ChatOutboxFile[];
154
+ /** Files already in Athena the message carries, asked about before it goes. */
155
+ attachments?: ChatOutboxAttachment[];
156
+ }
157
+ export type ChatOutboxEvent = {
158
+ type: "held";
159
+ threadId: string;
160
+ messageId: string;
161
+ durable: boolean;
162
+ } | {
163
+ type: "countdown-started";
164
+ threadId: string;
165
+ count: number;
166
+ } | {
167
+ type: "asked";
168
+ threadId: string;
169
+ messageId: string;
170
+ ageMs: number;
171
+ } | {
172
+ type: "handed";
173
+ threadId: string;
174
+ messageId: string;
175
+ auto: boolean;
176
+ ageMs: number;
177
+ } | {
178
+ type: "delivered";
179
+ threadId: string;
180
+ messageId: string;
181
+ status: string;
182
+ } | {
183
+ type: "adopted";
184
+ threadId: string;
185
+ messageId: string;
186
+ } | {
187
+ type: "failed";
188
+ threadId: string;
189
+ messageId: string;
190
+ message: string;
191
+ reason: ChatOutboxFailureReason;
192
+ } | {
193
+ type: "cancelled";
194
+ threadId: string;
195
+ messageId: string;
196
+ } | {
197
+ type: "discarded";
198
+ threadId: string;
199
+ messageId: string;
200
+ };
201
+ /** The command-lifecycle update statewire reports (`onCommandChange`), structurally. */
202
+ export interface ChatOutboxCommandUpdate {
203
+ status: "queued" | "posted" | "applied" | "settled";
204
+ params?: readonly unknown[];
205
+ failure?: {
206
+ fate: string;
207
+ cause?: string;
208
+ } | undefined;
209
+ }
210
+ export interface ChatOutbox {
211
+ readonly threadId: string;
212
+ getSnapshot(): ChatOutboxSnapshot;
213
+ subscribe(listener: () => void): () => void;
214
+ /**
215
+ * Whether Athena can be reached, as this outbox reads it (the host's model; in the SDK the
216
+ * conversation's own channel too). An edit of a sent message waits on it as a send does: while it
217
+ * says no, the Edit action is not offered and a submitted edit is refused
218
+ * ({@link CHAT_EDIT_UNREACHABLE_LABEL}, {@link ChatEditUnreachableError}).
219
+ */
220
+ readonly reachability: ChatOutboxSignal;
221
+ /**
222
+ * Whether a send made now must wait here: Athena can't be reached, or earlier messages of this
223
+ * conversation are still waiting (a later message never overtakes them).
224
+ */
225
+ shouldHold(): boolean;
226
+ /** Keep a message typed now; it waits until it can be sent. */
227
+ hold(input: ChatOutboxInput): ChatOutboxEntry;
228
+ /** Cancel (or the ask's Edit): the message leaves the outbox and its text goes back to the composer. */
229
+ cancel(id: string): void;
230
+ /** The ask's Send, a failed row's Retry: hand it over now (one attempt; waits if Athena is out of reach). */
231
+ send(id: string): void;
232
+ discard(id: string): void;
233
+ /** Feed statewire's command lifecycle (`onCommandChange`). */
234
+ observeCommand(update: ChatOutboxCommandUpdate): void;
235
+ /** Open another conversation the tray lists as holding waiting messages (`null`: the host cannot). */
236
+ readonly openThread: ((target: {
237
+ threadId: string;
238
+ newChat: boolean;
239
+ }) => void) | null;
240
+ dispose(): void;
241
+ }
242
+ export interface ChatOutboxOptions {
243
+ threadId: string;
244
+ /**
245
+ * The conversation has never started (a new chat): what waits reopens with it. Read when a
246
+ * message is held, so a chat that started since stamps its later messages as started.
247
+ */
248
+ isNewChat: boolean | (() => boolean);
249
+ /** Where waiting messages are kept for this person; `null` keeps them in memory only. */
250
+ store: ChatOutboxStore | null;
251
+ reachability: ChatOutboxSignal;
252
+ foreground: ChatOutboxSignal;
253
+ thread: ChatOutboxThreadPort;
254
+ /** Give a cancelled message's text back to the composer. */
255
+ restore: (entry: ChatOutboxEntry) => void;
256
+ /**
257
+ * Open another of the person's conversations that holds waiting messages (the tray's Open);
258
+ * omitted where the host cannot switch conversations (an embedded chat).
259
+ */
260
+ openThread?: (target: {
261
+ threadId: string;
262
+ newChat: boolean;
263
+ }) => void;
264
+ onEvent?: (event: ChatOutboxEvent) => void;
265
+ /**
266
+ * Asks Athena whether a waiting message's attachments can still be opened, right before it goes
267
+ * (`createChatOutboxAttachmentCheck`). `refused` keeps the message as "Couldn't send" (Retry,
268
+ * Edit, Discard); `unknown` too, as a send error. Omitted: attachments go unchecked.
269
+ */
270
+ checkAttachments?: ChatOutboxAttachmentCheck;
271
+ now?: () => number;
272
+ countdownMs?: number;
273
+ askAfterMs?: number;
274
+ claimLeaseMs?: number;
275
+ /** How long the attachment check may take before it counts as unanswered. */
276
+ attachmentCheckTimeoutMs?: number;
277
+ newMessageId?: () => string;
278
+ /** Timer seam (tests): schedule `task` after `ms`, returning what cancels it. */
279
+ setTimer?: (task: () => void, ms: number) => () => void;
280
+ }
281
+ /** The message id a run send carries, off a command update's params. */
282
+ export declare function chatOutboxCommandMessageId(params: readonly unknown[] | undefined): string | null;
283
+ /** Whether two snapshots show the same thing (the rows' entries by identity: a listing keeps them). */
284
+ export declare function sameChatOutboxSnapshot(a: ChatOutboxSnapshot, b: ChatOutboxSnapshot): boolean;
285
+ export declare function createChatOutbox(options: ChatOutboxOptions): ChatOutbox;