@athenaintel/react 0.42.2 → 0.48.0

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 (685) hide show
  1. package/README.md +225 -3
  2. package/dist/agent-runtime/src/answer-label.cjs +137 -0
  3. package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
  4. package/dist/agent-runtime/src/answer-label.d.ts +104 -0
  5. package/dist/agent-runtime/src/answer-label.js +137 -0
  6. package/dist/agent-runtime/src/answer-label.js.map +1 -0
  7. package/dist/agent-runtime/src/answer-rows.cjs +180 -0
  8. package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
  9. package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
  10. package/dist/agent-runtime/src/answer-rows.js +180 -0
  11. package/dist/agent-runtime/src/answer-rows.js.map +1 -0
  12. package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
  13. package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  14. package/dist/agent-runtime/src/conversation-index.cjs +8 -8
  15. package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
  16. package/dist/agent-runtime/src/conversation-list-groups.d.ts +74 -0
  17. package/dist/agent-runtime/src/decision-checks.cjs +207 -0
  18. package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
  19. package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
  20. package/dist/agent-runtime/src/decision-checks.js +207 -0
  21. package/dist/agent-runtime/src/decision-checks.js.map +1 -0
  22. package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
  23. package/dist/agent-runtime/src/errors.cjs +18 -0
  24. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  25. package/dist/agent-runtime/src/errors.d.ts +7 -0
  26. package/dist/agent-runtime/src/errors.js +18 -0
  27. package/dist/agent-runtime/src/errors.js.map +1 -1
  28. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
  29. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  30. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
  31. package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
  32. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  33. package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
  34. package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
  35. package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
  36. package/dist/agent-runtime/src/handoff-arrival.js +60 -0
  37. package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
  38. package/dist/agent-runtime/src/index.d.ts +15 -8
  39. package/dist/agent-runtime/src/interrupts.cjs +43 -18
  40. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  41. package/dist/agent-runtime/src/interrupts.d.ts +19 -2
  42. package/dist/agent-runtime/src/interrupts.js +28 -3
  43. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  44. package/dist/agent-runtime/src/lane-history.cjs +8 -8
  45. package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
  46. package/dist/agent-runtime/src/messages.cjs +43 -8
  47. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  48. package/dist/agent-runtime/src/messages.d.ts +25 -3
  49. package/dist/agent-runtime/src/messages.js +43 -8
  50. package/dist/agent-runtime/src/messages.js.map +1 -1
  51. package/dist/agent-runtime/src/offline-status.cjs +36 -0
  52. package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
  53. package/dist/agent-runtime/src/offline-status.d.ts +118 -3
  54. package/dist/agent-runtime/src/offline-status.js +36 -0
  55. package/dist/agent-runtime/src/offline-status.js.map +1 -0
  56. package/dist/agent-runtime/src/queue.cjs +0 -9
  57. package/dist/agent-runtime/src/queue.cjs.map +1 -1
  58. package/dist/agent-runtime/src/queue.js +0 -9
  59. package/dist/agent-runtime/src/queue.js.map +1 -1
  60. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
  61. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  62. package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
  63. package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
  64. package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
  65. package/dist/agent-runtime/src/runtime-catalog.js +42 -0
  66. package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
  67. package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
  68. package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
  69. package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
  70. package/dist/agent-runtime/src/runtime.d.ts +40 -0
  71. package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
  72. package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  73. package/dist/agent-runtime/src/subagents.cjs +32 -2
  74. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  75. package/dist/agent-runtime/src/subagents.d.ts +9 -0
  76. package/dist/agent-runtime/src/subagents.js +30 -0
  77. package/dist/agent-runtime/src/subagents.js.map +1 -1
  78. package/dist/agent-runtime/src/thread-driver.cjs +67 -0
  79. package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
  80. package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
  81. package/dist/agent-runtime/src/thread-driver.js +67 -0
  82. package/dist/agent-runtime/src/thread-driver.js.map +1 -0
  83. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
  84. package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +756 -0
  85. package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
  86. package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
  87. package/dist/agent-runtime/src/thread-status.cjs +3 -3
  88. package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
  89. package/dist/agent-runtime/src/tool-metadata.cjs +210 -33
  90. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  91. package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
  92. package/dist/agent-runtime/src/tool-metadata.js +210 -33
  93. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  94. package/dist/agent-runtime/src/tool-names.cjs +2 -0
  95. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  96. package/dist/agent-runtime/src/tool-names.d.ts +2 -0
  97. package/dist/agent-runtime/src/tool-names.js +2 -0
  98. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  99. package/dist/agent-runtime/src/types.d.ts +10 -2
  100. package/dist/agent-runtime/src/use-conversation-list.cjs +11 -11
  101. package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
  102. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +24 -19
  103. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
  104. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +2 -1
  105. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +6 -1
  106. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
  107. package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
  108. package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
  109. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
  110. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  111. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +16 -16
  112. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  113. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
  114. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  115. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +572 -134
  116. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
  117. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +137 -10
  118. package/dist/agent-runtime/src/use-deep-agent-voice.js +514 -76
  119. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
  120. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
  121. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  122. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
  123. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
  124. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +28 -26
  125. package/dist/agent-runtime/src/voice-media.cjs +117 -0
  126. package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
  127. package/dist/agent-runtime/src/voice-media.d.ts +49 -0
  128. package/dist/agent-runtime/src/voice-media.js +117 -0
  129. package/dist/agent-runtime/src/voice-media.js.map +1 -0
  130. package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
  131. package/dist/assets/AssetPanel.cjs +11 -11
  132. package/dist/assets/AssetPanel.cjs.map +1 -1
  133. package/dist/assets/AthenaAssetEmbed.cjs +11 -9
  134. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  135. package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
  136. package/dist/assets/AthenaAssetEmbed.js +4 -2
  137. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  138. package/dist/assets/AthenaLayout.cjs +16 -16
  139. package/dist/assets/AthenaLayout.cjs.map +1 -1
  140. package/dist/assets/use-asset-content.cjs +4 -4
  141. package/dist/assets/use-asset-content.cjs.map +1 -1
  142. package/dist/assets/use-asset-embed.cjs +14 -7
  143. package/dist/assets/use-asset-embed.cjs.map +1 -1
  144. package/dist/assets/use-asset-embed.d.ts +11 -1
  145. package/dist/assets/use-asset-embed.js +10 -3
  146. package/dist/assets/use-asset-embed.js.map +1 -1
  147. package/dist/auth/AthenaAuthContext.cjs +3 -3
  148. package/dist/auth/AthenaAuthContext.cjs.map +1 -1
  149. package/dist/auth/AthenaAuthProvider.cjs +8 -8
  150. package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
  151. package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
  152. package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
  153. package/dist/auth/AthenaSSOProvider.cjs +14 -14
  154. package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
  155. package/dist/auth/credential-source.cjs +26 -13
  156. package/dist/auth/credential-source.cjs.map +1 -1
  157. package/dist/auth/credential-source.d.ts +8 -0
  158. package/dist/auth/credential-source.js +26 -13
  159. package/dist/auth/credential-source.js.map +1 -1
  160. package/dist/catalog/agent-model-options.cjs +25 -17
  161. package/dist/catalog/agent-model-options.cjs.map +1 -1
  162. package/dist/catalog/agent-model-options.d.ts +38 -5
  163. package/dist/catalog/agent-model-options.js +25 -17
  164. package/dist/catalog/agent-model-options.js.map +1 -1
  165. package/dist/catalog/channel-refusal.cjs +36 -0
  166. package/dist/catalog/channel-refusal.cjs.map +1 -0
  167. package/dist/catalog/channel-refusal.d.ts +29 -0
  168. package/dist/catalog/channel-refusal.js +36 -0
  169. package/dist/catalog/channel-refusal.js.map +1 -0
  170. package/dist/catalog/chat-pickers.cjs +60 -24
  171. package/dist/catalog/chat-pickers.cjs.map +1 -1
  172. package/dist/catalog/chat-pickers.d.ts +12 -2
  173. package/dist/catalog/chat-pickers.js +56 -20
  174. package/dist/catalog/chat-pickers.js.map +1 -1
  175. package/dist/catalog/runtime-catalog.cjs +89 -23
  176. package/dist/catalog/runtime-catalog.cjs.map +1 -1
  177. package/dist/catalog/runtime-catalog.d.ts +8 -2
  178. package/dist/catalog/runtime-catalog.js +83 -17
  179. package/dist/catalog/runtime-catalog.js.map +1 -1
  180. package/dist/catalog/use-athena-chat-mode.cjs +12 -12
  181. package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
  182. package/dist/chat/AthenaChat.cjs +155 -67
  183. package/dist/chat/AthenaChat.cjs.map +1 -1
  184. package/dist/chat/AthenaChat.d.ts +42 -2
  185. package/dist/chat/AthenaChat.js +106 -18
  186. package/dist/chat/AthenaChat.js.map +1 -1
  187. package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
  188. package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
  189. package/dist/chat/DrivingOnChip.cjs +23 -0
  190. package/dist/chat/DrivingOnChip.cjs.map +1 -0
  191. package/dist/chat/DrivingOnChip.d.ts +17 -0
  192. package/dist/chat/DrivingOnChip.js +23 -0
  193. package/dist/chat/DrivingOnChip.js.map +1 -0
  194. package/dist/chat/StatewireApprovalCard.cjs +125 -31
  195. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  196. package/dist/chat/StatewireApprovalCard.d.ts +73 -1
  197. package/dist/chat/StatewireApprovalCard.js +115 -21
  198. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  199. package/dist/chat/StatewireClientToolBridge.cjs +2 -2
  200. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  201. package/dist/chat/StatewireQueuedMessages.cjs +25 -63
  202. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  203. package/dist/chat/StatewireQueuedMessages.d.ts +11 -13
  204. package/dist/chat/StatewireQueuedMessages.js +16 -54
  205. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  206. package/dist/chat/WaitingOnYouBanner.cjs +3 -3
  207. package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
  208. package/dist/chat/athena-chat-welcome.cjs +2 -2
  209. package/dist/chat/athena-chat-welcome.cjs.map +1 -1
  210. package/dist/chat/athena-citation-links.cjs +5 -5
  211. package/dist/chat/athena-citation-links.cjs.map +1 -1
  212. package/dist/chat/athena-composer-controls.cjs +26 -16
  213. package/dist/chat/athena-composer-controls.cjs.map +1 -1
  214. package/dist/chat/athena-composer-controls.d.ts +6 -0
  215. package/dist/chat/athena-composer-controls.js +26 -16
  216. package/dist/chat/athena-composer-controls.js.map +1 -1
  217. package/dist/chat/athena-turn-end-status.cjs +42 -0
  218. package/dist/chat/athena-turn-end-status.cjs.map +1 -0
  219. package/dist/chat/athena-turn-end-status.d.ts +24 -0
  220. package/dist/chat/athena-turn-end-status.js +42 -0
  221. package/dist/chat/athena-turn-end-status.js.map +1 -0
  222. package/dist/chat/browser-decision-check.cjs +131 -0
  223. package/dist/chat/browser-decision-check.cjs.map +1 -0
  224. package/dist/chat/browser-decision-check.d.ts +61 -0
  225. package/dist/chat/browser-decision-check.js +131 -0
  226. package/dist/chat/browser-decision-check.js.map +1 -0
  227. package/dist/chat/chat-outbox-rows.cjs +3 -3
  228. package/dist/chat/chat-outbox-rows.cjs.map +1 -1
  229. package/dist/chat/chat-voice-controls.cjs +93 -28
  230. package/dist/chat/chat-voice-controls.cjs.map +1 -1
  231. package/dist/chat/chat-voice-controls.d.ts +36 -2
  232. package/dist/chat/chat-voice-controls.js +89 -24
  233. package/dist/chat/chat-voice-controls.js.map +1 -1
  234. package/dist/chat/composer-keyboard-hint.cjs +5 -5
  235. package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
  236. package/dist/chat/device-operation.cjs +29 -0
  237. package/dist/chat/device-operation.cjs.map +1 -0
  238. package/dist/chat/device-operation.d.ts +34 -0
  239. package/dist/chat/device-operation.js +29 -0
  240. package/dist/chat/device-operation.js.map +1 -0
  241. package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
  242. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  243. package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
  244. package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
  245. package/dist/chat/super-grouping/SuperGroupingCard.cjs +60 -38
  246. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  247. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +24 -4
  248. package/dist/chat/super-grouping/SuperGroupingCard.js +37 -15
  249. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  250. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
  251. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  252. package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
  253. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  254. package/dist/chat/super-grouping/ToolTimeline.cjs +97 -37
  255. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
  256. package/dist/chat/super-grouping/ToolTimeline.d.ts +14 -2
  257. package/dist/chat/super-grouping/ToolTimeline.js +94 -34
  258. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
  259. package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
  260. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  261. package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
  262. package/dist/chat/super-grouping/activity-timeline.js +47 -12
  263. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  264. package/dist/chat/super-grouping/grouping-function.cjs +4 -0
  265. package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
  266. package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
  267. package/dist/chat/super-grouping/grouping-function.js +5 -1
  268. package/dist/chat/super-grouping/grouping-function.js.map +1 -1
  269. package/dist/chat/super-grouping/index.cjs +6 -0
  270. package/dist/chat/super-grouping/index.cjs.map +1 -1
  271. package/dist/chat/super-grouping/index.d.ts +6 -2
  272. package/dist/chat/super-grouping/index.js +7 -1
  273. package/dist/chat/super-grouping/index.js.map +1 -1
  274. package/dist/chat/super-grouping/timeline-step.cjs +61 -2
  275. package/dist/chat/super-grouping/timeline-step.cjs.map +1 -1
  276. package/dist/chat/super-grouping/timeline-step.d.ts +13 -1
  277. package/dist/chat/super-grouping/timeline-step.js +61 -2
  278. package/dist/chat/super-grouping/timeline-step.js.map +1 -1
  279. package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
  280. package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
  281. package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
  282. package/dist/chat/super-grouping/tool-part-placement.js +17 -0
  283. package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
  284. package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
  285. package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
  286. package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
  287. package/dist/chat/thread-scroll-to-bottom.js +2 -2
  288. package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
  289. package/dist/chat/tooltip-icon-button.cjs +2 -2
  290. package/dist/chat/tooltip-icon-button.cjs.map +1 -1
  291. package/dist/chat/use-athena-voice-live.cjs +11 -0
  292. package/dist/chat/use-athena-voice-live.cjs.map +1 -0
  293. package/dist/chat/use-athena-voice-live.d.ts +11 -0
  294. package/dist/chat/use-athena-voice-live.js +11 -0
  295. package/dist/chat/use-athena-voice-live.js.map +1 -0
  296. package/dist/chat/use-statewire-approval-request.cjs +56 -24
  297. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  298. package/dist/chat/use-statewire-approval-request.d.ts +33 -4
  299. package/dist/chat/use-statewire-approval-request.js +41 -9
  300. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  301. package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
  302. package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
  303. package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
  304. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  305. package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
  306. package/dist/chat-ui/composer/tiptap-composer.js +85 -54
  307. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  308. package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
  309. package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
  310. package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
  311. package/dist/chat-ui/header/conversation-history-panel.js +38 -12
  312. package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
  313. package/dist/chat-ui/index.cjs +18 -0
  314. package/dist/chat-ui/index.cjs.map +1 -1
  315. package/dist/chat-ui/index.d.ts +7 -1
  316. package/dist/chat-ui/index.js +18 -0
  317. package/dist/chat-ui/index.js.map +1 -1
  318. package/dist/chat-ui/mentions/mention-chip.cjs +147 -38
  319. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  320. package/dist/chat-ui/mentions/mention-chip.d.ts +17 -1
  321. package/dist/chat-ui/mentions/mention-chip.js +146 -37
  322. package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
  323. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
  324. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
  325. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
  326. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
  327. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
  328. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
  329. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
  330. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
  331. package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
  332. package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
  333. package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
  334. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
  335. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
  336. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
  337. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
  338. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
  339. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  340. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
  341. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
  342. package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
  343. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
  344. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
  345. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
  346. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  347. package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
  348. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
  349. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  350. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
  351. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
  352. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
  353. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
  354. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
  355. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
  356. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
  357. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
  358. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
  359. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
  360. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
  361. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
  362. package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
  363. package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
  364. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
  365. package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
  366. package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
  367. package/dist/chat-ui/mentions/use-mention-asset.cjs +140 -0
  368. package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -0
  369. package/dist/chat-ui/mentions/use-mention-asset.d.ts +16 -0
  370. package/dist/chat-ui/mentions/use-mention-asset.js +140 -0
  371. package/dist/chat-ui/mentions/use-mention-asset.js.map +1 -0
  372. package/dist/chat-ui/messages/answer-label.cjs +42 -0
  373. package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
  374. package/dist/chat-ui/messages/answer-label.d.ts +33 -0
  375. package/dist/chat-ui/messages/answer-label.js +42 -0
  376. package/dist/chat-ui/messages/answer-label.js.map +1 -0
  377. package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
  378. package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
  379. package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
  380. package/dist/chat-ui/messages/arrival-animation.js +13 -0
  381. package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
  382. package/dist/chat-ui/messages/continue-pill.cjs +5 -5
  383. package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
  384. package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
  385. package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
  386. package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
  387. package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
  388. package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
  389. package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
  390. package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
  391. package/dist/chat-ui/messages/message-components.cjs +8 -4
  392. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  393. package/dist/chat-ui/messages/message-components.js +5 -1
  394. package/dist/chat-ui/messages/message-components.js.map +1 -1
  395. package/dist/chat-ui/messages/message-images.cjs +66 -0
  396. package/dist/chat-ui/messages/message-images.cjs.map +1 -0
  397. package/dist/chat-ui/messages/message-images.d.ts +16 -0
  398. package/dist/chat-ui/messages/message-images.js +66 -0
  399. package/dist/chat-ui/messages/message-images.js.map +1 -0
  400. package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
  401. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  402. package/dist/chat-ui/messages/wake-marker.cjs +3 -3
  403. package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
  404. package/dist/chat-ui/rich-text/chat-link.cjs +7 -6
  405. package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
  406. package/dist/chat-ui/rich-text/chat-link.d.ts +2 -3
  407. package/dist/chat-ui/rich-text/chat-link.js +6 -5
  408. package/dist/chat-ui/rich-text/chat-link.js.map +1 -1
  409. package/dist/chat-ui/rich-text/chat-message-body.cjs +8 -8
  410. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
  411. package/dist/chat-ui/rich-text/chat-node-views.cjs +7 -6
  412. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
  413. package/dist/chat-ui/rich-text/chat-node-views.js +1 -0
  414. package/dist/chat-ui/rich-text/chat-node-views.js.map +1 -1
  415. package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
  416. package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
  417. package/dist/chat-ui/statewire.cjs +3 -0
  418. package/dist/chat-ui/statewire.cjs.map +1 -1
  419. package/dist/chat-ui/statewire.d.ts +2 -1
  420. package/dist/chat-ui/statewire.js +3 -0
  421. package/dist/chat-ui/statewire.js.map +1 -1
  422. package/dist/chat-ui/thread/chat-thread-shell.cjs +43 -14
  423. package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
  424. package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
  425. package/dist/chat-ui/thread/chat-thread-shell.js +35 -6
  426. package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
  427. package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
  428. package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
  429. package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
  430. package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
  431. package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
  432. package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
  433. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  434. package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
  435. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  436. package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
  437. package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
  438. package/dist/collab/client.cjs +40 -3
  439. package/dist/collab/client.cjs.map +1 -1
  440. package/dist/collab/client.d.ts +25 -0
  441. package/dist/collab/client.js +40 -3
  442. package/dist/collab/client.js.map +1 -1
  443. package/dist/collab/document-status.cjs +150 -0
  444. package/dist/collab/document-status.cjs.map +1 -0
  445. package/dist/collab/document-status.d.ts +68 -0
  446. package/dist/collab/document-status.js +150 -0
  447. package/dist/collab/document-status.js.map +1 -0
  448. package/dist/collab/index.cjs +7 -0
  449. package/dist/collab/index.cjs.map +1 -1
  450. package/dist/collab/index.d.ts +6 -1
  451. package/dist/collab/index.js +7 -0
  452. package/dist/collab/index.js.map +1 -1
  453. package/dist/collab/presence-react.cjs +11 -11
  454. package/dist/collab/presence-react.cjs.map +1 -1
  455. package/dist/collab/react.cjs +6 -6
  456. package/dist/collab/react.cjs.map +1 -1
  457. package/dist/composer/AttachmentContext.cjs +24 -11
  458. package/dist/composer/AttachmentContext.cjs.map +1 -1
  459. package/dist/composer/AttachmentContext.js +18 -5
  460. package/dist/composer/AttachmentContext.js.map +1 -1
  461. package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
  462. package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
  463. package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
  464. package/dist/composer/ComposerAttachmentPreview.js +79 -24
  465. package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
  466. package/dist/composer/ComposerDropZone.cjs +7 -7
  467. package/dist/composer/ComposerDropZone.cjs.map +1 -1
  468. package/dist/composer/FileUploadButton.cjs +37 -22
  469. package/dist/composer/FileUploadButton.cjs.map +1 -1
  470. package/dist/composer/FileUploadButton.d.ts +6 -0
  471. package/dist/composer/FileUploadButton.js +34 -19
  472. package/dist/composer/FileUploadButton.js.map +1 -1
  473. package/dist/composer/QuoteContext.cjs +8 -8
  474. package/dist/composer/QuoteContext.cjs.map +1 -1
  475. package/dist/composer/composer-handoff.cjs +4 -4
  476. package/dist/composer/composer-handoff.cjs.map +1 -1
  477. package/dist/composer/useAppendToComposer.cjs +4 -4
  478. package/dist/composer/useAppendToComposer.cjs.map +1 -1
  479. package/dist/composer/useAttachFiles.cjs +23 -6
  480. package/dist/composer/useAttachFiles.cjs.map +1 -1
  481. package/dist/composer/useAttachFiles.d.ts +15 -7
  482. package/dist/composer/useAttachFiles.js +22 -5
  483. package/dist/composer/useAttachFiles.js.map +1 -1
  484. package/dist/composer/useComposerAttachment.cjs +4 -4
  485. package/dist/composer/useComposerAttachment.cjs.map +1 -1
  486. package/dist/composer/useFileUpload.cjs +21 -16
  487. package/dist/composer/useFileUpload.cjs.map +1 -1
  488. package/dist/composer/useFileUpload.d.ts +12 -0
  489. package/dist/composer/useFileUpload.js +12 -7
  490. package/dist/composer/useFileUpload.js.map +1 -1
  491. package/dist/composer/useReadComposerDraft.cjs +2 -2
  492. package/dist/composer/useReadComposerDraft.cjs.map +1 -1
  493. package/dist/composer/useSendMessage.cjs +4 -4
  494. package/dist/composer/useSendMessage.cjs.map +1 -1
  495. package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
  496. package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
  497. package/dist/dictation/audio-level-history.cjs +3 -3
  498. package/dist/dictation/audio-level-history.cjs.map +1 -1
  499. package/dist/dictation/dictation-controls.cjs +24 -20
  500. package/dist/dictation/dictation-controls.cjs.map +1 -1
  501. package/dist/dictation/dictation-controls.d.ts +6 -1
  502. package/dist/dictation/dictation-controls.js +24 -20
  503. package/dist/dictation/dictation-controls.js.map +1 -1
  504. package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
  505. package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
  506. package/dist/dictation/use-dictation.cjs +22 -22
  507. package/dist/dictation/use-dictation.cjs.map +1 -1
  508. package/dist/index.cjs +26 -2
  509. package/dist/index.cjs.map +1 -1
  510. package/dist/index.d.ts +15 -3
  511. package/dist/index.js +26 -2
  512. package/dist/index.js.map +1 -1
  513. package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
  514. package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
  515. package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
  516. package/dist/keryx-http/src/receive-only-socket.js +40 -0
  517. package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
  518. package/dist/keryx-http/src/update-attributions.cjs +111 -0
  519. package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
  520. package/dist/keryx-http/src/update-attributions.d.ts +75 -0
  521. package/dist/keryx-http/src/update-attributions.js +111 -0
  522. package/dist/keryx-http/src/update-attributions.js.map +1 -0
  523. package/dist/lib/owner-document.cjs +6 -6
  524. package/dist/lib/owner-document.cjs.map +1 -1
  525. package/dist/lib/use-athena-rest-query.cjs +4 -4
  526. package/dist/lib/use-athena-rest-query.cjs.map +1 -1
  527. package/dist/lib/use-document-active.cjs +4 -4
  528. package/dist/lib/use-document-active.cjs.map +1 -1
  529. package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
  530. package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
  531. package/dist/offline/offline-history.cjs +7 -7
  532. package/dist/offline/offline-history.cjs.map +1 -1
  533. package/dist/provider/AthenaContext.cjs +3 -3
  534. package/dist/provider/AthenaContext.cjs.map +1 -1
  535. package/dist/provider/AthenaProvider.cjs +116 -79
  536. package/dist/provider/AthenaProvider.cjs.map +1 -1
  537. package/dist/provider/AthenaProvider.js +40 -3
  538. package/dist/provider/AthenaProvider.js.map +1 -1
  539. package/dist/provider/PostHogProvider.cjs +2 -2
  540. package/dist/provider/PostHogProvider.cjs.map +1 -1
  541. package/dist/provider/agent-selection-context.cjs +2 -2
  542. package/dist/provider/agent-selection-context.cjs.map +1 -1
  543. package/dist/provider/chat-mode-context.cjs +2 -2
  544. package/dist/provider/chat-mode-context.cjs.map +1 -1
  545. package/dist/provider/session-persistence-context.cjs +10 -0
  546. package/dist/provider/session-persistence-context.cjs.map +1 -0
  547. package/dist/provider/session-persistence-context.d.ts +15 -0
  548. package/dist/provider/session-persistence-context.js +10 -0
  549. package/dist/provider/session-persistence-context.js.map +1 -0
  550. package/dist/provider/statewire-history-context.cjs +4 -4
  551. package/dist/provider/statewire-history-context.cjs.map +1 -1
  552. package/dist/provider/statewire-lifecycle-context.cjs +3 -3
  553. package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
  554. package/dist/provider/statewire-window-context.cjs +3 -3
  555. package/dist/provider/statewire-window-context.cjs.map +1 -1
  556. package/dist/provider/theme-style-context.cjs +3 -3
  557. package/dist/provider/theme-style-context.cjs.map +1 -1
  558. package/dist/react/package.json.cjs +1 -1
  559. package/dist/react/package.json.js +1 -1
  560. package/dist/references/src/tool-option-schemas.d.ts +0 -34
  561. package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
  562. package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
  563. package/dist/runtime/auth-refusal-restart.cjs +7 -7
  564. package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
  565. package/dist/runtime/auth.cjs +13 -13
  566. package/dist/runtime/auth.cjs.map +1 -1
  567. package/dist/runtime/statewire-lifecycle.cjs +1 -0
  568. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  569. package/dist/runtime/statewire-lifecycle.d.ts +3 -1
  570. package/dist/runtime/statewire-lifecycle.js +2 -1
  571. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  572. package/dist/runtime/statewire-server-lane-context.cjs +2 -2
  573. package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
  574. package/dist/runtime/statewire-session-lane.cjs +4 -4
  575. package/dist/runtime/statewire-session-lane.cjs.map +1 -1
  576. package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
  577. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  578. package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
  579. package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
  580. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  581. package/dist/styles.css +1 -1
  582. package/dist/threads/Inbox.cjs +8 -8
  583. package/dist/threads/Inbox.cjs.map +1 -1
  584. package/dist/threads/SessionList.cjs +9 -9
  585. package/dist/threads/SessionList.cjs.map +1 -1
  586. package/dist/threads/SessionsPage.cjs +11 -11
  587. package/dist/threads/SessionsPage.cjs.map +1 -1
  588. package/dist/threads/index-triggered-refresh.cjs +10 -10
  589. package/dist/threads/index-triggered-refresh.cjs.map +1 -1
  590. package/dist/threads/mark-viewed-thread-read.cjs +12 -12
  591. package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
  592. package/dist/threads/offline-session-list.cjs +3 -3
  593. package/dist/threads/offline-session-list.cjs.map +1 -1
  594. package/dist/threads/session-list-tab-share.cjs +5 -5
  595. package/dist/threads/session-list-tab-share.cjs.map +1 -1
  596. package/dist/threads/statewire-thread-list.cjs +55 -51
  597. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  598. package/dist/threads/statewire-thread-list.js +6 -2
  599. package/dist/threads/statewire-thread-list.js.map +1 -1
  600. package/dist/threads/thread-id-context.cjs +5 -5
  601. package/dist/threads/thread-id-context.cjs.map +1 -1
  602. package/dist/threads/use-athena-session-attention.cjs +2 -2
  603. package/dist/threads/use-athena-session-attention.cjs.map +1 -1
  604. package/dist/threads/use-athena-sessions.cjs +10 -10
  605. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  606. package/dist/threads/use-athena-thread-model.cjs +3 -3
  607. package/dist/threads/use-athena-thread-model.cjs.map +1 -1
  608. package/dist/threads/use-rest-conversation-history.cjs +3 -3
  609. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  610. package/dist/threads/use-statewire-conversation-history.cjs +8 -8
  611. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  612. package/dist/threads/use-thread-archive.cjs +9 -9
  613. package/dist/threads/use-thread-archive.cjs.map +1 -1
  614. package/dist/threads/use-thread-favorite.cjs +2 -2
  615. package/dist/threads/use-thread-favorite.cjs.map +1 -1
  616. package/dist/threads/use-thread-field-override.cjs +20 -20
  617. package/dist/threads/use-thread-field-override.cjs.map +1 -1
  618. package/dist/threads/use-thread-read-state.cjs +4 -4
  619. package/dist/threads/use-thread-read-state.cjs.map +1 -1
  620. package/dist/threads/use-thread-rename.cjs +2 -2
  621. package/dist/threads/use-thread-rename.cjs.map +1 -1
  622. package/dist/threads/useAthenaThreadManager.cjs +2 -2
  623. package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
  624. package/dist/tools/NestedPtcMessages.cjs +6 -6
  625. package/dist/tools/NestedPtcMessages.cjs.map +1 -1
  626. package/dist/tools/append-document-tool-ui.cjs +7 -7
  627. package/dist/tools/append-document-tool-ui.cjs.map +1 -1
  628. package/dist/tools/file-tool-uis.cjs +2 -2
  629. package/dist/tools/file-tool-uis.cjs.map +1 -1
  630. package/dist/tools/misc-tool-uis.cjs +2 -2
  631. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  632. package/dist/tools/primitives.cjs +6 -6
  633. package/dist/tools/primitives.cjs.map +1 -1
  634. package/dist/tools/read-asset-tool-ui.cjs +6 -6
  635. package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
  636. package/dist/tools/subagent-task-tool-ui.cjs +21 -21
  637. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  638. package/dist/tools/test-recording-tool-uis.cjs +16 -16
  639. package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
  640. package/dist/tools/todo-plan-store.cjs +4 -4
  641. package/dist/tools/todo-plan-store.cjs.map +1 -1
  642. package/dist/tools/tool-appearance.cjs +3 -3
  643. package/dist/tools/tool-appearance.cjs.map +1 -1
  644. package/dist/tools/tool-fallback.cjs +14 -14
  645. package/dist/tools/tool-fallback.cjs.map +1 -1
  646. package/dist/tools/tool-summary.cjs +0 -2
  647. package/dist/tools/tool-summary.cjs.map +1 -1
  648. package/dist/tools/tool-summary.js +0 -2
  649. package/dist/tools/tool-summary.js.map +1 -1
  650. package/dist/tools/tool-uis.cjs +74 -74
  651. package/dist/tools/tool-uis.cjs.map +1 -1
  652. package/dist/tools/use-elapsed-seconds.cjs +3 -3
  653. package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
  654. package/dist/tools/write-todos-tool-ui.cjs +9 -9
  655. package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
  656. package/dist/ui/image-viewer.cjs +382 -0
  657. package/dist/ui/image-viewer.cjs.map +1 -0
  658. package/dist/ui/image-viewer.d.ts +50 -0
  659. package/dist/ui/image-viewer.js +382 -0
  660. package/dist/ui/image-viewer.js.map +1 -0
  661. package/dist/voice/chat.cjs +6 -0
  662. package/dist/voice/chat.cjs.map +1 -1
  663. package/dist/voice/chat.d.ts +1 -1
  664. package/dist/voice/chat.js +8 -2
  665. package/dist/voice/livekit-join.cjs +52 -101
  666. package/dist/voice/livekit-join.cjs.map +1 -1
  667. package/dist/voice/livekit-join.d.ts +1 -6
  668. package/dist/voice/livekit-join.js +52 -101
  669. package/dist/voice/livekit-join.js.map +1 -1
  670. package/dist/voice/livekit.cjs.map +1 -1
  671. package/dist/voice/livekit.d.ts +11 -1
  672. package/dist/voice/livekit.js.map +1 -1
  673. package/dist/voice/use-athena-voice-session.cjs +34 -34
  674. package/dist/voice/use-athena-voice-session.cjs.map +1 -1
  675. package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
  676. package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
  677. package/dist/workbench/SessionWorkbench.cjs +22 -22
  678. package/dist/workbench/SessionWorkbench.cjs.map +1 -1
  679. package/dist/workbench/session-workbench-context.cjs +3 -3
  680. package/dist/workbench/session-workbench-context.cjs.map +1 -1
  681. package/dist/workbench/session-workbench-panes.cjs +8 -8
  682. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  683. package/dist/workbench/workbench-layout-context.cjs +3 -3
  684. package/dist/workbench/workbench-layout-context.cjs.map +1 -1
  685. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"auth.cjs","sources":["../../src/runtime/auth.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { AthenaTokenRenewer } from '../auth/credential-source';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { AthenaSdkError } from '../diagnostics/errors';\n\n/**\n * Hosts under `athenaintel.com` that serve customer-written code:\n * - Marathon's computer and application apps: `{id}.app.athenaintel.com`,\n * `{id}.staging-app.athenaintel.com`, `{id}.canary-app.athenaintel.com`, an\n * environment's `{id}.app.{env}.athenaintel.com`, and the staging wildcard\n * `{id}.computer.stg.athenaintel.com` (and `{id}.computer-canary.stg.athenaintel.com`);\n * - the Sandpack bundler's User Interface previews:\n * `{id}-sandpack.code-sandpack.athenaintel.com` (and `.code-sandpack.{env}.`).\n * They are never a trusted parent and never a backend the bridge points the\n * SDK at.\n */\nconst CUSTOMER_APP_HOST =\n /^.+\\.(?:(?:[a-z0-9-]+-)?app(?:\\.[a-z0-9-]+)*|computer(?:-[a-z0-9-]+)?\\.stg|code-sandpack(?:\\.[a-z0-9-]+)*)\\.athenaintel\\.com$/i;\n\n/** Whether `hostname` serves customer apps (see {@link CUSTOMER_APP_HOST}). */\nexport function isCustomerAppHost(hostname: string): boolean {\n return CUSTOMER_APP_HOST.test(hostname);\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';\n}\n\nfunction isAthenaHost(hostname: string): boolean {\n return hostname === 'athenaintel.com' || hostname.endsWith('.athenaintel.com');\n}\n\n/**\n * Check whether a PostMessage origin is trusted as the parent.\n * Accepts:\n * - explicit trusted origins passed by the host app\n * - the current iframe origin (for same-origin wrappers like Marathon)\n * - Athena's own hosts under athenaintel.com and localhost (default\n * behavior), except the customer-app hosts Marathon serves\n */\nexport function isTrustedParentOrigin({\n origin,\n trustedOrigins,\n}: {\n origin: string;\n trustedOrigins: string[];\n}): boolean {\n try {\n const normalizedOrigin = new URL(origin).origin;\n if (trustedOrigins.includes(normalizedOrigin)) {\n return true;\n }\n\n const { hostname } = new URL(normalizedOrigin);\n if (isCustomerAppHost(hostname)) {\n return false;\n }\n return isAthenaHost(hostname) || hostname === 'localhost';\n } catch {\n return false;\n }\n}\n\n/** Why {@link isAcceptableBridgeUrl} refused a URL. */\nexport type BridgeUrlRefusal = 'invalid' | 'insecure' | 'customer_app_host' | 'other_domain';\n\n/**\n * Whether a URL a trusted parent sent in `athena-config` may become the\n * SDK's backend, statewire mount or app URL. The SDK sends its bearer token\n * to the first two, so a URL is taken only when it is `https:` (plain\n * `http:` only between loopback hosts, for local development), carries no\n * credentials, is not a customer-code host ({@link CUSTOMER_APP_HOST}), and\n * is one of Athena's own hosts or, for a parent outside `athenaintel.com`,\n * the parent's own host or a subdomain of it. Sibling hosts are not taken:\n * without a public-suffix list `portal.example.co.uk` and `tenant.github.io`\n * cannot be told apart from a private domain, so a wrapper whose backend is\n * elsewhere passes its URLs through `config`. Returns the refusal, or `null`\n * when the URL is acceptable.\n */\nexport function refuseBridgeUrl({\n url,\n parentOrigin,\n}: {\n url: string;\n parentOrigin: string;\n}): BridgeUrlRefusal | null {\n let parsed: URL;\n let parentHostname: string;\n try {\n parsed = new URL(url);\n parentHostname = new URL(parentOrigin).hostname;\n } catch {\n return 'invalid';\n }\n if (parsed.username || parsed.password) return 'invalid';\n const { hostname } = parsed;\n const loopbackPair = isLoopbackHost(hostname) && isLoopbackHost(parentHostname);\n if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopbackPair)) {\n return 'insecure';\n }\n if (isCustomerAppHost(hostname)) return 'customer_app_host';\n if (loopbackPair || isAthenaHost(hostname)) return null;\n // Athena and loopback parents point only at Athena's own hosts (above).\n if (isAthenaHost(parentHostname) || isLoopbackHost(parentHostname)) return 'other_domain';\n return hostname === parentHostname || hostname.endsWith(`.${parentHostname}`)\n ? null\n : 'other_domain';\n}\n\n/** {@link refuseBridgeUrl} as a predicate. */\nexport function isAcceptableBridgeUrl(options: { url: string; parentOrigin: string }): boolean {\n return refuseBridgeUrl(options) === null;\n}\n\nexport interface ParentBridgeState {\n /** PropelAuth access token from the parent window. */\n token: string | null;\n /**\n * Statewire sync mount (`…/v2/threads`) minted by the host. `null` when the\n * host minted none; the provider then derives it from the configured\n * `apiUrl`'s origin (or the environment preset).\n */\n statewireSyncUrl: string | null;\n /**\n * Bare Agora API base (no path) minted by the host. `null` when the host\n * minted none; the provider then uses the configured `backendUrl` (or the\n * environment preset).\n */\n backendBaseUrl: string | null;\n /** Athena frontend origin provided by the parent wrapper. */\n appUrl: string | null;\n /**\n * True once a host answered the bridge — a `/_athena/auth` mint or an\n * `athena-config` message — whether or not it minted the statewire fields.\n * Lets the provider tell an outdated host (answered, no mount) from no host\n * at all (the environment preset applies).\n */\n hostAnswered: boolean;\n /** True once config has been received from the parent (or timeout fired). */\n ready: boolean;\n /**\n * Set when the Marathon mint (`/_athena/auth`) gave up. It gives up when it\n * gets a refusal (401, 403, or any 4xx other than 404), a body it cannot\n * read, or a transient failure (5xx, 408, 429, a network error, a timeout)\n * on every attempt of one bounded retry cycle. `code` is\n * `auth_bridge_failed`, or `auth_bridge_timeout` when the last attempt\n * timed out. After that the bridge does not mint again in the background. A\n * forced renewal (`renewToken({ force: true })`) starts one new bounded\n * cycle. A token that an earlier mint handed out is kept (the server still\n * validates it), and the bridge never puts an empty token in its place. The\n * next successful mint clears it. Absent or `null` otherwise.\n */\n error?: AthenaSdkError | null;\n}\n\n/**\n * {@link ParentBridgeState} plus the bridge's token renewal: `force` (the\n * token was refused) asks the host for a new one — a fresh `/_athena/auth`\n * mint on a Marathon origin, or an `athena-auth-ready` request answered by the\n * parent window's next `athena-auth` — and resolves the held token otherwise.\n */\nexport type ParentBridge = ParentBridgeState & { renewToken: AthenaTokenRenewer };\n\nconst BRIDGE_URL_FIELDS = ['statewireSyncUrl', 'backendBaseUrl', 'appUrl'] as const;\n\ntype BridgeUrlField = (typeof BRIDGE_URL_FIELDS)[number];\n\n/** The URL half of {@link ParentBridgeState} — what a host can hand the SDK. */\nexport type ParentBridgeUrls = Pick<ParentBridgeState, BridgeUrlField>;\n\nconst EMPTY_BRIDGE_URLS: ParentBridgeUrls = {\n statewireSyncUrl: null,\n backendBaseUrl: null,\n appUrl: null,\n};\n\n/**\n * Fold a URL payload over the current URL set without vetting it (the\n * same-origin `/_athena/auth` mint body; a parent's `athena-config` goes\n * through {@link acceptBridgeConfigMessage}). A field is taken only when it is\n * a string; anything else keeps the previous value. Keys outside\n * {@link BridgeUrlField} (a legacy parent's `apiUrl` / `backendUrl` among\n * them) are dropped.\n */\nexport function mergeBridgeConfigMessage(\n previous: ParentBridgeUrls,\n payload: Partial<Record<BridgeUrlField, unknown>>,\n): ParentBridgeUrls {\n const next: ParentBridgeUrls = {\n statewireSyncUrl: previous.statewireSyncUrl,\n backendBaseUrl: previous.backendBaseUrl,\n appUrl: previous.appUrl,\n };\n for (const field of BRIDGE_URL_FIELDS) {\n const value = payload[field];\n if (typeof value === 'string') {\n next[field] = value;\n }\n }\n return next;\n}\n\n/** A URL field of an `athena-config` message that was not taken, and why. */\nexport interface RejectedBridgeUrl {\n field: BridgeUrlField;\n reason: BridgeUrlRefusal | 'changed';\n}\n\n/**\n * Fold an `athena-config` message from a trusted parent over the current URL\n * set, taking only what is safe to point the SDK's bearer at: each string\n * field must pass {@link refuseBridgeUrl} against the parent's origin. The\n * first config message sets the URLs; once `locked` (a config message was\n * already taken) a value that differs from the held one, including a field\n * the first message left unset, is refused (`changed`), so a later message\n * cannot repoint a running SDK. Resending the same value is fine.\n */\nexport function acceptBridgeConfigMessage({\n previous,\n payload,\n parentOrigin,\n locked = false,\n}: {\n previous: ParentBridgeUrls;\n payload: Partial<Record<BridgeUrlField, unknown>>;\n parentOrigin: string;\n locked?: boolean;\n}): { urls: ParentBridgeUrls; rejected: RejectedBridgeUrl[] } {\n const urls: ParentBridgeUrls = {\n statewireSyncUrl: previous.statewireSyncUrl,\n backendBaseUrl: previous.backendBaseUrl,\n appUrl: previous.appUrl,\n };\n const rejected: RejectedBridgeUrl[] = [];\n for (const field of BRIDGE_URL_FIELDS) {\n const value = payload[field];\n if (typeof value !== 'string') continue;\n const held = previous[field];\n if (locked || held !== null) {\n if (held !== value) rejected.push({ field, reason: 'changed' });\n continue;\n }\n const refusal = refuseBridgeUrl({ url: value, parentOrigin });\n if (refusal !== null) {\n rejected.push({ field, reason: refusal });\n continue;\n }\n urls[field] = value;\n }\n return { urls, rejected };\n}\n\n/**\n * Read the URL set out of a `/_athena/auth` mint body. Non-string fields are\n * `null`.\n */\nexport function readAuthMintUrls(data: Partial<Record<BridgeUrlField, unknown>>): ParentBridgeUrls {\n return mergeBridgeConfigMessage(EMPTY_BRIDGE_URLS, data);\n}\n\nexport interface ParentBridgeOptions {\n /**\n * Exact parent origins that are allowed to send auth/config via postMessage.\n * Useful for private-cloud or custom-domain deployments.\n */\n trustedOrigins?: string[];\n /** @internal Overrides {@link DEFAULT_MINT_RETRY_POLICY}; used by tests. */\n mintRetryPolicy?: MintRetryPolicy;\n}\n\n/** How long to wait for the parent bridge before falling back to defaults. */\nconst BRIDGE_TIMEOUT_MS = 2000;\n/** How long a renewal waits for the parent window to answer `athena-auth-ready`. */\nconst PARENT_TOKEN_RENEWAL_TIMEOUT_MS = 5000;\nconst TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;\nconst TOKEN_REFRESH_MIN_DELAY_MS = 60 * 1000;\nconst DEFAULT_TOKEN_REFRESH_MS = 55 * 60 * 1000;\nconst EMPTY_TRUSTED_ORIGINS: string[] = [];\n\n/**\n * How one Marathon mint cycle retries. A cycle is the initial acquisition, a\n * scheduled refresh, or a forced renewal. It sends at most `maxAttempts`\n * requests. It retries only a transient failure (5xx, 408, 429, a network\n * error, a timeout), after a capped exponential backoff with jitter, and then\n * it gives up. Nothing retries in the background after a cycle gave up.\n */\nexport interface MintRetryPolicy {\n /** Requests per cycle, the first one included. */\n maxAttempts: number;\n /** Ceiling of the delay before the first retry; it doubles for each retry. */\n baseDelayMs: number;\n /** Largest delay before any retry. */\n maxDelayMs: number;\n /** How long one request can take before it is aborted and counted as a timeout. */\n timeoutMs: number;\n /** Source of jitter in `[0, 1)`. */\n random: () => number;\n}\n\nexport const DEFAULT_MINT_RETRY_POLICY: MintRetryPolicy = {\n maxAttempts: 4,\n baseDelayMs: 500,\n maxDelayMs: 4000,\n timeoutMs: BRIDGE_TIMEOUT_MS,\n random: Math.random,\n};\n\n/** Untrusted shape of the `/_athena/auth` mint body; every field is type-guarded on read. */\ninterface AthenaAuthResponse {\n token?: unknown;\n statewireSyncUrl?: unknown;\n backendBaseUrl?: unknown;\n appUrl?: unknown;\n expires_at?: unknown;\n}\n\nconst normalizeOrigin = (value: string): string | null => {\n try {\n return new URL(value).origin;\n } catch {\n return null;\n }\n};\n\nexport const getTokenRefreshDelay = (expiresAt: unknown, nowMs: number): number => {\n if (typeof expiresAt !== 'string') {\n return DEFAULT_TOKEN_REFRESH_MS;\n }\n\n const expiresAtMs = Date.parse(expiresAt);\n if (!Number.isFinite(expiresAtMs)) {\n return DEFAULT_TOKEN_REFRESH_MS;\n }\n\n return Math.max(TOKEN_REFRESH_MIN_DELAY_MS, expiresAtMs - nowMs - TOKEN_REFRESH_BUFFER_MS);\n};\n\n/**\n * The delay before retry number `retry` of a mint cycle (1 is the first\n * retry). The ceiling is `min(maxDelayMs, baseDelayMs * 2^(retry - 1))`, and\n * equal jitter puts the wait between half of that ceiling and all of it, so\n * viewers whose mint failed at the same time do not retry at the same time.\n */\nexport function getMintRetryDelay({\n retry,\n policy = DEFAULT_MINT_RETRY_POLICY,\n}: {\n retry: number;\n policy?: Pick<MintRetryPolicy, 'baseDelayMs' | 'maxDelayMs' | 'random'>;\n}): number {\n const safeRetry = Number.isFinite(retry) ? Math.max(1, Math.floor(retry)) : 1;\n const ceiling = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** (safeRetry - 1));\n const jitter = Math.min(1, Math.max(0, policy.random()));\n return Math.round(ceiling / 2 + (ceiling / 2) * jitter);\n}\n\n/** A mint status worth another attempt: the host, or something in front of it, is briefly unwell. */\nexport function isRetryableMintStatus(status: number): boolean {\n return status >= 500 || status === 408 || status === 429;\n}\n\n/** A failed `/_athena/auth` request that is worth another attempt. */\ninterface TransientMintFailure {\n kind: 'transient';\n status: number | null;\n reason: 'status' | 'network' | 'timeout';\n hostError: string | null;\n cause?: unknown;\n}\n\n/** A failed `/_athena/auth` request that ends its cycle at once. */\ninterface RefusedMintFailure {\n kind: 'refused';\n status: number;\n /** `status`: a 4xx other than 404, 408 and 429. `invalid_body`: a 2xx whose body is not a JSON object. */\n reason: 'status' | 'invalid_body';\n hostError: string | null;\n}\n\nexport type MintFailure = TransientMintFailure | RefusedMintFailure;\n\n/** The outcome of one `/_athena/auth` request. */\ntype MintAttempt =\n | { kind: 'minted'; data: AthenaAuthResponse }\n /** 404: this is not a Marathon origin. */\n | { kind: 'absent'; status: number }\n | MintFailure\n | { kind: 'cancelled' };\n\n/** The `error` string of a Marathon failure body (`{\"error\":\"mint_failed\"}`), if any. */\nasync function readHostError(resp: Response): Promise<string | null> {\n try {\n const body: unknown = await resp.json();\n if (body && typeof body === 'object' && 'error' in body) {\n const value = (body as { error?: unknown }).error;\n return typeof value === 'string' ? value.slice(0, 100) : null;\n }\n } catch {\n // An empty or non-JSON error body tells nothing more than the status.\n }\n return null;\n}\n\nconst MINT_RETRY_NOTE =\n 'The SDK stopped retrying and does not connect without a credential. Remount the provider, or call renewToken({ force: true }), to try again.';\n\nfunction mintFailureHint(failure: MintFailure): string {\n if (failure.kind === 'transient') {\n return `The host could not mint a viewer token. Check the Marathon and Agora logs. ${MINT_RETRY_NOTE}`;\n }\n if (failure.reason === 'invalid_body') {\n return `The host answered /_athena/auth without a JSON mint body, so this origin is not a Marathon bridge. Pass token, getToken or apiKey. ${MINT_RETRY_NOTE}`;\n }\n if (failure.status === 401) {\n return `The host has no session for this viewer. Sign in again through the app URL. ${MINT_RETRY_NOTE}`;\n }\n if (failure.status === 403) {\n return `The host does not give this viewer access to the app. ${MINT_RETRY_NOTE}`;\n }\n return `The host refused the mint request. ${MINT_RETRY_NOTE}`;\n}\n\n/** The typed error that a mint cycle reports when it gives up. */\nexport function mintFailureError({\n failure,\n attempts,\n phase,\n}: {\n failure: MintFailure;\n attempts: number;\n phase: 'initial' | 'renewal';\n}): AthenaSdkError {\n const timedOut = failure.kind === 'transient' && failure.reason === 'timeout';\n const answer =\n failure.status !== null ? `HTTP ${failure.status}` : timedOut ? 'a timeout' : 'a network error';\n const message =\n failure.kind === 'transient'\n ? `The host auth bridge (/_athena/auth) failed ${attempts} time${attempts === 1 ? '' : 's'} (last: ${answer}).`\n : failure.reason === 'invalid_body'\n ? `The host auth bridge (/_athena/auth) answered ${answer} without a JSON mint body.`\n : `The host auth bridge (/_athena/auth) refused the mint (${answer}).`;\n return new AthenaSdkError({\n code: timedOut ? 'auth_bridge_timeout' : 'auth_bridge_failed',\n message,\n hint: mintFailureHint(failure),\n ...(failure.status !== null && { status: failure.status }),\n ...(failure.hostError !== null && { detail: { code: failure.hostError } }),\n ...(failure.kind === 'transient' && failure.cause !== undefined && { cause: failure.cause }),\n context: {\n mode: 'marathon',\n phase,\n attempts,\n reason: failure.reason,\n host_error: failure.hostError,\n },\n });\n}\n\n/**\n * Listens for auth tokens AND environment config from the host environment.\n *\n * Two transport modes, picked automatically:\n *\n * 1. **Iframe (legacy / Olympus inline preview)**: a parent window posts\n * `athena-config` and `athena-auth` via PostMessage. The hook also posts\n * `athena-auth-ready` so the parent knows when to (re-)send. Only the\n * window that frames the app (`event.source === window.parent`) on a\n * trusted origin ({@link isTrustedParentOrigin}) is heard, and an\n * `athena-config` URL is taken only once and only when it passes\n * {@link refuseBridgeUrl}.\n *\n * 2. **Standalone (Marathon-served deploy URL)**: top-level navigation, no\n * parent. The hook fetches `/_athena/auth` on its own origin. Marathon\n * validates its session cookie (sent by the browser automatically) and\n * returns `{ token, statewireSyncUrl, backendBaseUrl, appUrl }` — the\n * statewire mount, the bare Agora base and the app origin. A 404 means\n * we're not on a Marathon origin — the hook falls through with empty\n * state. Any other failure fails closed: one bounded retry cycle\n * ({@link MintRetryPolicy}) for a transient failure, none for a refusal,\n * and then `error` is set and `ready` flips with no token — never an\n * empty or anonymous one.\n *\n * In both modes the app never blocks indefinitely: the iframe bridge flips\n * `ready: true` after a timeout, and a Marathon mint cycle ends after at most\n * `maxAttempts` requests.\n */\nexport function useParentBridge({\n trustedOrigins = EMPTY_TRUSTED_ORIGINS,\n mintRetryPolicy = DEFAULT_MINT_RETRY_POLICY,\n}: ParentBridgeOptions = {}): ParentBridge {\n const isInIframe = typeof window !== 'undefined' && window.parent !== window;\n const runtimeTrustedOrigins = useMemo(() => {\n const origins = new Set<string>();\n\n if (typeof window !== 'undefined') {\n origins.add(window.location.origin);\n }\n\n for (const trustedOrigin of trustedOrigins) {\n const normalizedOrigin = normalizeOrigin(trustedOrigin);\n if (normalizedOrigin) {\n origins.add(normalizedOrigin);\n }\n }\n\n return [...origins];\n }, [trustedOrigins]);\n\n const [state, setState] = useState<ParentBridgeState>({\n token: null,\n ...EMPTY_BRIDGE_URLS,\n hostAnswered: false,\n ready: false,\n error: null,\n });\n // Read when a mint cycle starts, so a caller's inline policy object does not\n // restart the bridge on every render.\n const mintRetryPolicyRef = useRef(mintRetryPolicy);\n mintRetryPolicyRef.current = mintRetryPolicy;\n const readySignalSent = useRef(false);\n const configReceived = useRef(false);\n // The URLs the parent has set so far: a later `athena-config` may not change them.\n const parentUrlsRef = useRef<ParentBridgeUrls>(EMPTY_BRIDGE_URLS);\n const tokenRef = useRef<string | null>(state.token);\n tokenRef.current = state.token;\n // Installed by whichever transport mode is active (iframe or Marathon).\n const renewerRef = useRef<AthenaTokenRenewer | null>(null);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n const endBridgeSpan = athenaDiagnostics.span('auth.bridge', 'auth.bridge.start', {\n mode: 'iframe',\n });\n let spanEnded = false;\n const endOnce: typeof endBridgeSpan = (name, options) => {\n if (spanEnded) return 0;\n spanEnded = true;\n return endBridgeSpan(name, options);\n };\n\n // Renewals waiting for the parent's next `athena-auth`.\n const tokenWaiters = new Set<(token: string | null) => void>();\n\n const handler = (event: MessageEvent) => {\n // Only the window that frames this app speaks for the host: a popup,\n // an opener or a sibling frame on a trusted origin does not.\n if (event.source !== window.parent) return;\n if (\n !isTrustedParentOrigin({ origin: event.origin, trustedOrigins: runtimeTrustedOrigins })\n ) {\n return;\n }\n if (!event.data || typeof event.data !== 'object') return;\n\n if (event.data.type === 'athena-config') {\n const { urls, rejected } = acceptBridgeConfigMessage({\n previous: parentUrlsRef.current,\n payload: event.data,\n parentOrigin: event.origin,\n locked: configReceived.current,\n });\n configReceived.current = true;\n parentUrlsRef.current = urls;\n for (const { field, reason } of rejected) {\n athenaDiagnostics.emit('auth.bridge.config_rejected', {\n level: 'warn',\n data: { mode: 'iframe', field, reason },\n });\n }\n setState((prev) => ({\n ...prev,\n ...urls,\n hostAnswered: true,\n // Don't set ready here — wait for athena-auth (token) or the timeout.\n // Setting ready on config alone causes a race: the thread list fires\n // before the token arrives, falling back to X-API-KEY.\n }));\n }\n\n if (event.data.type === 'athena-auth' && typeof event.data.token === 'string') {\n endOnce('auth.bridge.ready', { data: { mode: 'iframe' } });\n athenaDiagnostics.emit('auth.token.acquired', {\n level: 'debug',\n data: { source: 'iframe-postmessage' },\n });\n setState((prev) => ({\n ...prev,\n token: event.data.token,\n ready: true,\n }));\n tokenRef.current = event.data.token;\n for (const resolve of [...tokenWaiters]) resolve(event.data.token);\n }\n };\n window.addEventListener('message', handler);\n\n // A renewal asks the parent to send its current token again — the same\n // `athena-auth-ready` handshake a parent already answers — and settles on\n // the next `athena-auth`, or on the held token when none arrives in time.\n renewerRef.current = ({ force }) => {\n if (!force) return Promise.resolve(tokenRef.current);\n return new Promise<string | null>((resolve) => {\n const settle = (token: string | null) => {\n clearTimeout(timer);\n tokenWaiters.delete(settle);\n resolve(token ?? tokenRef.current);\n };\n const timer = setTimeout(() => settle(null), PARENT_TOKEN_RENEWAL_TIMEOUT_MS);\n tokenWaiters.add(settle);\n window.parent.postMessage({ type: 'athena-auth-ready' }, '*');\n });\n };\n\n if (!readySignalSent.current) {\n window.parent.postMessage({ type: 'athena-auth-ready' }, '*');\n readySignalSent.current = true;\n }\n\n const timer = setTimeout(() => {\n endOnce('auth.bridge.timeout', {\n data: {\n mode: 'iframe',\n timeout_ms: BRIDGE_TIMEOUT_MS,\n config_received: configReceived.current,\n },\n });\n setState((prev) => (prev.ready ? prev : { ...prev, ready: true }));\n }, BRIDGE_TIMEOUT_MS);\n\n return () => {\n window.removeEventListener('message', handler);\n clearTimeout(timer);\n renewerRef.current = null;\n for (const resolve of [...tokenWaiters]) resolve(null);\n };\n }, [isInIframe, runtimeTrustedOrigins]);\n\n useEffect(() => {\n if (isInIframe) return;\n if (typeof window === 'undefined') return;\n\n let cancelled = false;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n let controller: AbortController | null = null;\n let inFlight: Promise<string | null> | null = null;\n let retryWait: { timer: ReturnType<typeof setTimeout>; resolve: () => void } | null = null;\n\n const clearRefreshTimer = () => {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = null;\n }\n };\n\n const endRetryWait = () => {\n if (!retryWait) return;\n clearTimeout(retryWait.timer);\n const { resolve } = retryWait;\n retryWait = null;\n resolve();\n };\n\n /** The backoff between two attempts of one cycle; unmounting ends it at once. */\n const waitBeforeRetry = (delayMs: number) =>\n new Promise<void>((resolve) => {\n retryWait = { timer: setTimeout(endRetryWait, delayMs), resolve };\n });\n\n // The only background mint: once per token, shortly before it expires. It\n // is not rescheduled when its cycle gives up. A forced renewal that gives\n // up leaves it in place on purpose: the held token is still live, and\n // this one bounded cycle keeps a viewer connected past a brief outage.\n const scheduleRefresh = (expiresAt: unknown) => {\n clearRefreshTimer();\n const delay = getTokenRefreshDelay(expiresAt, Date.now());\n refreshTimer = setTimeout(() => {\n refreshTimer = null;\n void fetchAuth({ initial: false });\n }, delay);\n };\n\n /** One `/_athena/auth` request, classified. */\n const mintOnce = async (timeoutMs: number): Promise<MintAttempt> => {\n const requestController = new AbortController();\n controller = requestController;\n let timedOut = false;\n const requestTimer = setTimeout(() => {\n timedOut = true;\n requestController.abort();\n }, timeoutMs);\n\n try {\n const resp = await fetch('/_athena/auth', {\n credentials: 'include',\n headers: { Accept: 'application/json' },\n signal: requestController.signal,\n });\n if (cancelled) return { kind: 'cancelled' };\n // Not a Marathon origin: expected for standalone apps and local dev.\n if (resp.status === 404) return { kind: 'absent', status: resp.status };\n if (!resp.ok) {\n const hostError = await readHostError(resp);\n if (cancelled) return { kind: 'cancelled' };\n // `readHostError` swallows the abort of a stalled error body. Only a\n // retryable status becomes a timeout: a refusal (401, 403, other\n // 4xx) is known from its status and still fails after one request.\n if (timedOut && isRetryableMintStatus(resp.status)) {\n return { kind: 'transient', status: null, reason: 'timeout', hostError: null };\n }\n return isRetryableMintStatus(resp.status)\n ? { kind: 'transient', status: resp.status, reason: 'status', hostError }\n : { kind: 'refused', status: resp.status, reason: 'status', hostError };\n }\n\n let data: unknown;\n try {\n data = await resp.json();\n } catch (error) {\n if (cancelled) return { kind: 'cancelled' };\n if (timedOut) {\n return { kind: 'transient', status: null, reason: 'timeout', hostError: null, cause: error };\n }\n return { kind: 'refused', status: resp.status, reason: 'invalid_body', hostError: null };\n }\n if (cancelled) return { kind: 'cancelled' };\n // Marathon's 200 always carries a token. A 2xx without one is a\n // broken mint: it must not replace a held token or count as success.\n const token = data && typeof data === 'object' ? (data as { token?: unknown }).token : null;\n if (typeof token !== 'string' || token === '') {\n return { kind: 'refused', status: resp.status, reason: 'invalid_body', hostError: null };\n }\n return { kind: 'minted', data: data as AthenaAuthResponse };\n } catch (error) {\n if (cancelled) return { kind: 'cancelled' };\n if (timedOut) {\n return { kind: 'transient', status: null, reason: 'timeout', hostError: null, cause: error };\n }\n return { kind: 'transient', status: null, reason: 'network', hostError: null, cause: error };\n } finally {\n clearTimeout(requestTimer);\n if (controller === requestController) controller = null;\n }\n };\n\n /**\n * One bounded mint cycle: the initial acquisition (a span the provider\n * waits on) or a renewal (the scheduled refresh, a forced renewal). It\n * retries a transient failure up to `maxAttempts` requests in all, with\n * a capped, jittered backoff. On a refusal, or after the last attempt, it\n * gives up: it reports one typed error, sets `error`, keeps any token an\n * earlier mint handed out, and schedules nothing.\n */\n const runMintCycle = async ({ initial }: { initial: boolean }): Promise<string | null> => {\n const policy = mintRetryPolicyRef.current;\n const maxAttempts = Math.max(1, Math.floor(policy.maxAttempts));\n const phase = initial ? 'initial' : 'renewal';\n const endBridgeSpan = initial\n ? athenaDiagnostics.span('auth.bridge', 'auth.bridge.start', { mode: 'marathon' })\n : null;\n\n let attempts = 0;\n let lastFailure: MintFailure | null = null;\n while (attempts < maxAttempts) {\n attempts += 1;\n const outcome = await mintOnce(policy.timeoutMs);\n if (cancelled || outcome.kind === 'cancelled') return null;\n\n if (outcome.kind === 'absent') {\n endBridgeSpan?.('auth.bridge.absent', {\n data: { mode: 'marathon', status: outcome.status },\n });\n // 404 means no bridge here, so an earlier mint failure no longer\n // applies; the provider falls back to its other credentials.\n setState((prev) =>\n prev.ready && prev.error == null ? prev : { ...prev, ready: true, error: null },\n );\n return null;\n }\n\n if (outcome.kind === 'minted') {\n const { data } = outcome;\n if (endBridgeSpan) {\n endBridgeSpan('auth.bridge.ready', {\n data: { mode: 'marathon', has_token: typeof data.token === 'string', attempts },\n });\n athenaDiagnostics.emit('auth.token.acquired', {\n level: 'debug',\n data: { source: 'marathon', expires_at: data.expires_at },\n });\n } else {\n athenaDiagnostics.emit('auth.token.refreshed', {\n level: 'debug',\n data: { source: 'marathon', expires_at: data.expires_at, attempts },\n });\n }\n const token = typeof data.token === 'string' ? data.token : null;\n setState({\n token,\n ...readAuthMintUrls(data),\n hostAnswered: true,\n ready: true,\n error: null,\n });\n tokenRef.current = token;\n scheduleRefresh(data.expires_at);\n return token;\n }\n\n lastFailure = outcome;\n if (outcome.kind === 'refused' || attempts >= maxAttempts) break;\n\n const delayMs = getMintRetryDelay({ retry: attempts, policy });\n athenaDiagnostics.emit('auth.bridge.retry', {\n level: 'warn',\n data: {\n mode: 'marathon',\n phase,\n status: outcome.status,\n reason: outcome.reason,\n host_error: outcome.hostError,\n attempt: attempts,\n max_attempts: maxAttempts,\n delay_ms: delayMs,\n },\n });\n await waitBeforeRetry(delayMs);\n if (cancelled) return null;\n }\n\n if (!lastFailure) return null;\n const error = mintFailureError({ failure: lastFailure, attempts, phase });\n const failureData = {\n mode: 'marathon',\n phase,\n status: lastFailure.status,\n reason: lastFailure.reason,\n attempts,\n };\n if (endBridgeSpan) {\n endBridgeSpan(\n error.code === 'auth_bridge_timeout' ? 'auth.bridge.timeout' : 'auth.bridge.error',\n { data: failureData, error },\n );\n } else {\n athenaDiagnostics.emit('auth.token.refresh_failed', {\n level: 'error',\n data: failureData,\n error,\n });\n }\n setState((prev) => ({ ...prev, error, ready: true }));\n return null;\n };\n\n // One mint cycle at a time. The initial acquisition, a scheduled refresh\n // and forced renewals that overlap share the cycle in flight (its\n // requests, their timeouts and its backoff) instead of starting their own,\n // so concurrent callers never multiply the requests.\n const fetchAuth = (options: { initial: boolean }): Promise<string | null> => {\n inFlight ??= runMintCycle(options).finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n\n // A forced renewal mints now instead of waiting for the scheduled refresh\n // (joining a cycle already in flight), and may start a new bounded cycle\n // after one gave up. The schedule restarts from the new token's expiry.\n renewerRef.current = ({ force }) => {\n if (!force) return Promise.resolve(tokenRef.current);\n return fetchAuth({ initial: false }).then((token) => token ?? tokenRef.current);\n };\n\n void fetchAuth({ initial: true });\n\n return () => {\n cancelled = true;\n controller?.abort();\n clearRefreshTimer();\n endRetryWait();\n renewerRef.current = null;\n };\n }, [isInIframe]);\n\n const renewToken = useCallback<AthenaTokenRenewer>(\n (options) => renewerRef.current?.(options) ?? Promise.resolve(tokenRef.current),\n [],\n );\n\n return useMemo(() => ({ ...state, renewToken }), [state, renewToken]);\n}\n\n/**\n * Legacy hook — returns just the auth token from the parent bridge.\n * Prefer useParentBridge() for new code.\n */\nexport function useParentAuth(): string | null {\n return useParentBridge().token;\n}\n"],"names":["AthenaSdkError","useMemo","useState","useRef","useEffect","athenaDiagnostics","timer","useCallback"],"mappings":"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"}
1
+ {"version":3,"file":"auth.cjs","sources":["../../src/runtime/auth.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { AthenaTokenRenewer } from '../auth/credential-source';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { AthenaSdkError } from '../diagnostics/errors';\n\n/**\n * Hosts under `athenaintel.com` that serve customer-written code:\n * - Marathon's computer and application apps: `{id}.app.athenaintel.com`,\n * `{id}.staging-app.athenaintel.com`, `{id}.canary-app.athenaintel.com`, an\n * environment's `{id}.app.{env}.athenaintel.com`, and the staging wildcard\n * `{id}.computer.stg.athenaintel.com` (and `{id}.computer-canary.stg.athenaintel.com`);\n * - the Sandpack bundler's User Interface previews:\n * `{id}-sandpack.code-sandpack.athenaintel.com` (and `.code-sandpack.{env}.`).\n * They are never a trusted parent and never a backend the bridge points the\n * SDK at.\n */\nconst CUSTOMER_APP_HOST =\n /^.+\\.(?:(?:[a-z0-9-]+-)?app(?:\\.[a-z0-9-]+)*|computer(?:-[a-z0-9-]+)?\\.stg|code-sandpack(?:\\.[a-z0-9-]+)*)\\.athenaintel\\.com$/i;\n\n/** Whether `hostname` serves customer apps (see {@link CUSTOMER_APP_HOST}). */\nexport function isCustomerAppHost(hostname: string): boolean {\n return CUSTOMER_APP_HOST.test(hostname);\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';\n}\n\nfunction isAthenaHost(hostname: string): boolean {\n return hostname === 'athenaintel.com' || hostname.endsWith('.athenaintel.com');\n}\n\n/**\n * Check whether a PostMessage origin is trusted as the parent.\n * Accepts:\n * - explicit trusted origins passed by the host app\n * - the current iframe origin (for same-origin wrappers like Marathon)\n * - Athena's own hosts under athenaintel.com and localhost (default\n * behavior), except the customer-app hosts Marathon serves\n */\nexport function isTrustedParentOrigin({\n origin,\n trustedOrigins,\n}: {\n origin: string;\n trustedOrigins: string[];\n}): boolean {\n try {\n const normalizedOrigin = new URL(origin).origin;\n if (trustedOrigins.includes(normalizedOrigin)) {\n return true;\n }\n\n const { hostname } = new URL(normalizedOrigin);\n if (isCustomerAppHost(hostname)) {\n return false;\n }\n return isAthenaHost(hostname) || hostname === 'localhost';\n } catch {\n return false;\n }\n}\n\n/** Why {@link isAcceptableBridgeUrl} refused a URL. */\nexport type BridgeUrlRefusal = 'invalid' | 'insecure' | 'customer_app_host' | 'other_domain';\n\n/**\n * Whether a URL a trusted parent sent in `athena-config` may become the\n * SDK's backend, statewire mount or app URL. The SDK sends its bearer token\n * to the first two, so a URL is taken only when it is `https:` (plain\n * `http:` only between loopback hosts, for local development), carries no\n * credentials, is not a customer-code host ({@link CUSTOMER_APP_HOST}), and\n * is one of Athena's own hosts or, for a parent outside `athenaintel.com`,\n * the parent's own host or a subdomain of it. Sibling hosts are not taken:\n * without a public-suffix list `portal.example.co.uk` and `tenant.github.io`\n * cannot be told apart from a private domain, so a wrapper whose backend is\n * elsewhere passes its URLs through `config`. Returns the refusal, or `null`\n * when the URL is acceptable.\n */\nexport function refuseBridgeUrl({\n url,\n parentOrigin,\n}: {\n url: string;\n parentOrigin: string;\n}): BridgeUrlRefusal | null {\n let parsed: URL;\n let parentHostname: string;\n try {\n parsed = new URL(url);\n parentHostname = new URL(parentOrigin).hostname;\n } catch {\n return 'invalid';\n }\n if (parsed.username || parsed.password) return 'invalid';\n const { hostname } = parsed;\n const loopbackPair = isLoopbackHost(hostname) && isLoopbackHost(parentHostname);\n if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopbackPair)) {\n return 'insecure';\n }\n if (isCustomerAppHost(hostname)) return 'customer_app_host';\n if (loopbackPair || isAthenaHost(hostname)) return null;\n // Athena and loopback parents point only at Athena's own hosts (above).\n if (isAthenaHost(parentHostname) || isLoopbackHost(parentHostname)) return 'other_domain';\n return hostname === parentHostname || hostname.endsWith(`.${parentHostname}`)\n ? null\n : 'other_domain';\n}\n\n/** {@link refuseBridgeUrl} as a predicate. */\nexport function isAcceptableBridgeUrl(options: { url: string; parentOrigin: string }): boolean {\n return refuseBridgeUrl(options) === null;\n}\n\nexport interface ParentBridgeState {\n /** PropelAuth access token from the parent window. */\n token: string | null;\n /**\n * Statewire sync mount (`…/v2/threads`) minted by the host. `null` when the\n * host minted none; the provider then derives it from the configured\n * `apiUrl`'s origin (or the environment preset).\n */\n statewireSyncUrl: string | null;\n /**\n * Bare Agora API base (no path) minted by the host. `null` when the host\n * minted none; the provider then uses the configured `backendUrl` (or the\n * environment preset).\n */\n backendBaseUrl: string | null;\n /** Athena frontend origin provided by the parent wrapper. */\n appUrl: string | null;\n /**\n * True once a host answered the bridge — a `/_athena/auth` mint or an\n * `athena-config` message — whether or not it minted the statewire fields.\n * Lets the provider tell an outdated host (answered, no mount) from no host\n * at all (the environment preset applies).\n */\n hostAnswered: boolean;\n /** True once config has been received from the parent (or timeout fired). */\n ready: boolean;\n /**\n * Set when the Marathon mint (`/_athena/auth`) gave up. It gives up when it\n * gets a refusal (401, 403, or any 4xx other than 404), a body it cannot\n * read, or a transient failure (5xx, 408, 429, a network error, a timeout)\n * on every attempt of one bounded retry cycle. `code` is\n * `auth_bridge_failed`, or `auth_bridge_timeout` when the last attempt\n * timed out. After that the bridge does not mint again in the background. A\n * forced renewal (`renewToken({ force: true })`) starts one new bounded\n * cycle. A token that an earlier mint handed out is kept (the server still\n * validates it), and the bridge never puts an empty token in its place. The\n * next successful mint clears it. Absent or `null` otherwise.\n */\n error?: AthenaSdkError | null;\n}\n\n/**\n * {@link ParentBridgeState} plus the bridge's token renewal: `force` (the\n * token was refused) asks the host for a new one — a fresh `/_athena/auth`\n * mint on a Marathon origin, or an `athena-auth-ready` request answered by the\n * parent window's next `athena-auth` — and resolves the held token otherwise.\n */\nexport type ParentBridge = ParentBridgeState & { renewToken: AthenaTokenRenewer };\n\nconst BRIDGE_URL_FIELDS = ['statewireSyncUrl', 'backendBaseUrl', 'appUrl'] as const;\n\ntype BridgeUrlField = (typeof BRIDGE_URL_FIELDS)[number];\n\n/** The URL half of {@link ParentBridgeState} — what a host can hand the SDK. */\nexport type ParentBridgeUrls = Pick<ParentBridgeState, BridgeUrlField>;\n\nconst EMPTY_BRIDGE_URLS: ParentBridgeUrls = {\n statewireSyncUrl: null,\n backendBaseUrl: null,\n appUrl: null,\n};\n\n/**\n * Fold a URL payload over the current URL set without vetting it (the\n * same-origin `/_athena/auth` mint body; a parent's `athena-config` goes\n * through {@link acceptBridgeConfigMessage}). A field is taken only when it is\n * a string; anything else keeps the previous value. Keys outside\n * {@link BridgeUrlField} (a legacy parent's `apiUrl` / `backendUrl` among\n * them) are dropped.\n */\nexport function mergeBridgeConfigMessage(\n previous: ParentBridgeUrls,\n payload: Partial<Record<BridgeUrlField, unknown>>,\n): ParentBridgeUrls {\n const next: ParentBridgeUrls = {\n statewireSyncUrl: previous.statewireSyncUrl,\n backendBaseUrl: previous.backendBaseUrl,\n appUrl: previous.appUrl,\n };\n for (const field of BRIDGE_URL_FIELDS) {\n const value = payload[field];\n if (typeof value === 'string') {\n next[field] = value;\n }\n }\n return next;\n}\n\n/** A URL field of an `athena-config` message that was not taken, and why. */\nexport interface RejectedBridgeUrl {\n field: BridgeUrlField;\n reason: BridgeUrlRefusal | 'changed';\n}\n\n/**\n * Fold an `athena-config` message from a trusted parent over the current URL\n * set, taking only what is safe to point the SDK's bearer at: each string\n * field must pass {@link refuseBridgeUrl} against the parent's origin. The\n * first config message sets the URLs; once `locked` (a config message was\n * already taken) a value that differs from the held one, including a field\n * the first message left unset, is refused (`changed`), so a later message\n * cannot repoint a running SDK. Resending the same value is fine.\n */\nexport function acceptBridgeConfigMessage({\n previous,\n payload,\n parentOrigin,\n locked = false,\n}: {\n previous: ParentBridgeUrls;\n payload: Partial<Record<BridgeUrlField, unknown>>;\n parentOrigin: string;\n locked?: boolean;\n}): { urls: ParentBridgeUrls; rejected: RejectedBridgeUrl[] } {\n const urls: ParentBridgeUrls = {\n statewireSyncUrl: previous.statewireSyncUrl,\n backendBaseUrl: previous.backendBaseUrl,\n appUrl: previous.appUrl,\n };\n const rejected: RejectedBridgeUrl[] = [];\n for (const field of BRIDGE_URL_FIELDS) {\n const value = payload[field];\n if (typeof value !== 'string') continue;\n const held = previous[field];\n if (locked || held !== null) {\n if (held !== value) rejected.push({ field, reason: 'changed' });\n continue;\n }\n const refusal = refuseBridgeUrl({ url: value, parentOrigin });\n if (refusal !== null) {\n rejected.push({ field, reason: refusal });\n continue;\n }\n urls[field] = value;\n }\n return { urls, rejected };\n}\n\n/**\n * Read the URL set out of a `/_athena/auth` mint body. Non-string fields are\n * `null`.\n */\nexport function readAuthMintUrls(data: Partial<Record<BridgeUrlField, unknown>>): ParentBridgeUrls {\n return mergeBridgeConfigMessage(EMPTY_BRIDGE_URLS, data);\n}\n\nexport interface ParentBridgeOptions {\n /**\n * Exact parent origins that are allowed to send auth/config via postMessage.\n * Useful for private-cloud or custom-domain deployments.\n */\n trustedOrigins?: string[];\n /** @internal Overrides {@link DEFAULT_MINT_RETRY_POLICY}; used by tests. */\n mintRetryPolicy?: MintRetryPolicy;\n}\n\n/** How long to wait for the parent bridge before falling back to defaults. */\nconst BRIDGE_TIMEOUT_MS = 2000;\n/** How long a renewal waits for the parent window to answer `athena-auth-ready`. */\nconst PARENT_TOKEN_RENEWAL_TIMEOUT_MS = 5000;\nconst TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;\nconst TOKEN_REFRESH_MIN_DELAY_MS = 60 * 1000;\nconst DEFAULT_TOKEN_REFRESH_MS = 55 * 60 * 1000;\nconst EMPTY_TRUSTED_ORIGINS: string[] = [];\n\n/**\n * How one Marathon mint cycle retries. A cycle is the initial acquisition, a\n * scheduled refresh, or a forced renewal. It sends at most `maxAttempts`\n * requests. It retries only a transient failure (5xx, 408, 429, a network\n * error, a timeout), after a capped exponential backoff with jitter, and then\n * it gives up. Nothing retries in the background after a cycle gave up.\n */\nexport interface MintRetryPolicy {\n /** Requests per cycle, the first one included. */\n maxAttempts: number;\n /** Ceiling of the delay before the first retry; it doubles for each retry. */\n baseDelayMs: number;\n /** Largest delay before any retry. */\n maxDelayMs: number;\n /** How long one request can take before it is aborted and counted as a timeout. */\n timeoutMs: number;\n /** Source of jitter in `[0, 1)`. */\n random: () => number;\n}\n\nexport const DEFAULT_MINT_RETRY_POLICY: MintRetryPolicy = {\n maxAttempts: 4,\n baseDelayMs: 500,\n maxDelayMs: 4000,\n timeoutMs: BRIDGE_TIMEOUT_MS,\n random: Math.random,\n};\n\n/** Untrusted shape of the `/_athena/auth` mint body; every field is type-guarded on read. */\ninterface AthenaAuthResponse {\n token?: unknown;\n statewireSyncUrl?: unknown;\n backendBaseUrl?: unknown;\n appUrl?: unknown;\n expires_at?: unknown;\n}\n\nconst normalizeOrigin = (value: string): string | null => {\n try {\n return new URL(value).origin;\n } catch {\n return null;\n }\n};\n\nexport const getTokenRefreshDelay = (expiresAt: unknown, nowMs: number): number => {\n if (typeof expiresAt !== 'string') {\n return DEFAULT_TOKEN_REFRESH_MS;\n }\n\n const expiresAtMs = Date.parse(expiresAt);\n if (!Number.isFinite(expiresAtMs)) {\n return DEFAULT_TOKEN_REFRESH_MS;\n }\n\n return Math.max(TOKEN_REFRESH_MIN_DELAY_MS, expiresAtMs - nowMs - TOKEN_REFRESH_BUFFER_MS);\n};\n\n/**\n * The delay before retry number `retry` of a mint cycle (1 is the first\n * retry). The ceiling is `min(maxDelayMs, baseDelayMs * 2^(retry - 1))`, and\n * equal jitter puts the wait between half of that ceiling and all of it, so\n * viewers whose mint failed at the same time do not retry at the same time.\n */\nexport function getMintRetryDelay({\n retry,\n policy = DEFAULT_MINT_RETRY_POLICY,\n}: {\n retry: number;\n policy?: Pick<MintRetryPolicy, 'baseDelayMs' | 'maxDelayMs' | 'random'>;\n}): number {\n const safeRetry = Number.isFinite(retry) ? Math.max(1, Math.floor(retry)) : 1;\n const ceiling = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** (safeRetry - 1));\n const jitter = Math.min(1, Math.max(0, policy.random()));\n return Math.round(ceiling / 2 + (ceiling / 2) * jitter);\n}\n\n/** A mint status worth another attempt: the host, or something in front of it, is briefly unwell. */\nexport function isRetryableMintStatus(status: number): boolean {\n return status >= 500 || status === 408 || status === 429;\n}\n\n/** A failed `/_athena/auth` request that is worth another attempt. */\ninterface TransientMintFailure {\n kind: 'transient';\n status: number | null;\n reason: 'status' | 'network' | 'timeout';\n hostError: string | null;\n cause?: unknown;\n}\n\n/** A failed `/_athena/auth` request that ends its cycle at once. */\ninterface RefusedMintFailure {\n kind: 'refused';\n status: number;\n /** `status`: a 4xx other than 404, 408 and 429. `invalid_body`: a 2xx whose body is not a JSON object. */\n reason: 'status' | 'invalid_body';\n hostError: string | null;\n}\n\nexport type MintFailure = TransientMintFailure | RefusedMintFailure;\n\n/** The outcome of one `/_athena/auth` request. */\ntype MintAttempt =\n | { kind: 'minted'; data: AthenaAuthResponse }\n /** 404: this is not a Marathon origin. */\n | { kind: 'absent'; status: number }\n | MintFailure\n | { kind: 'cancelled' };\n\n/** The `error` string of a Marathon failure body (`{\"error\":\"mint_failed\"}`), if any. */\nasync function readHostError(resp: Response): Promise<string | null> {\n try {\n const body: unknown = await resp.json();\n if (body && typeof body === 'object' && 'error' in body) {\n const value = (body as { error?: unknown }).error;\n return typeof value === 'string' ? value.slice(0, 100) : null;\n }\n } catch {\n // An empty or non-JSON error body tells nothing more than the status.\n }\n return null;\n}\n\nconst MINT_RETRY_NOTE =\n 'The SDK stopped retrying and does not connect without a credential. Remount the provider, or call renewToken({ force: true }), to try again.';\n\nfunction mintFailureHint(failure: MintFailure): string {\n if (failure.kind === 'transient') {\n return `The host could not mint a viewer token. Check the Marathon and Agora logs. ${MINT_RETRY_NOTE}`;\n }\n if (failure.reason === 'invalid_body') {\n return `The host answered /_athena/auth without a JSON mint body, so this origin is not a Marathon bridge. Pass token, getToken or apiKey. ${MINT_RETRY_NOTE}`;\n }\n if (failure.status === 401) {\n return `The host has no session for this viewer. Sign in again through the app URL. ${MINT_RETRY_NOTE}`;\n }\n if (failure.status === 403) {\n return `The host does not give this viewer access to the app. ${MINT_RETRY_NOTE}`;\n }\n return `The host refused the mint request. ${MINT_RETRY_NOTE}`;\n}\n\n/** The typed error that a mint cycle reports when it gives up. */\nexport function mintFailureError({\n failure,\n attempts,\n phase,\n}: {\n failure: MintFailure;\n attempts: number;\n phase: 'initial' | 'renewal';\n}): AthenaSdkError {\n const timedOut = failure.kind === 'transient' && failure.reason === 'timeout';\n const answer =\n failure.status !== null ? `HTTP ${failure.status}` : timedOut ? 'a timeout' : 'a network error';\n const message =\n failure.kind === 'transient'\n ? `The host auth bridge (/_athena/auth) failed ${attempts} time${attempts === 1 ? '' : 's'} (last: ${answer}).`\n : failure.reason === 'invalid_body'\n ? `The host auth bridge (/_athena/auth) answered ${answer} without a JSON mint body.`\n : `The host auth bridge (/_athena/auth) refused the mint (${answer}).`;\n return new AthenaSdkError({\n code: timedOut ? 'auth_bridge_timeout' : 'auth_bridge_failed',\n message,\n hint: mintFailureHint(failure),\n ...(failure.status !== null && { status: failure.status }),\n ...(failure.hostError !== null && { detail: { code: failure.hostError } }),\n ...(failure.kind === 'transient' && failure.cause !== undefined && { cause: failure.cause }),\n context: {\n mode: 'marathon',\n phase,\n attempts,\n reason: failure.reason,\n host_error: failure.hostError,\n },\n });\n}\n\n/**\n * Listens for auth tokens AND environment config from the host environment.\n *\n * Two transport modes, picked automatically:\n *\n * 1. **Iframe (legacy / Olympus inline preview)**: a parent window posts\n * `athena-config` and `athena-auth` via PostMessage. The hook also posts\n * `athena-auth-ready` so the parent knows when to (re-)send. Only the\n * window that frames the app (`event.source === window.parent`) on a\n * trusted origin ({@link isTrustedParentOrigin}) is heard, and an\n * `athena-config` URL is taken only once and only when it passes\n * {@link refuseBridgeUrl}.\n *\n * 2. **Standalone (Marathon-served deploy URL)**: top-level navigation, no\n * parent. The hook fetches `/_athena/auth` on its own origin. Marathon\n * validates its session cookie (sent by the browser automatically) and\n * returns `{ token, statewireSyncUrl, backendBaseUrl, appUrl }` — the\n * statewire mount, the bare Agora base and the app origin. A 404 means\n * we're not on a Marathon origin — the hook falls through with empty\n * state. Any other failure fails closed: one bounded retry cycle\n * ({@link MintRetryPolicy}) for a transient failure, none for a refusal,\n * and then `error` is set and `ready` flips with no token — never an\n * empty or anonymous one.\n *\n * In both modes the app never blocks indefinitely: the iframe bridge flips\n * `ready: true` after a timeout, and a Marathon mint cycle ends after at most\n * `maxAttempts` requests.\n */\nexport function useParentBridge({\n trustedOrigins = EMPTY_TRUSTED_ORIGINS,\n mintRetryPolicy = DEFAULT_MINT_RETRY_POLICY,\n}: ParentBridgeOptions = {}): ParentBridge {\n const isInIframe = typeof window !== 'undefined' && window.parent !== window;\n const runtimeTrustedOrigins = useMemo(() => {\n const origins = new Set<string>();\n\n if (typeof window !== 'undefined') {\n origins.add(window.location.origin);\n }\n\n for (const trustedOrigin of trustedOrigins) {\n const normalizedOrigin = normalizeOrigin(trustedOrigin);\n if (normalizedOrigin) {\n origins.add(normalizedOrigin);\n }\n }\n\n return [...origins];\n }, [trustedOrigins]);\n\n const [state, setState] = useState<ParentBridgeState>({\n token: null,\n ...EMPTY_BRIDGE_URLS,\n hostAnswered: false,\n ready: false,\n error: null,\n });\n // Read when a mint cycle starts, so a caller's inline policy object does not\n // restart the bridge on every render.\n const mintRetryPolicyRef = useRef(mintRetryPolicy);\n mintRetryPolicyRef.current = mintRetryPolicy;\n const readySignalSent = useRef(false);\n const configReceived = useRef(false);\n // The URLs the parent has set so far: a later `athena-config` may not change them.\n const parentUrlsRef = useRef<ParentBridgeUrls>(EMPTY_BRIDGE_URLS);\n const tokenRef = useRef<string | null>(state.token);\n tokenRef.current = state.token;\n // Installed by whichever transport mode is active (iframe or Marathon).\n const renewerRef = useRef<AthenaTokenRenewer | null>(null);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n const endBridgeSpan = athenaDiagnostics.span('auth.bridge', 'auth.bridge.start', {\n mode: 'iframe',\n });\n let spanEnded = false;\n const endOnce: typeof endBridgeSpan = (name, options) => {\n if (spanEnded) return 0;\n spanEnded = true;\n return endBridgeSpan(name, options);\n };\n\n // Renewals waiting for the parent's next `athena-auth`.\n const tokenWaiters = new Set<(token: string | null) => void>();\n\n const handler = (event: MessageEvent) => {\n // Only the window that frames this app speaks for the host: a popup,\n // an opener or a sibling frame on a trusted origin does not.\n if (event.source !== window.parent) return;\n if (\n !isTrustedParentOrigin({ origin: event.origin, trustedOrigins: runtimeTrustedOrigins })\n ) {\n return;\n }\n if (!event.data || typeof event.data !== 'object') return;\n\n if (event.data.type === 'athena-config') {\n const { urls, rejected } = acceptBridgeConfigMessage({\n previous: parentUrlsRef.current,\n payload: event.data,\n parentOrigin: event.origin,\n locked: configReceived.current,\n });\n configReceived.current = true;\n parentUrlsRef.current = urls;\n for (const { field, reason } of rejected) {\n athenaDiagnostics.emit('auth.bridge.config_rejected', {\n level: 'warn',\n data: { mode: 'iframe', field, reason },\n });\n }\n setState((prev) => ({\n ...prev,\n ...urls,\n hostAnswered: true,\n // Don't set ready here — wait for athena-auth (token) or the timeout.\n // Setting ready on config alone causes a race: the thread list fires\n // before the token arrives, falling back to X-API-KEY.\n }));\n }\n\n if (event.data.type === 'athena-auth' && typeof event.data.token === 'string') {\n endOnce('auth.bridge.ready', { data: { mode: 'iframe' } });\n athenaDiagnostics.emit('auth.token.acquired', {\n level: 'debug',\n data: { source: 'iframe-postmessage' },\n });\n setState((prev) => ({\n ...prev,\n token: event.data.token,\n ready: true,\n }));\n tokenRef.current = event.data.token;\n for (const resolve of [...tokenWaiters]) resolve(event.data.token);\n }\n };\n window.addEventListener('message', handler);\n\n // A renewal asks the parent to send its current token again — the same\n // `athena-auth-ready` handshake a parent already answers — and settles on\n // the next `athena-auth`, or on the held token when none arrives in time.\n renewerRef.current = ({ force }) => {\n if (!force) return Promise.resolve(tokenRef.current);\n return new Promise<string | null>((resolve) => {\n const settle = (token: string | null) => {\n clearTimeout(timer);\n tokenWaiters.delete(settle);\n resolve(token ?? tokenRef.current);\n };\n const timer = setTimeout(() => settle(null), PARENT_TOKEN_RENEWAL_TIMEOUT_MS);\n tokenWaiters.add(settle);\n window.parent.postMessage({ type: 'athena-auth-ready' }, '*');\n });\n };\n\n if (!readySignalSent.current) {\n window.parent.postMessage({ type: 'athena-auth-ready' }, '*');\n readySignalSent.current = true;\n }\n\n const timer = setTimeout(() => {\n endOnce('auth.bridge.timeout', {\n data: {\n mode: 'iframe',\n timeout_ms: BRIDGE_TIMEOUT_MS,\n config_received: configReceived.current,\n },\n });\n setState((prev) => (prev.ready ? prev : { ...prev, ready: true }));\n }, BRIDGE_TIMEOUT_MS);\n\n return () => {\n window.removeEventListener('message', handler);\n clearTimeout(timer);\n renewerRef.current = null;\n for (const resolve of [...tokenWaiters]) resolve(null);\n };\n }, [isInIframe, runtimeTrustedOrigins]);\n\n useEffect(() => {\n if (isInIframe) return;\n if (typeof window === 'undefined') return;\n\n let cancelled = false;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n let controller: AbortController | null = null;\n let inFlight: Promise<string | null> | null = null;\n let retryWait: { timer: ReturnType<typeof setTimeout>; resolve: () => void } | null = null;\n\n const clearRefreshTimer = () => {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = null;\n }\n };\n\n const endRetryWait = () => {\n if (!retryWait) return;\n clearTimeout(retryWait.timer);\n const { resolve } = retryWait;\n retryWait = null;\n resolve();\n };\n\n /** The backoff between two attempts of one cycle; unmounting ends it at once. */\n const waitBeforeRetry = (delayMs: number) =>\n new Promise<void>((resolve) => {\n retryWait = { timer: setTimeout(endRetryWait, delayMs), resolve };\n });\n\n // The only background mint: once per token, shortly before it expires. It\n // is not rescheduled when its cycle gives up. A forced renewal that gives\n // up leaves it in place on purpose: the held token is still live, and\n // this one bounded cycle keeps a viewer connected past a brief outage.\n const scheduleRefresh = (expiresAt: unknown) => {\n clearRefreshTimer();\n const delay = getTokenRefreshDelay(expiresAt, Date.now());\n refreshTimer = setTimeout(() => {\n refreshTimer = null;\n void fetchAuth({ initial: false });\n }, delay);\n };\n\n /** One `/_athena/auth` request, classified. */\n const mintOnce = async (timeoutMs: number): Promise<MintAttempt> => {\n const requestController = new AbortController();\n controller = requestController;\n let timedOut = false;\n const requestTimer = setTimeout(() => {\n timedOut = true;\n requestController.abort();\n }, timeoutMs);\n\n try {\n const resp = await fetch('/_athena/auth', {\n credentials: 'include',\n headers: { Accept: 'application/json' },\n signal: requestController.signal,\n });\n if (cancelled) return { kind: 'cancelled' };\n // Not a Marathon origin: expected for standalone apps and local dev.\n if (resp.status === 404) return { kind: 'absent', status: resp.status };\n if (!resp.ok) {\n const hostError = await readHostError(resp);\n if (cancelled) return { kind: 'cancelled' };\n // `readHostError` swallows the abort of a stalled error body. Only a\n // retryable status becomes a timeout: a refusal (401, 403, other\n // 4xx) is known from its status and still fails after one request.\n if (timedOut && isRetryableMintStatus(resp.status)) {\n return { kind: 'transient', status: null, reason: 'timeout', hostError: null };\n }\n return isRetryableMintStatus(resp.status)\n ? { kind: 'transient', status: resp.status, reason: 'status', hostError }\n : { kind: 'refused', status: resp.status, reason: 'status', hostError };\n }\n\n let data: unknown;\n try {\n data = await resp.json();\n } catch (error) {\n if (cancelled) return { kind: 'cancelled' };\n if (timedOut) {\n return { kind: 'transient', status: null, reason: 'timeout', hostError: null, cause: error };\n }\n return { kind: 'refused', status: resp.status, reason: 'invalid_body', hostError: null };\n }\n if (cancelled) return { kind: 'cancelled' };\n // Marathon's 200 always carries a token. A 2xx without one is a\n // broken mint: it must not replace a held token or count as success.\n const token = data && typeof data === 'object' ? (data as { token?: unknown }).token : null;\n if (typeof token !== 'string' || token === '') {\n return { kind: 'refused', status: resp.status, reason: 'invalid_body', hostError: null };\n }\n return { kind: 'minted', data: data as AthenaAuthResponse };\n } catch (error) {\n if (cancelled) return { kind: 'cancelled' };\n if (timedOut) {\n return { kind: 'transient', status: null, reason: 'timeout', hostError: null, cause: error };\n }\n return { kind: 'transient', status: null, reason: 'network', hostError: null, cause: error };\n } finally {\n clearTimeout(requestTimer);\n if (controller === requestController) controller = null;\n }\n };\n\n /**\n * One bounded mint cycle: the initial acquisition (a span the provider\n * waits on) or a renewal (the scheduled refresh, a forced renewal). It\n * retries a transient failure up to `maxAttempts` requests in all, with\n * a capped, jittered backoff. On a refusal, or after the last attempt, it\n * gives up: it reports one typed error, sets `error`, keeps any token an\n * earlier mint handed out, and schedules nothing.\n */\n const runMintCycle = async ({ initial }: { initial: boolean }): Promise<string | null> => {\n const policy = mintRetryPolicyRef.current;\n const maxAttempts = Math.max(1, Math.floor(policy.maxAttempts));\n const phase = initial ? 'initial' : 'renewal';\n const endBridgeSpan = initial\n ? athenaDiagnostics.span('auth.bridge', 'auth.bridge.start', { mode: 'marathon' })\n : null;\n\n let attempts = 0;\n let lastFailure: MintFailure | null = null;\n while (attempts < maxAttempts) {\n attempts += 1;\n const outcome = await mintOnce(policy.timeoutMs);\n if (cancelled || outcome.kind === 'cancelled') return null;\n\n if (outcome.kind === 'absent') {\n endBridgeSpan?.('auth.bridge.absent', {\n data: { mode: 'marathon', status: outcome.status },\n });\n // 404 means no bridge here, so an earlier mint failure no longer\n // applies; the provider falls back to its other credentials.\n setState((prev) =>\n prev.ready && prev.error == null ? prev : { ...prev, ready: true, error: null },\n );\n return null;\n }\n\n if (outcome.kind === 'minted') {\n const { data } = outcome;\n if (endBridgeSpan) {\n endBridgeSpan('auth.bridge.ready', {\n data: { mode: 'marathon', has_token: typeof data.token === 'string', attempts },\n });\n athenaDiagnostics.emit('auth.token.acquired', {\n level: 'debug',\n data: { source: 'marathon', expires_at: data.expires_at },\n });\n } else {\n athenaDiagnostics.emit('auth.token.refreshed', {\n level: 'debug',\n data: { source: 'marathon', expires_at: data.expires_at, attempts },\n });\n }\n const token = typeof data.token === 'string' ? data.token : null;\n setState({\n token,\n ...readAuthMintUrls(data),\n hostAnswered: true,\n ready: true,\n error: null,\n });\n tokenRef.current = token;\n scheduleRefresh(data.expires_at);\n return token;\n }\n\n lastFailure = outcome;\n if (outcome.kind === 'refused' || attempts >= maxAttempts) break;\n\n const delayMs = getMintRetryDelay({ retry: attempts, policy });\n athenaDiagnostics.emit('auth.bridge.retry', {\n level: 'warn',\n data: {\n mode: 'marathon',\n phase,\n status: outcome.status,\n reason: outcome.reason,\n host_error: outcome.hostError,\n attempt: attempts,\n max_attempts: maxAttempts,\n delay_ms: delayMs,\n },\n });\n await waitBeforeRetry(delayMs);\n if (cancelled) return null;\n }\n\n if (!lastFailure) return null;\n const error = mintFailureError({ failure: lastFailure, attempts, phase });\n const failureData = {\n mode: 'marathon',\n phase,\n status: lastFailure.status,\n reason: lastFailure.reason,\n attempts,\n };\n if (endBridgeSpan) {\n endBridgeSpan(\n error.code === 'auth_bridge_timeout' ? 'auth.bridge.timeout' : 'auth.bridge.error',\n { data: failureData, error },\n );\n } else {\n athenaDiagnostics.emit('auth.token.refresh_failed', {\n level: 'error',\n data: failureData,\n error,\n });\n }\n setState((prev) => ({ ...prev, error, ready: true }));\n return null;\n };\n\n // One mint cycle at a time. The initial acquisition, a scheduled refresh\n // and forced renewals that overlap share the cycle in flight (its\n // requests, their timeouts and its backoff) instead of starting their own,\n // so concurrent callers never multiply the requests.\n const fetchAuth = (options: { initial: boolean }): Promise<string | null> => {\n inFlight ??= runMintCycle(options).finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n\n // A forced renewal mints now instead of waiting for the scheduled refresh\n // (joining a cycle already in flight), and may start a new bounded cycle\n // after one gave up. The schedule restarts from the new token's expiry.\n renewerRef.current = ({ force }) => {\n if (!force) return Promise.resolve(tokenRef.current);\n return fetchAuth({ initial: false }).then((token) => token ?? tokenRef.current);\n };\n\n void fetchAuth({ initial: true });\n\n return () => {\n cancelled = true;\n controller?.abort();\n clearRefreshTimer();\n endRetryWait();\n renewerRef.current = null;\n };\n }, [isInIframe]);\n\n const renewToken = useCallback<AthenaTokenRenewer>(\n (options) => renewerRef.current?.(options) ?? Promise.resolve(tokenRef.current),\n [],\n );\n\n return useMemo(() => ({ ...state, renewToken }), [state, renewToken]);\n}\n\n/**\n * Legacy hook — returns just the auth token from the parent bridge.\n * Prefer useParentBridge() for new code.\n */\nexport function useParentAuth(): string | null {\n return useParentBridge().token;\n}\n"],"names":["AthenaSdkError","useMemo","useState","useRef","useEffect","athenaDiagnostics","timer","useCallback"],"mappings":"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"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const errors = require("../agent-runtime/src/errors.cjs");
4
4
  function athenaStatewireErrorNotice(error) {
5
5
  if (errors.isStatewireChannelTeardown(error)) return null;
6
+ if (errors.isVoiceCommandRejection(error)) return null;
6
7
  const rejection = errors.statewireRejectionPayload(error);
7
8
  const detail = errors.statewireRejectionDetailMessage(error);
8
9
  if ((rejection == null ? void 0 : rejection.status) === 402) {
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-lifecycle.cjs","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n CONVERSATION_ARCHIVED_MESSAGE,\n isConversationArchivedRejection,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors.\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // The conversation is archived (in the trash): it takes no new turns until\n // it is restored. Not broken and not retriable — the amber \"not sent\".\n if (isConversationArchivedRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: CONVERSATION_ARCHIVED_MESSAGE,\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\n/**\n * Whether the statewire channel can take a command now: connected, or on\n * standby (attached and idle). `null` (no connection observed yet) is not.\n */\nexport function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean {\n return connection?.status === 'connected' || connection?.status === 'standby';\n}\n\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy = isStatewireChannelLive(action.connection);\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":["isStatewireChannelTeardown","statewireRejectionPayload","statewireRejectionDetailMessage","statewireRejectionCode","isLegacyThreadReadOnlyRejection","isConversationArchivedRejection","CONVERSATION_ARCHIVED_MESSAGE","COLLAB_AGENT_CHANNEL_SESSION_MISMATCH"],"mappings":";;;AA8BO,SAAS,2BACd,OACmC;AACnC,MAAIA,OAAAA,2BAA2B,KAAK,EAAG,QAAO;AAC9C,QAAM,YAAYC,OAAAA,0BAA0B,KAAK;AAGjD,QAAM,SAASC,OAAAA,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAOC,OAAAA,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAIC,OAAAA,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAIA,MAAIC,OAAAA,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAASC,OAAAA;AAAAA,MACT,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAASC,OAAAA,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,uBAAuB,YAAsD;AAC3F,UAAO,yCAAY,YAAW,gBAAe,yCAAY,YAAW;AACtE;AAEO,SAAS,0BACd,OACA,QACgC;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,UAAU,uBAAuB,OAAO,UAAU;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;;;;;"}
1
+ {"version":3,"file":"statewire-lifecycle.cjs","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n CONVERSATION_ARCHIVED_MESSAGE,\n isConversationArchivedRejection,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n isVoiceCommandRejection,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors, and for `voice/*` rejections: the voice\n * controller owns those (an end that found the session already closed is\n * not a failure, and a refused typed-in-voice send falls back to a run).\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n if (isVoiceCommandRejection(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // The conversation is archived (in the trash): it takes no new turns until\n // it is restored. Not broken and not retriable — the amber \"not sent\".\n if (isConversationArchivedRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: CONVERSATION_ARCHIVED_MESSAGE,\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\n/**\n * Whether the statewire channel can take a command now: connected, or on\n * standby (attached and idle). `null` (no connection observed yet) is not.\n */\nexport function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean {\n return connection?.status === 'connected' || connection?.status === 'standby';\n}\n\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy = isStatewireChannelLive(action.connection);\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":["isStatewireChannelTeardown","isVoiceCommandRejection","statewireRejectionPayload","statewireRejectionDetailMessage","statewireRejectionCode","isLegacyThreadReadOnlyRejection","isConversationArchivedRejection","CONVERSATION_ARCHIVED_MESSAGE","COLLAB_AGENT_CHANNEL_SESSION_MISMATCH"],"mappings":";;;AAiCO,SAAS,2BACd,OACmC;AACnC,MAAIA,OAAAA,2BAA2B,KAAK,EAAG,QAAO;AAC9C,MAAIC,OAAAA,wBAAwB,KAAK,EAAG,QAAO;AAC3C,QAAM,YAAYC,OAAAA,0BAA0B,KAAK;AAGjD,QAAM,SAASC,OAAAA,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAOC,OAAAA,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAIC,OAAAA,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAIA,MAAIC,OAAAA,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAASC,OAAAA;AAAAA,MACT,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAASC,OAAAA,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,uBAAuB,YAAsD;AAC3F,UAAO,yCAAY,YAAW,gBAAe,yCAAY,YAAW;AACtE;AAEO,SAAS,0BACd,OACA,QACgC;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,UAAU,uBAAuB,OAAO,UAAU;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;;;;;"}
@@ -14,7 +14,9 @@ export interface AthenaStatewireErrorNotice {
14
14
  /**
15
15
  * Map the statewire failure envelope to a concise, actionable notice.
16
16
  * Returns null for expected channel teardowns (thread switch, unmount),
17
- * which must not surface as errors.
17
+ * which must not surface as errors, and for `voice/*` rejections: the voice
18
+ * controller owns those (an end that found the session already closed is
19
+ * not a failure, and a refused typed-in-voice send falls back to a run).
18
20
  */
19
21
  export declare function athenaStatewireErrorNotice(error: unknown): AthenaStatewireErrorNotice | null;
20
22
  /** Shared lifecycle state for the statewire transport, provided by
@@ -1,6 +1,7 @@
1
- import { isStatewireChannelTeardown, statewireRejectionPayload, statewireRejectionDetailMessage, statewireRejectionCode, isLegacyThreadReadOnlyRejection, isConversationArchivedRejection, CONVERSATION_ARCHIVED_MESSAGE, COLLAB_AGENT_CHANNEL_SESSION_MISMATCH } from "../agent-runtime/src/errors.js";
1
+ import { isStatewireChannelTeardown, isVoiceCommandRejection, statewireRejectionPayload, statewireRejectionDetailMessage, statewireRejectionCode, isLegacyThreadReadOnlyRejection, isConversationArchivedRejection, CONVERSATION_ARCHIVED_MESSAGE, COLLAB_AGENT_CHANNEL_SESSION_MISMATCH } from "../agent-runtime/src/errors.js";
2
2
  function athenaStatewireErrorNotice(error) {
3
3
  if (isStatewireChannelTeardown(error)) return null;
4
+ if (isVoiceCommandRejection(error)) return null;
4
5
  const rejection = statewireRejectionPayload(error);
5
6
  const detail = statewireRejectionDetailMessage(error);
6
7
  if ((rejection == null ? void 0 : rejection.status) === 402) {
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-lifecycle.js","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n CONVERSATION_ARCHIVED_MESSAGE,\n isConversationArchivedRejection,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors.\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // The conversation is archived (in the trash): it takes no new turns until\n // it is restored. Not broken and not retriable — the amber \"not sent\".\n if (isConversationArchivedRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: CONVERSATION_ARCHIVED_MESSAGE,\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\n/**\n * Whether the statewire channel can take a command now: connected, or on\n * standby (attached and idle). `null` (no connection observed yet) is not.\n */\nexport function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean {\n return connection?.status === 'connected' || connection?.status === 'standby';\n}\n\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy = isStatewireChannelLive(action.connection);\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":[],"mappings":";AA8BO,SAAS,2BACd,OACmC;AACnC,MAAI,2BAA2B,KAAK,EAAG,QAAO;AAC9C,QAAM,YAAY,0BAA0B,KAAK;AAGjD,QAAM,SAAS,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAO,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAI,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAIA,MAAI,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAAS,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,uBAAuB,YAAsD;AAC3F,UAAO,yCAAY,YAAW,gBAAe,yCAAY,YAAW;AACtE;AAEO,SAAS,0BACd,OACA,QACgC;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,UAAU,uBAAuB,OAAO,UAAU;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;"}
1
+ {"version":3,"file":"statewire-lifecycle.js","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n CONVERSATION_ARCHIVED_MESSAGE,\n isConversationArchivedRejection,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n isVoiceCommandRejection,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors, and for `voice/*` rejections: the voice\n * controller owns those (an end that found the session already closed is\n * not a failure, and a refused typed-in-voice send falls back to a run).\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n if (isVoiceCommandRejection(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // The conversation is archived (in the trash): it takes no new turns until\n // it is restored. Not broken and not retriable — the amber \"not sent\".\n if (isConversationArchivedRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: CONVERSATION_ARCHIVED_MESSAGE,\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\n/**\n * Whether the statewire channel can take a command now: connected, or on\n * standby (attached and idle). `null` (no connection observed yet) is not.\n */\nexport function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean {\n return connection?.status === 'connected' || connection?.status === 'standby';\n}\n\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy = isStatewireChannelLive(action.connection);\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":[],"mappings":";AAiCO,SAAS,2BACd,OACmC;AACnC,MAAI,2BAA2B,KAAK,EAAG,QAAO;AAC9C,MAAI,wBAAwB,KAAK,EAAG,QAAO;AAC3C,QAAM,YAAY,0BAA0B,KAAK;AAGjD,QAAM,SAAS,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAO,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAI,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAIA,MAAI,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAAS,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,uBAAuB,YAAsD;AAC3F,UAAO,yCAAY,YAAW,gBAAe,yCAAY,YAAW;AACtE;AAEO,SAAS,0BACd,OACA,QACgC;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,UAAU,uBAAuB,OAAO,UAAU;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;"}
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
3
+ const require$$0 = require("react");
4
4
  const STATEWIRE_SERVER_LANE_PENDING = Object.freeze({
5
5
  landed: false,
6
6
  config: null
7
7
  });
8
- const AthenaStatewireServerLaneContext = react.createContext(
8
+ const AthenaStatewireServerLaneContext = require$$0.createContext(
9
9
  null
10
10
  );
11
11
  function nextServerLane({
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-server-lane-context.cjs","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the\n * thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.\n */\nexport interface AthenaStatewireServerLane {\n /** `true` once this attach's snapshot from the host has arrived. */\n landed: boolean;\n /** The lane in that snapshot (and every later host frame), `null` at version 0. */\n config: DeepAgentServerConfig | null;\n}\n\nexport const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane = Object.freeze({\n landed: false,\n config: null,\n});\n\n/** Provided by `AthenaProvider` around the host's children, per attached thread. */\nexport const AthenaStatewireServerLaneContext = createContext<AthenaStatewireServerLane | null>(\n null,\n);\n\n/**\n * The next lane value for a host frame: the same object while the lane's\n * version is unchanged, so a frame that moved only messages (every streamed\n * token) re-renders nothing.\n */\nexport function nextServerLane({\n previous,\n config,\n}: {\n previous: AthenaStatewireServerLane;\n config: DeepAgentServerConfig | null;\n}): AthenaStatewireServerLane {\n if (previous.landed && (previous.config?.version ?? 0) === (config?.version ?? 0)) {\n return previous;\n }\n return { landed: true, config };\n}\n"],"names":["createContext"],"mappings":";;;AAqBO,MAAM,gCAA2D,OAAO,OAAO;AAAA,EACpF,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAGM,MAAM,mCAAmCA,MAAAA;AAAAA,EAC9C;AACF;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAG8B;;AAC5B,MAAI,SAAS,aAAW,cAAS,WAAT,mBAAiB,YAAW,SAAQ,iCAAQ,YAAW,IAAI;AACjF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,OAAA;AACzB;;;;"}
1
+ {"version":3,"file":"statewire-server-lane-context.cjs","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the\n * thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.\n */\nexport interface AthenaStatewireServerLane {\n /** `true` once this attach's snapshot from the host has arrived. */\n landed: boolean;\n /** The lane in that snapshot (and every later host frame), `null` at version 0. */\n config: DeepAgentServerConfig | null;\n}\n\nexport const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane = Object.freeze({\n landed: false,\n config: null,\n});\n\n/** Provided by `AthenaProvider` around the host's children, per attached thread. */\nexport const AthenaStatewireServerLaneContext = createContext<AthenaStatewireServerLane | null>(\n null,\n);\n\n/**\n * The next lane value for a host frame: the same object while the lane's\n * version is unchanged, so a frame that moved only messages (every streamed\n * token) re-renders nothing.\n */\nexport function nextServerLane({\n previous,\n config,\n}: {\n previous: AthenaStatewireServerLane;\n config: DeepAgentServerConfig | null;\n}): AthenaStatewireServerLane {\n if (previous.landed && (previous.config?.version ?? 0) === (config?.version ?? 0)) {\n return previous;\n }\n return { landed: true, config };\n}\n"],"names":["createContext"],"mappings":";;;AAqBO,MAAM,gCAA2D,OAAO,OAAO;AAAA,EACpF,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAGM,MAAM,mCAAmCA,WAAAA;AAAAA,EAC9C;AACF;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAG8B;;AAC5B,MAAI,SAAS,aAAW,cAAS,WAAT,mBAAiB,YAAW,SAAQ,iCAAQ,YAAW,IAAI;AACjF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,OAAA;AACzB;;;;"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
3
+ const require$$0 = require("react");
4
4
  function createStatewireSessionLaneGate({
5
5
  pending
6
6
  }) {
@@ -30,16 +30,16 @@ function createStatewireSessionLaneGate({
30
30
  }
31
31
  };
32
32
  }
33
- const StatewireSessionLaneContext = react.createContext(null);
33
+ const StatewireSessionLaneContext = require$$0.createContext(null);
34
34
  function useStatewireSessionLane() {
35
- return react.useContext(StatewireSessionLaneContext);
35
+ return require$$0.useContext(StatewireSessionLaneContext);
36
36
  }
37
37
  const subscribeToNothing = () => () => {
38
38
  };
39
39
  function useStatewireSessionLanePending() {
40
40
  const lane = useStatewireSessionLane();
41
41
  const read = () => (lane == null ? void 0 : lane.isPending()) ?? false;
42
- return react.useSyncExternalStore((lane == null ? void 0 : lane.subscribe) ?? subscribeToNothing, read, read);
42
+ return require$$0.useSyncExternalStore((lane == null ? void 0 : lane.subscribe) ?? subscribeToNothing, read, read);
43
43
  }
44
44
  exports.StatewireSessionLaneContext = StatewireSessionLaneContext;
45
45
  exports.createStatewireSessionLaneGate = createStatewireSessionLaneGate;
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-session-lane.cjs","sources":["../../src/runtime/statewire-session-lane.ts"],"sourcesContent":["import { createContext, useContext, useSyncExternalStore } from 'react';\n\n/**\n * Whether the chat's persisted command lane is known. The lane is scoped by the\n * signed-in principal (`statewireSessionPrincipal`), so while the sign-in\n * provider above is still resolving who is signed in the lane is pending: the\n * thread's transport is parked and a command dispatched into it is refused\n * unsent. A send made meanwhile waits on this instead and goes out on the\n * signed-in user's lane once it is known.\n */\nexport interface StatewireSessionLane {\n /** True while the lane waits for the signed-in principal. */\n isPending: () => boolean;\n /** Resolves once the lane is known (at once when it already is). */\n whenKnown: () => Promise<void>;\n /** Called whenever `isPending()` changes. */\n subscribe: (listener: () => void) => () => void;\n}\n\n/** The provider's side of {@link StatewireSessionLane}: the mounted runtime reports its lane. */\nexport interface StatewireSessionLaneGate extends StatewireSessionLane {\n /** Report the lane of the runtime that has just committed it. */\n setPending: (pending: boolean) => void;\n}\n\nexport function createStatewireSessionLaneGate({\n pending,\n}: {\n pending: boolean;\n}): StatewireSessionLaneGate {\n let current = pending;\n let waiters: Array<() => void> = [];\n const listeners = new Set<() => void>();\n return {\n isPending: () => current,\n whenKnown: () =>\n current\n ? new Promise<void>((resolve) => {\n waiters.push(resolve);\n })\n : Promise.resolve(),\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n setPending: (next) => {\n if (next === current) return;\n current = next;\n if (!next) {\n const known = waiters;\n waiters = [];\n for (const resolve of known) resolve();\n }\n for (const listener of [...listeners]) listener();\n },\n };\n}\n\nexport const StatewireSessionLaneContext = createContext<StatewireSessionLane | null>(null);\n\n/** The provider's session lane, or `null` outside `AthenaProvider` (no lane to wait for). */\nexport function useStatewireSessionLane(): StatewireSessionLane | null {\n return useContext(StatewireSessionLaneContext);\n}\n\nconst subscribeToNothing = (): (() => void) => () => {};\n\n/** Whether the provider's session lane still waits for the signed-in principal (`false` outside one). */\nexport function useStatewireSessionLanePending(): boolean {\n const lane = useStatewireSessionLane();\n const read = () => lane?.isPending() ?? false;\n return useSyncExternalStore(lane?.subscribe ?? subscribeToNothing, read, read);\n}\n"],"names":["createContext","useContext","useSyncExternalStore"],"mappings":";;;AAyBO,SAAS,+BAA+B;AAAA,EAC7C;AACF,GAE6B;AAC3B,MAAI,UAAU;AACd,MAAI,UAA6B,CAAA;AACjC,QAAM,gCAAgB,IAAA;AACtB,SAAO;AAAA,IACL,WAAW,MAAM;AAAA,IACjB,WAAW,MACT,UACI,IAAI,QAAc,CAAC,YAAY;AAC7B,cAAQ,KAAK,OAAO;AAAA,IACtB,CAAC,IACD,QAAQ,QAAA;AAAA,IACd,WAAW,CAAC,aAAa;AACvB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,YAAY,CAAC,SAAS;AACpB,UAAI,SAAS,QAAS;AACtB,gBAAU;AACV,UAAI,CAAC,MAAM;AACT,cAAM,QAAQ;AACd,kBAAU,CAAA;AACV,mBAAW,WAAW,MAAO,SAAA;AAAA,MAC/B;AACA,iBAAW,YAAY,CAAC,GAAG,SAAS,EAAG,UAAA;AAAA,IACzC;AAAA,EAAA;AAEJ;AAEO,MAAM,8BAA8BA,MAAAA,cAA2C,IAAI;AAGnF,SAAS,0BAAuD;AACrE,SAAOC,MAAAA,WAAW,2BAA2B;AAC/C;AAEA,MAAM,qBAAqB,MAAoB,MAAM;AAAC;AAG/C,SAAS,iCAA0C;AACxD,QAAM,OAAO,wBAAA;AACb,QAAM,OAAO,OAAM,6BAAM,gBAAe;AACxC,SAAOC,MAAAA,sBAAqB,6BAAM,cAAa,oBAAoB,MAAM,IAAI;AAC/E;;;;;"}
1
+ {"version":3,"file":"statewire-session-lane.cjs","sources":["../../src/runtime/statewire-session-lane.ts"],"sourcesContent":["import { createContext, useContext, useSyncExternalStore } from 'react';\n\n/**\n * Whether the chat's persisted command lane is known. The lane is scoped by the\n * signed-in principal (`statewireSessionPrincipal`), so while the sign-in\n * provider above is still resolving who is signed in the lane is pending: the\n * thread's transport is parked and a command dispatched into it is refused\n * unsent. A send made meanwhile waits on this instead and goes out on the\n * signed-in user's lane once it is known.\n */\nexport interface StatewireSessionLane {\n /** True while the lane waits for the signed-in principal. */\n isPending: () => boolean;\n /** Resolves once the lane is known (at once when it already is). */\n whenKnown: () => Promise<void>;\n /** Called whenever `isPending()` changes. */\n subscribe: (listener: () => void) => () => void;\n}\n\n/** The provider's side of {@link StatewireSessionLane}: the mounted runtime reports its lane. */\nexport interface StatewireSessionLaneGate extends StatewireSessionLane {\n /** Report the lane of the runtime that has just committed it. */\n setPending: (pending: boolean) => void;\n}\n\nexport function createStatewireSessionLaneGate({\n pending,\n}: {\n pending: boolean;\n}): StatewireSessionLaneGate {\n let current = pending;\n let waiters: Array<() => void> = [];\n const listeners = new Set<() => void>();\n return {\n isPending: () => current,\n whenKnown: () =>\n current\n ? new Promise<void>((resolve) => {\n waiters.push(resolve);\n })\n : Promise.resolve(),\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n setPending: (next) => {\n if (next === current) return;\n current = next;\n if (!next) {\n const known = waiters;\n waiters = [];\n for (const resolve of known) resolve();\n }\n for (const listener of [...listeners]) listener();\n },\n };\n}\n\nexport const StatewireSessionLaneContext = createContext<StatewireSessionLane | null>(null);\n\n/** The provider's session lane, or `null` outside `AthenaProvider` (no lane to wait for). */\nexport function useStatewireSessionLane(): StatewireSessionLane | null {\n return useContext(StatewireSessionLaneContext);\n}\n\nconst subscribeToNothing = (): (() => void) => () => {};\n\n/** Whether the provider's session lane still waits for the signed-in principal (`false` outside one). */\nexport function useStatewireSessionLanePending(): boolean {\n const lane = useStatewireSessionLane();\n const read = () => lane?.isPending() ?? false;\n return useSyncExternalStore(lane?.subscribe ?? subscribeToNothing, read, read);\n}\n"],"names":["createContext","useContext","useSyncExternalStore"],"mappings":";;;AAyBO,SAAS,+BAA+B;AAAA,EAC7C;AACF,GAE6B;AAC3B,MAAI,UAAU;AACd,MAAI,UAA6B,CAAA;AACjC,QAAM,gCAAgB,IAAA;AACtB,SAAO;AAAA,IACL,WAAW,MAAM;AAAA,IACjB,WAAW,MACT,UACI,IAAI,QAAc,CAAC,YAAY;AAC7B,cAAQ,KAAK,OAAO;AAAA,IACtB,CAAC,IACD,QAAQ,QAAA;AAAA,IACd,WAAW,CAAC,aAAa;AACvB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,YAAY,CAAC,SAAS;AACpB,UAAI,SAAS,QAAS;AACtB,gBAAU;AACV,UAAI,CAAC,MAAM;AACT,cAAM,QAAQ;AACd,kBAAU,CAAA;AACV,mBAAW,WAAW,MAAO,SAAA;AAAA,MAC/B;AACA,iBAAW,YAAY,CAAC,GAAG,SAAS,EAAG,UAAA;AAAA,IACzC;AAAA,EAAA;AAEJ;AAEO,MAAM,8BAA8BA,WAAAA,cAA2C,IAAI;AAGnF,SAAS,0BAAuD;AACrE,SAAOC,WAAAA,WAAW,2BAA2B;AAC/C;AAEA,MAAM,qBAAqB,MAAoB,MAAM;AAAC;AAG/C,SAAS,iCAA0C;AACxD,QAAM,OAAO,wBAAA;AACb,QAAM,OAAO,OAAM,6BAAM,gBAAe;AACxC,SAAOC,WAAAA,sBAAqB,6BAAM,cAAa,oBAAoB,MAAM,IAAI;AAC/E;;;;;"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react$1 = require("@assistant-ui/react");
4
- const react = require("react");
3
+ const react = require("@assistant-ui/react");
4
+ const require$$0 = require("react");
5
5
  const AthenaAuthContext = require("../auth/AthenaAuthContext.cjs");
6
6
  const statewireClientTools = require("../chat/statewire-client-tools.cjs");
7
7
  const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
@@ -20,7 +20,7 @@ const ATHENA_SDK_MESSAGE_WINDOW = {
20
20
  const EMPTY_TOOLKIT = {};
21
21
  const EMPTY_TOOL_IDS = [];
22
22
  function useStatewireClientTools(frontendToolkit) {
23
- return react.useMemo(
23
+ return require$$0.useMemo(
24
24
  () => statewireClientTools.collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),
25
25
  [frontendToolkit]
26
26
  );
@@ -53,14 +53,15 @@ function useAthenaStatewireRuntime(config) {
53
53
  onConnectionChange,
54
54
  onRawConnectionChange,
55
55
  onRunningChange,
56
+ onSessionPersistedChange,
56
57
  onCommandChange,
57
58
  onServerState
58
59
  } = config;
59
60
  statewireRunConfig.resolveAgentProp({ agent });
60
61
  const clientTools = useStatewireClientTools(frontendToolkit);
61
- const principal = statewireSessionKey.statewireSessionPrincipal(react.useContext(AthenaAuthContext.AthenaAuthContext));
62
- const attachSpanRef = react.useRef(null);
63
- const attachThreadRef = react.useRef(null);
62
+ const principal = statewireSessionKey.statewireSessionPrincipal(require$$0.useContext(AthenaAuthContext.AthenaAuthContext));
63
+ const attachSpanRef = require$$0.useRef(null);
64
+ const attachThreadRef = require$$0.useRef(null);
64
65
  if (attachThreadRef.current !== threadId) {
65
66
  attachThreadRef.current = threadId;
66
67
  attachSpanRef.current = athenaDiagnostics.athenaDiagnostics.span(
@@ -84,8 +85,8 @@ function useAthenaStatewireRuntime(config) {
84
85
  clientTools: statewireClientTools.statewireClientToolWireEntries(clientTools)
85
86
  });
86
87
  const runConfigKey = JSON.stringify(runConfigValue);
87
- const auiTools = react.useMemo(() => react$1.Tools({ toolkit: frontendToolkit }), [frontendToolkit]);
88
- const useSdkClient = (thread) => react$1.useAui({ thread, tools: auiTools });
88
+ const auiTools = require$$0.useMemo(() => react.Tools({ toolkit: frontendToolkit }), [frontendToolkit]);
89
+ const useSdkClient = (thread) => react.useAui({ thread, tools: auiTools });
89
90
  return useDeepAgentRuntime.useDeepAgentRuntime({
90
91
  surface: "AthenaSDK",
91
92
  threadId,
@@ -158,6 +159,7 @@ function useAthenaStatewireRuntime(config) {
158
159
  },
159
160
  onRawConnectionChange,
160
161
  onRunningChange,
162
+ onSessionPersistedChange,
161
163
  ...onCommandChange && { onCommandChange },
162
164
  // Each model-context notification pulls the latest getter through the
163
165
  // core's per-render ref; the value-stable key re-registers (and so
@@ -1 +1 @@
1
- {"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier steps\n * on request, as `AthenaChat`'s subagent card does (\"Load earlier steps\").\n * When true, its attaches declare the deep-agent lane-cut contract\n * (protocol 2): the host sends a finished subagent's card cut to its newest\n * steps, as it sends a running one, and the card reads the rest. Default\n * `false`, so a chat that does not page lanes declares the default contract\n * and finished lanes arrive whole; a host whose `AthenaChat` renders every\n * `task` call in the subagent card turns it on through `AthenaProvider`'s\n * `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onCommandChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n session:\n principal === null\n ? { kind: 'pending' }\n : {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // card (`SubagentTaskToolUI`) shows.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","statewireSessionPrincipal","useContext","AthenaAuthContext","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","statewireSessionKey","createSubagentTranscriptConversionCache","withStagedComposerMarkdown","isDeepAgentHostState","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
1
+ {"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier steps\n * on request, as `AthenaChat`'s subagent card does (\"Load earlier steps\").\n * When true, its attaches declare the deep-agent lane-cut contract\n * (protocol 2): the host sends a finished subagent's card cut to its newest\n * steps, as it sends a running one, and the card reads the rest. Default\n * `false`, so a chat that does not page lanes declares the default contract\n * and finished lanes arrive whole; a host whose `AthenaChat` renders every\n * `task` call in the subagent card turns it on through `AthenaProvider`'s\n * `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n session:\n principal === null\n ? { kind: 'pending' }\n : {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // card (`SubagentTaskToolUI`) shows.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","statewireSessionPrincipal","useContext","AthenaAuthContext","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","statewireSessionKey","createSubagentTranscriptConversionCache","withStagedComposerMarkdown","isDeepAgentHostState","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
@@ -92,6 +92,8 @@ export interface AthenaStatewireRuntimeConfig {
92
92
  onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];
93
93
  /** Notified when a run starts/stops. */
94
94
  onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];
95
+ /** Core's paired session-asset existence verdict, including remembered/unknown state. */
96
+ onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];
95
97
  /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */
96
98
  onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];
97
99
  /**