@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":"quota-safe-local-storage-session.cjs","sources":["../../../../agent-runtime/src/quota-safe-local-storage-session.ts"],"sourcesContent":["import { resource, useResource } from \"@assistant-ui/tap\";\nimport type { StatewireClient, StatewireProtocol } from \"statewire\";\nimport { KeyValueSessionStorage } from \"statewire/storage\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport {\n type DeepAgentSessionLaneScope,\n isSameSessionLaneScope,\n} from \"./session-lane-scope\";\nimport { DEEP_AGENT_STATEWIRE_PROTOCOL } from \"./statewire-transport\";\n\nconst SESSION_PREFIX = \"aui:statewire-session:\";\nconst SESSION_LOCK_PREFIX = \"aui:statewire-session-lock:\";\nconst SESSION_ACTIVE_PREFIX = \"aui:statewire-session-active:\";\nconst DAY_MS = 24 * 60 * 60 * 1000;\n/** The stored-record formats the statewire this build ships reads (it writes 3). */\nconst READABLE_STORAGE_VERSIONS: ReadonlySet<unknown> = new Set([1, 2, 3]);\n\n/** Structural view of the browser storage global — this package compiles\n * without the DOM lib (React Native honesty; see `globals.d.ts`). */\ntype StorageLike = {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n key(index: number): string | null;\n readonly length: number;\n};\n\ntype LockGrant = object | null;\n\n/** The Web Locks API surface the session uses (`navigator.locks`). */\ntype LockManagerLike = {\n request<T>(\n name: string,\n callback: (lock: LockGrant) => T | Promise<T>\n ): Promise<T>;\n request<T>(\n name: string,\n options: { mode?: \"shared\" | \"exclusive\"; ifAvailable?: boolean },\n callback: (lock: LockGrant) => T | Promise<T>\n ): Promise<T>;\n};\n\ntype StorageEventLike = { key: string | null };\n\ntype BrowserGlobals = {\n localStorage?: StorageLike;\n navigator?: { locks?: LockManagerLike };\n addEventListener?: (\n type: \"storage\",\n listener: (event: StorageEventLike) => void\n ) => void;\n removeEventListener?: (\n type: \"storage\",\n listener: (event: StorageEventLike) => void\n ) => void;\n};\n\nconst browserGlobals = globalThis as BrowserGlobals;\n\n/** A persisted session record: per-lane failed entries (a pre-lane record carried them at the root). */\ntype SessionRecordLike = {\n failed?: unknown;\n lanes?: Record<string, { failed?: unknown } | null | undefined> | null;\n};\n\nexport function readPersistedFailedSendStamps(\n sessionKey: string\n): ReadonlyMap<string, number> | null {\n const storage = browserGlobals.localStorage;\n if (!storage) return null;\n let record: SessionRecordLike | null;\n try {\n const raw = storage.getItem(SESSION_PREFIX + sessionKey);\n record =\n raw === null ? null : (JSON.parse(raw) as SessionRecordLike | null);\n } catch {\n return null;\n }\n return readFailedSendStampsFromRecord(record);\n}\n\n/**\n * Send stamps (message id → epoch ms of the original send) off an already\n * loaded session record's failed lane — the storage-agnostic half of\n * {@link readPersistedFailedSendStamps}, for hosts whose session store is not\n * localStorage (the React Native AsyncStorage-backed store reads its record\n * synchronously through `SessionStorage.load()`).\n *\n * Returns `null` for no record (every failed entry then counts as fresh) and\n * an empty map for a record without failures.\n */\nexport function readFailedSendStampsFromRecord(\n record: SessionRecordLike | null | undefined\n): ReadonlyMap<string, number> | null {\n if (!record || typeof record !== \"object\") return null;\n const stamps = new Map<string, number>();\n const lanes =\n record.lanes && typeof record.lanes === \"object\" ? record.lanes : {};\n const failed = [\n ...(Array.isArray(record.failed) ? record.failed : []),\n ...Object.values(lanes).flatMap((lane) =>\n Array.isArray(lane?.failed) ? lane.failed : []\n ),\n ];\n for (const entry of failed) {\n const failed = entry as {\n ts?: unknown;\n params?: readonly { message?: { id?: unknown } }[];\n } | null;\n const messageId = failed?.params?.[0]?.message?.id;\n if (typeof messageId === \"string\" && typeof failed?.ts === \"number\") {\n stamps.set(messageId, failed.ts);\n }\n }\n return stamps;\n}\n\n/** A storage operation the session survived by degrading instead of failing. */\nexport type SessionStorageDegradation = {\n operation:\n | \"getItem\"\n | \"setItem\"\n | \"removeItem\"\n | \"getAllKeys\"\n | \"withUnused\"\n /** The lock manager refused the transaction fence; it ran unfenced. */\n | \"lock\"\n /**\n * The stored record is one this build cannot read (not JSON, or a newer\n * storage version): served as absent, and the key is shielded from being\n * overwritten so the record survives this tab.\n */\n | \"record\"\n /** statewire's own storage failure (a structurally invalid stored record). */\n | \"session\"\n /**\n * Queued commands persisted by an earlier statewire build no longer fit\n * the current wire/protocol range: parked in the lane's failed list (the\n * send-recovery sweep re-dispatches them) instead of blocking the mount.\n */\n | \"migrate\";\n key: string;\n error: unknown;\n};\n\ntype ProducedRange = NonNullable<StatewireClient.SessionCommand[\"produced\"]>;\n\nconst inRange = (value: string, range: StatewireProtocol.Range) =>\n value >= (range.minVersion ?? range.version) && value <= range.version;\n\n/** Mirrors statewire's own stored-command compatibility check. */\nconst storedCommandCompatible = (\n protocol: string,\n command: StatewireClient.SessionCommand,\n current: ProducedRange\n): boolean => {\n if (\n !command.produced ||\n !inRange(command.produced.wire.version, current.wire)\n )\n return false;\n if (current.protocols === \"*\") return true;\n if (command.produced.protocols === \"*\") return false;\n const produced = command.produced.protocols.find((p) => p.name === protocol);\n const offer = current.protocols.find((p) => p.name === protocol);\n return (\n produced !== undefined &&\n offer !== undefined &&\n inRange(produced.version, offer)\n );\n};\n\n/**\n * The oldest wire whose stored statements the current client still replays.\n * Bundled clients before #45143 offered 2026-09-13 through 2026-09-30 and\n * stamped every queued statement with 2026-09-13. The durable statement grammar\n * (protocol, method, params, meta, seq) is the same on 2026-09-30; only\n * frame-level context differs. So those statements ride the current wire\n * unchanged, while the network offer stays native 2026-09-30 only.\n */\nexport const STORED_STATEMENT_WIRE_FLOOR = \"2026-09-13\";\n\n/** A stored command the current wire replays as-is: re-stamp, don't park. */\nconst replayableOnCurrentWire = (\n protocol: string,\n command: StatewireClient.SessionCommand,\n current: ProducedRange\n): boolean =>\n command.produced !== undefined &&\n inRange(command.produced.wire.version, {\n version: current.wire.version,\n minVersion: STORED_STATEMENT_WIRE_FLOOR,\n }) &&\n storedCommandCompatible(\n protocol,\n { ...command, produced: { ...command.produced, wire: current.wire } },\n current\n );\n\n/**\n * statewire's `migrate` for a record whose queued commands were produced by\n * an earlier build. A command whose statement the current wire still replays\n * ({@link STORED_STATEMENT_WIRE_FLOOR}: an approval's `run/input` saved by a\n * previous bundled client, say) stays queued, re-stamped with the current\n * range, so it is delivered with its original seq. Every other incompatible\n * command leaves its lane's queue and is\n * retained as a `lost`/`session-lost` failed send re-stamped with the current\n * range. Client identity, lane clocks, compatible commands and existing failed\n * history are untouched, so the mount proceeds and the send-recovery sweep\n * (or the user, via the failed-send UI) re-dispatches the parked sends under\n * the negotiated format instead of the runtime throwing before it dials.\n *\n * Returns the record itself when nothing needed migrating, and the count of\n * parked commands otherwise.\n */\nexport function parkIncompatibleSessionCommands(\n record: StatewireClient.SessionRecord,\n current: ProducedRange,\n now: number = Date.now()\n): { record: StatewireClient.SessionRecord; parked: number; restamped: number } {\n let parked = 0;\n let restamped = 0;\n const lanes: Record<string, StatewireClient.SessionLane> = {};\n for (const [protocol, lane] of Object.entries(record.lanes)) {\n const kept: StatewireClient.SessionCommand[] = [];\n const failed: StatewireClient.FailedCommand[] = [];\n let laneRestamped = 0;\n for (const command of lane.commands) {\n if (storedCommandCompatible(protocol, command, current)) {\n kept.push(command);\n continue;\n }\n if (replayableOnCurrentWire(protocol, command, current)) {\n kept.push({ ...command, produced: current });\n laneRestamped += 1;\n continue;\n }\n failed.push({\n protocol,\n produced: current,\n command: command.method,\n params: command.params,\n ...(command.meta !== undefined && { meta: command.meta }),\n failure: { fate: \"lost\", cause: \"session-lost\" },\n ts: now,\n seq: command.seq,\n });\n }\n parked += failed.length;\n restamped += laneRestamped;\n lanes[protocol] =\n failed.length === 0 && laneRestamped === 0\n ? lane\n : {\n ...lane,\n commands: kept,\n ...((failed.length > 0 || lane.failed !== undefined) && {\n failed: [...(lane.failed ?? []), ...failed],\n }),\n };\n }\n return parked === 0 && restamped === 0\n ? { record, parked, restamped }\n : { record: { ...record, lanes }, parked, restamped };\n}\n\n/**\n * Whether `error` is the browser refusing a write for lack of room, under\n * every name the engines use — `QuotaExceededError` (Chromium, WebKit, current\n * Firefox), `NS_ERROR_DOM_QUOTA_REACHED` (older Firefox), the legacy\n * `DOMException` codes 22 (WebKit) and 1014 (Firefox) — or a plain error whose\n * message carries one of those (storage proxies and WebViews rewrap the\n * exception). Olympus's `isStorageQuotaError` recognises the same set; the two\n * stay in step.\n */\nexport function isStorageQuotaError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n const { name, code, message } = error as {\n name?: unknown;\n code?: unknown;\n message?: unknown;\n };\n return (\n name === \"QuotaExceededError\" ||\n name === \"NS_ERROR_DOM_QUOTA_REACHED\" ||\n code === 22 ||\n code === 1014 ||\n (typeof message === \"string\" &&\n /exceeded the quota|quotaexceedederror|ns_error_dom_quota_reached/i.test(\n message\n ))\n );\n}\n\n/** The one quota shape statewire's retention sweep recognises. */\nfunction asStatewireQuotaError(error: unknown): Error {\n if (error instanceof Error && error.name === \"QuotaExceededError\")\n return error;\n const normalized = new Error(\n error instanceof Error ? error.message : \"storage quota exceeded\"\n );\n normalized.name = \"QuotaExceededError\";\n return normalized;\n}\n\n/**\n * Why `raw` is a stored record this build cannot read, or `undefined` when it\n * may be one. Mirrors the two decode failures statewire raises for a record it\n * cannot read — invalid JSON, and a `statewireStorageVersion` newer than the\n * ones this build's statewire decodes (a tab left open across a\n * statewire upgrade, reading the record a newer tab keeps) — because statewire\n * throws those out of the resource at mount instead of treating the record as\n * absent. A structurally invalid record of the right version still fails\n * inside statewire.\n */\nfunction unreadableRecord(raw: string): Error | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n return error instanceof Error\n ? error\n : new Error(\"stored session record is not JSON\");\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return new Error(\"stored session record is not an object\");\n }\n const version = (parsed as { statewireStorageVersion?: unknown })\n .statewireStorageVersion;\n if (version !== undefined && !READABLE_STORAGE_VERSIONS.has(version)) {\n return new Error(\n `stored session record uses storage version ${String(version)}`\n );\n }\n return undefined;\n}\n\ntype SyncBackend = {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n getAllKeys: () => readonly string[];\n withUnused: (key: string, action: () => Promise<void>) => Promise<void>;\n};\n\n/**\n * The browser backend `@assistant-ui/react-statewire`'s `LocalStorageSession`\n * uses, reproduced here because that resource does not take a backend: raw\n * `localStorage`, with retention cleanup fenced by the same Web Locks so a\n * sweep never removes a record another tab is actively sharing.\n */\nfunction browserBackend({\n storage,\n locks,\n}: {\n storage: StorageLike;\n locks: LockManagerLike;\n}): SyncBackend {\n return {\n getItem: (key) => storage.getItem(key),\n setItem: (key, value) => storage.setItem(key, value),\n removeItem: (key) => storage.removeItem(key),\n getAllKeys: () =>\n Array.from({ length: storage.length }, (_, index) =>\n storage.key(index)\n ).filter((key): key is string => key !== null),\n withUnused: async (key, action) => {\n await locks.request(\n SESSION_ACTIVE_PREFIX + key,\n { ifAvailable: true },\n async (active) => {\n if (active === null) return;\n await locks.request(\n SESSION_LOCK_PREFIX + key.slice(SESSION_PREFIX.length),\n { ifAvailable: true },\n async (lock) => {\n if (lock === null) return;\n await action();\n }\n );\n }\n );\n },\n };\n}\n\n/**\n * Wraps a synchronous key-value backend so a failing origin degrades the\n * session to memory-only persistence instead of stopping the connection.\n *\n * statewire's session storage latches the first unrecognised write failure\n * and from then on rejects every send (`stopped/storage-error`, \"session\n * storage failed\" on the connection chip). It only recovers a\n * `QuotaExceededError` by that exact name — sweeping old session records and\n * retrying the write once — and latches again when the retry fails too. Here\n * the first quota failure per key is surfaced under that name so the sweep\n * runs; the retry that follows it and every other storage failure are absorbed\n * and reported through `onDegraded`, so chat keeps working.\n *\n * An absorbed write is kept in an in-memory overlay that `getItem` serves\n * first: statewire re-reads the record through `load()` on every shared-mode\n * transaction, so a stale persisted copy would otherwise win back its old\n * `nextSeq`, `clientId` and command journal. The overlay is per tab — another\n * tab sharing the thread still reads the last persisted copy, which is the\n * memory-only degradation this backend exists to allow. A later successful\n * write clears the overlay entry.\n *\n * A key whose read threw, or whose stored value this build cannot read (see\n * {@link unreadableRecord}), is served as absent and shielded: writes to it\n * stay in the overlay for good, so a fresh lane minted over an unreadable\n * record never overwrites what another tab or a newer build persisted.\n */\nexport function quotaTolerantBackend({\n inner,\n onDegraded,\n}: {\n inner: SyncBackend;\n onDegraded: (degradation: SessionStorageDegradation) => void;\n}): SyncBackend & KeyValueSessionStorage.Backend {\n // Keys whose write already surfaced a quota error to statewire: until a\n // write succeeds again, later failures on the key are absorbed instead of\n // surfaced, or every save would re-run statewire's sweep (which evicts\n // other threads' idle records) and the failure would latch on the retry.\n const quotaSurfaced = new Set<string>();\n // Absorbed writes, served ahead of the backend (see the function docs).\n const overlay = new Map<string, string>();\n // Keys served as absent and never written through (see the function docs).\n const shielded = new Set<string>();\n // statewire re-reads and re-decodes the record on every transaction; the\n // readability check is memoised on the raw string so it costs one string\n // comparison per read, not a second parse.\n const checked = new Map<\n string,\n { raw: string; verdict: Error | undefined }\n >();\n const readable = (key: string, raw: string): Error | undefined => {\n const previous = checked.get(key);\n if (previous !== undefined && previous.raw === raw) return previous.verdict;\n const verdict = unreadableRecord(raw);\n checked.set(key, { raw, verdict });\n return verdict;\n };\n return {\n getItem: (key) => {\n const shadowed = overlay.get(key);\n if (shadowed !== undefined) return shadowed;\n if (shielded.has(key)) return null;\n let raw: string | null;\n try {\n raw = inner.getItem(key);\n } catch (error) {\n shielded.add(key);\n onDegraded({ operation: \"getItem\", key, error });\n return null;\n }\n if (raw === null) return null;\n const unreadable = readable(key, raw);\n if (unreadable === undefined) return raw;\n shielded.add(key);\n onDegraded({ operation: \"record\", key, error: unreadable });\n return null;\n },\n setItem: (key, value) => {\n if (shielded.has(key)) {\n overlay.set(key, value);\n return;\n }\n try {\n inner.setItem(key, value);\n overlay.delete(key);\n quotaSurfaced.delete(key);\n } catch (error) {\n if (isStorageQuotaError(error) && !quotaSurfaced.has(key)) {\n quotaSurfaced.add(key);\n throw asStatewireQuotaError(error);\n }\n overlay.set(key, value);\n onDegraded({ operation: \"setItem\", key, error });\n }\n },\n removeItem: (key) => {\n overlay.delete(key);\n if (shielded.has(key)) return;\n try {\n inner.removeItem(key);\n } catch (error) {\n onDegraded({ operation: \"removeItem\", key, error });\n }\n },\n getAllKeys: () => {\n const keys = new Set<string>(overlay.keys());\n try {\n for (const key of inner.getAllKeys()) keys.add(key);\n } catch (error) {\n onDegraded({ operation: \"getAllKeys\", key: \"\", error });\n }\n return [...keys];\n },\n withUnused: async (key, action) => {\n try {\n await inner.withUnused(key, action);\n } catch (error) {\n onDegraded({ operation: \"withUnused\", key, error });\n }\n },\n };\n}\n\n/** A stored record's save stamp, or `undefined` when it carries none. */\nfunction savedAtOf(raw: string | null): number | undefined {\n if (raw === null) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof parsed !== \"object\" || parsed === null) return undefined;\n const { savedAt, updatedAt } = parsed as {\n savedAt?: unknown;\n updatedAt?: unknown;\n };\n const stamp = savedAt ?? updatedAt;\n return typeof stamp === \"number\" && Number.isFinite(stamp)\n ? stamp\n : undefined;\n}\n\n/**\n * Removes session records last saved more than `maxAgeMs` ago, skipping the\n * keys mounted in this tab and, through `withUnused`, those another tab holds.\n *\n * statewire's own retention sweep only retires records with nothing queued and\n * nothing failed: a record still carrying an unconfirmed or failed send is\n * exempt from both its age and count bounds, so every thread left with one\n * kept its key forever. Past the TTL those sends are long out of send\n * recovery's auto-retry window, so the record goes the same way an empty one\n * does.\n */\nexport async function retireExpiredSessionRecords({\n backend,\n mounted,\n maxAgeMs,\n now = Date.now(),\n}: {\n backend: Pick<\n SyncBackend,\n \"getItem\" | \"removeItem\" | \"getAllKeys\" | \"withUnused\"\n >;\n mounted: ReadonlyMap<string, number>;\n maxAgeMs: number;\n now?: number;\n}): Promise<void> {\n for (const key of backend.getAllKeys()) {\n if (!key.startsWith(SESSION_PREFIX) || mounted.has(key)) continue;\n const savedAt = savedAtOf(backend.getItem(key));\n if (savedAt === undefined || now - savedAt <= maxAgeMs) continue;\n await backend.withUnused(key, async () => {\n if (mounted.has(key) || savedAtOf(backend.getItem(key)) !== savedAt)\n return;\n backend.removeItem(key);\n });\n }\n}\n\ntype DegradationListener = (degradation: SessionStorageDegradation) => void;\n\ntype SharedBackend = {\n backend: SyncBackend & KeyValueSessionStorage.Backend;\n listeners: Set<DegradationListener>;\n /** Storage keys of the sessions mounted in this tab, with mount counts. */\n mounted: Map<string, number>;\n};\n\n/**\n * One backend per storage object — per origin, in a browser — shared by every\n * session mounted in the tab, exactly as the upstream resource's module-level\n * backend is. statewire keys its in-tab \"active\" bookkeeping by backend\n * identity, so a mount's retention sweep only skips the records of other\n * mounts on the *same* backend; and the absorbed-write overlay has to outlive\n * a remount of the same thread (a thread switch and back) or the remount would\n * read the stale persisted copy. Degradations fan out to every mounted\n * session's reporter.\n */\nconst sharedBackends = new WeakMap<StorageLike, SharedBackend>();\n\nfunction sharedBackend({\n storage,\n locks,\n}: {\n storage: StorageLike;\n locks: LockManagerLike;\n}): SharedBackend {\n let shared = sharedBackends.get(storage);\n if (shared === undefined) {\n const listeners = new Set<DegradationListener>();\n shared = {\n listeners,\n mounted: new Map(),\n backend: quotaTolerantBackend({\n inner: browserBackend({ storage, locks }),\n onDegraded: (degradation) => {\n for (const listener of listeners) listener(degradation);\n },\n }),\n };\n sharedBackends.set(storage, shared);\n }\n return shared;\n}\n\n/**\n * Athena's browser session store: `@assistant-ui/react-statewire`'s\n * `LocalStorageSession` contract (per-thread key under the shared prefix,\n * cross-tab Web Lock, storage-event subscription, retention) on top of\n * {@link quotaTolerantBackend}, with Athena's protocol lane and retention\n * policy.\n */\nconst useQuotaSafeLocalStorageSession = ({\n threadId,\n key = (id) => id,\n ttl = 7 * DAY_MS,\n max = 50,\n onStorageDegraded,\n}: QuotaSafeLocalStorageSession.Options): StatewireClient.SessionStorage => {\n const storage = browserGlobals.localStorage;\n const locks = browserGlobals.navigator?.locks;\n if (!storage)\n throw new Error(\n \"statewire: QuotaSafeLocalStorageSession requires localStorage\"\n );\n if (!locks)\n throw new Error(\n \"statewire: QuotaSafeLocalStorageSession requires the Web Locks API (navigator.locks)\"\n );\n const sessionKey = key(threadId);\n const storageKey = SESSION_PREFIX + sessionKey;\n const lockName = SESSION_LOCK_PREFIX + sessionKey;\n\n // One mounted store serves one lane scope (one principal, one backend) for\n // its whole life: the upstream `LocalStorageSession` contract, whose\n // principal guard this is. The statewire session over the store keeps the\n // client id, lane clocks and journal it loaded, so a store moved to another\n // principal's lane would carry them there and send the previous principal's\n // undelivered commands under the next one's credential. A thread switch keeps\n // the scope and re-targets the store; a change of scope refuses, and the host\n // remounts the account's thread (`useDeepAgentRuntime` does). The previous\n // principal's record is left as it is.\n const mountedScope = useRef<DeepAgentSessionLaneScope>({\n threadId,\n laneKey: sessionKey,\n });\n if (!isSameSessionLaneScope({ scope: mountedScope.current, key })) {\n throw new Error(\n \"statewire: principal changed; remount the account's thread/session\"\n );\n }\n\n const latestOnDegraded = useRef(onStorageDegraded);\n latestOnDegraded.current = onStorageDegraded;\n const reportDegradation = useMemo(() => {\n const reported = new Set<string>();\n return (degradation: SessionStorageDegradation) => {\n const handler = latestOnDegraded.current;\n if (handler) {\n try {\n handler(degradation);\n } catch {\n // Reporting runs inside the session's recovery path and must never\n // become the failure it is reporting.\n }\n return;\n }\n const dedupeKey = `${degradation.operation}:${degradation.key}`;\n if (reported.has(dedupeKey)) return;\n reported.add(dedupeKey);\n console.warn(\n `[statewire] session storage degraded to memory only (${degradation.operation} ${degradation.key})`,\n degradation.error\n );\n };\n }, []);\n\n const shared = sharedBackend({ storage, locks });\n // Registered during render as well as in the effect: the read statewire\n // makes while mounting below happens before any effect runs, and tap may\n // clean an effect up and re-run it within one commit.\n shared.listeners.add(reportDegradation);\n useEffect(() => {\n shared.listeners.add(reportDegradation);\n return () => {\n shared.listeners.delete(reportDegradation);\n };\n }, [shared, reportDegradation]);\n\n useEffect(() => {\n const { mounted } = shared;\n mounted.set(storageKey, (mounted.get(storageKey) ?? 0) + 1);\n retireExpiredSessionRecords({\n backend: shared.backend,\n mounted,\n maxAgeMs: ttl,\n }).catch((error: unknown) =>\n reportDegradation({ operation: \"withUnused\", key: storageKey, error })\n );\n return () => {\n const count = (mounted.get(storageKey) ?? 1) - 1;\n if (count === 0) mounted.delete(storageKey);\n else mounted.set(storageKey, count);\n };\n }, [shared, storageKey, ttl, reportDegradation]);\n\n // Hold the record's shared \"active\" lock while mounted so another tab's\n // retention sweep skips it (the same fence the upstream resource holds).\n useEffect(() => {\n let release: (() => void) | undefined;\n let disposed = false;\n Promise.resolve(\n locks.request(\n SESSION_ACTIVE_PREFIX + storageKey,\n { mode: \"shared\" },\n () => {\n if (disposed) return;\n return new Promise<void>((resolve) => {\n release = resolve;\n });\n }\n )\n ).catch((error: unknown) =>\n reportDegradation({ operation: \"lock\", key: storageKey, error })\n );\n return () => {\n disposed = true;\n release?.();\n };\n }, [locks, storageKey, reportDegradation]);\n\n // The storage resource includes migrate in its identity. A fresh callback\n // on every render replaces the store and prevents hydration from settling.\n const migrate = useCallback<\n NonNullable<StatewireClient.SessionStorage[\"migrate\"]>\n >(\n (record, current) => {\n const migrated = parkIncompatibleSessionCommands(record, current);\n if (migrated.parked === 0) return migrated.record;\n reportDegradation({\n operation: \"migrate\",\n key: storageKey,\n error: new Error(\n `${migrated.parked} queued statewire command(s) predate the current protocol range; parked as failed sends`\n ),\n });\n return migrated.record;\n },\n [reportDegradation, storageKey]\n );\n\n const sessionStorage = useResource(\n KeyValueSessionStorage({\n backend: shared.backend,\n key: sessionKey,\n namespace: SESSION_PREFIX,\n protocol: DEEP_AGENT_STATEWIRE_PROTOCOL,\n migrate,\n retention: { maxAgeMs: ttl, maxEntries: max },\n // A failure statewire raises itself (a structurally invalid stored\n // record) still stops the session; it is at least reported the same way.\n onError: (error) =>\n reportDegradation({ operation: \"session\", key: storageKey, error }),\n })\n );\n\n return useMemo(\n () => ({\n ...sessionStorage,\n lock: async <T>(fn: () => T | Promise<T>): Promise<T> => {\n let granted = false;\n try {\n return await locks.request(lockName, async () => {\n granted = true;\n return fn();\n });\n } catch (error) {\n if (granted) throw error;\n // The lock manager refused the request itself (a detached or\n // back/forward-cached document, a lockdown-mode origin): the\n // transaction runs unfenced rather than stopping the session.\n reportDegradation({ operation: \"lock\", key: storageKey, error });\n return fn();\n }\n },\n subscribe: (listener: () => void) => {\n const onStorage = (event: StorageEventLike) => {\n if (event.key === storageKey) listener();\n };\n browserGlobals.addEventListener?.(\"storage\", onStorage);\n return () => browserGlobals.removeEventListener?.(\"storage\", onStorage);\n },\n }),\n [sessionStorage, locks, storageKey, lockName, reportDegradation]\n );\n};\n\n/** Athena's browser session keys and retention policy. */\nexport const QuotaSafeLocalStorageSession = resource(\n useQuotaSafeLocalStorageSession\n);\n\nexport namespace QuotaSafeLocalStorageSession {\n export type Options = {\n threadId: string;\n /**\n * The lane's storage key for a thread, scoped by the principal (and the\n * sync host) the lane belongs to. It must keep naming the same principal's\n * lanes for the life of the mounted store: a change throws (\"principal\n * changed\"), as the upstream `LocalStorageSession` does, and the host\n * remounts the account's thread.\n */\n key?: (threadId: string) => string;\n ttl?: number;\n max?: number;\n /**\n * Called when a storage operation failed and the session carried on in\n * memory. Defaults to one `console.warn` per operation and key.\n */\n onStorageDegraded?: (degradation: SessionStorageDegradation) => void;\n };\n}\n"],"names":["storage","failed","useRef","isSameSessionLaneScope","useMemo","useEffect","useCallback","useResource","KeyValueSessionStorage","DEEP_AGENT_STATEWIRE_PROTOCOL","_a","resource"],"mappings":"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"}
1
+ {"version":3,"file":"quota-safe-local-storage-session.cjs","sources":["../../../../agent-runtime/src/quota-safe-local-storage-session.ts"],"sourcesContent":["import { resource, useResource } from \"@assistant-ui/tap\";\nimport type { StatewireClient, StatewireProtocol } from \"statewire\";\nimport { KeyValueSessionStorage } from \"statewire/storage\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport {\n type DeepAgentSessionLaneScope,\n isSameSessionLaneScope,\n} from \"./session-lane-scope\";\nimport { DEEP_AGENT_STATEWIRE_PROTOCOL } from \"./statewire-transport\";\n\nconst SESSION_PREFIX = \"aui:statewire-session:\";\nconst SESSION_LOCK_PREFIX = \"aui:statewire-session-lock:\";\nconst SESSION_ACTIVE_PREFIX = \"aui:statewire-session-active:\";\nconst DAY_MS = 24 * 60 * 60 * 1000;\n/** The stored-record formats the statewire this build ships reads (it writes 3). */\nconst READABLE_STORAGE_VERSIONS: ReadonlySet<unknown> = new Set([1, 2, 3]);\n\n/** Structural view of the browser storage global — this package compiles\n * without the DOM lib (React Native honesty; see `globals.d.ts`). */\ntype StorageLike = {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n key(index: number): string | null;\n readonly length: number;\n};\n\ntype LockGrant = object | null;\n\n/** The Web Locks API surface the session uses (`navigator.locks`). */\ntype LockManagerLike = {\n request<T>(\n name: string,\n callback: (lock: LockGrant) => T | Promise<T>\n ): Promise<T>;\n request<T>(\n name: string,\n options: { mode?: \"shared\" | \"exclusive\"; ifAvailable?: boolean },\n callback: (lock: LockGrant) => T | Promise<T>\n ): Promise<T>;\n};\n\ntype StorageEventLike = { key: string | null };\n\ntype BrowserGlobals = {\n localStorage?: StorageLike;\n navigator?: { locks?: LockManagerLike };\n addEventListener?: (\n type: \"storage\",\n listener: (event: StorageEventLike) => void\n ) => void;\n removeEventListener?: (\n type: \"storage\",\n listener: (event: StorageEventLike) => void\n ) => void;\n};\n\nconst browserGlobals = globalThis as BrowserGlobals;\n\n/** A persisted session record: per-lane failed entries (a pre-lane record carried them at the root). */\ntype SessionRecordLike = {\n failed?: unknown;\n lanes?: Record<string, { failed?: unknown } | null | undefined> | null;\n};\n\nexport function readPersistedFailedSendStamps(\n sessionKey: string\n): ReadonlyMap<string, number> | null {\n const storage = browserGlobals.localStorage;\n if (!storage) return null;\n let record: SessionRecordLike | null;\n try {\n const raw = storage.getItem(SESSION_PREFIX + sessionKey);\n record =\n raw === null ? null : (JSON.parse(raw) as SessionRecordLike | null);\n } catch {\n return null;\n }\n return readFailedSendStampsFromRecord(record);\n}\n\n/**\n * Send stamps (message id → epoch ms of the original send) off an already\n * loaded session record's failed lane — the storage-agnostic half of\n * {@link readPersistedFailedSendStamps}, for hosts whose session store is not\n * localStorage (the React Native AsyncStorage-backed store reads its record\n * synchronously through `SessionStorage.load()`).\n *\n * Returns `null` for no record (every failed entry then counts as fresh) and\n * an empty map for a record without failures.\n */\nexport function readFailedSendStampsFromRecord(\n record: SessionRecordLike | null | undefined\n): ReadonlyMap<string, number> | null {\n if (!record || typeof record !== \"object\") return null;\n const stamps = new Map<string, number>();\n const lanes =\n record.lanes && typeof record.lanes === \"object\" ? record.lanes : {};\n const failed = [\n ...(Array.isArray(record.failed) ? record.failed : []),\n ...Object.values(lanes).flatMap((lane) =>\n Array.isArray(lane?.failed) ? lane.failed : []\n ),\n ];\n for (const entry of failed) {\n const failed = entry as {\n ts?: unknown;\n params?: readonly { message?: { id?: unknown } }[];\n } | null;\n const messageId = failed?.params?.[0]?.message?.id;\n if (typeof messageId === \"string\" && typeof failed?.ts === \"number\") {\n stamps.set(messageId, failed.ts);\n }\n }\n return stamps;\n}\n\n/** A storage operation the session survived by degrading instead of failing. */\nexport type SessionStorageDegradation = {\n operation:\n | \"getItem\"\n | \"setItem\"\n | \"removeItem\"\n | \"getAllKeys\"\n | \"withUnused\"\n /** The lock manager refused the transaction fence; it ran unfenced. */\n | \"lock\"\n /**\n * The stored record is one this build cannot read (not JSON, or a newer\n * storage version): served as absent, and the key is shielded from being\n * overwritten so the record survives this tab.\n */\n | \"record\"\n /** statewire's own storage failure (a structurally invalid stored record). */\n | \"session\"\n /**\n * Queued commands persisted by an earlier statewire build no longer fit\n * the current wire/protocol range: parked in the lane's failed list (the\n * send-recovery sweep re-dispatches them) instead of blocking the mount.\n */\n | \"migrate\";\n key: string;\n error: unknown;\n};\n\ntype ProducedRange = NonNullable<StatewireClient.SessionCommand[\"produced\"]>;\n\nconst inRange = (value: string, range: StatewireProtocol.Range) =>\n value >= (range.minVersion ?? range.version) && value <= range.version;\n\n/** Mirrors statewire's own stored-command compatibility check. */\nconst storedCommandCompatible = (\n protocol: string,\n command: StatewireClient.SessionCommand,\n current: ProducedRange\n): boolean => {\n if (\n !command.produced ||\n !inRange(command.produced.wire.version, current.wire)\n )\n return false;\n if (current.protocols === \"*\") return true;\n if (command.produced.protocols === \"*\") return false;\n const produced = command.produced.protocols.find((p) => p.name === protocol);\n const offer = current.protocols.find((p) => p.name === protocol);\n return (\n produced !== undefined &&\n offer !== undefined &&\n inRange(produced.version, offer)\n );\n};\n\n/**\n * The oldest wire whose stored statements the current client still replays.\n * Bundled clients before #45143 offered 2026-09-13 through 2026-09-30 and\n * stamped every queued statement with 2026-09-13. The durable statement grammar\n * (protocol, method, params, meta, seq) is the same on 2026-09-30; only\n * frame-level context differs. So those statements ride the current wire\n * unchanged, while the network offer stays native 2026-09-30 only.\n */\nexport const STORED_STATEMENT_WIRE_FLOOR = \"2026-09-13\";\n\n/** A stored command the current wire replays as-is: re-stamp, don't park. */\nconst replayableOnCurrentWire = (\n protocol: string,\n command: StatewireClient.SessionCommand,\n current: ProducedRange\n): boolean =>\n command.produced !== undefined &&\n inRange(command.produced.wire.version, {\n version: current.wire.version,\n minVersion: STORED_STATEMENT_WIRE_FLOOR,\n }) &&\n storedCommandCompatible(\n protocol,\n { ...command, produced: { ...command.produced, wire: current.wire } },\n current\n );\n\n/**\n * statewire's `migrate` for a record whose queued commands were produced by\n * an earlier build. A command whose statement the current wire still replays\n * ({@link STORED_STATEMENT_WIRE_FLOOR}: an approval's `run/input` saved by a\n * previous bundled client, say) stays queued, re-stamped with the current\n * range, so it is delivered with its original seq. Every other incompatible\n * command leaves its lane's queue and is\n * retained as a `lost`/`session-lost` failed send re-stamped with the current\n * range. Client identity, lane clocks, compatible commands and existing failed\n * history are untouched, so the mount proceeds and the send-recovery sweep\n * (or the user, via the failed-send UI) re-dispatches the parked sends under\n * the negotiated format instead of the runtime throwing before it dials.\n *\n * Returns the record itself when nothing needed migrating, and the count of\n * parked commands otherwise.\n */\nexport function parkIncompatibleSessionCommands(\n record: StatewireClient.SessionRecord,\n current: ProducedRange,\n now: number = Date.now()\n): { record: StatewireClient.SessionRecord; parked: number; restamped: number } {\n let parked = 0;\n let restamped = 0;\n const lanes: Record<string, StatewireClient.SessionLane> = {};\n for (const [protocol, lane] of Object.entries(record.lanes)) {\n const kept: StatewireClient.SessionCommand[] = [];\n const failed: StatewireClient.FailedCommand[] = [];\n let laneRestamped = 0;\n for (const command of lane.commands) {\n if (storedCommandCompatible(protocol, command, current)) {\n kept.push(command);\n continue;\n }\n if (replayableOnCurrentWire(protocol, command, current)) {\n kept.push({ ...command, produced: current });\n laneRestamped += 1;\n continue;\n }\n failed.push({\n protocol,\n produced: current,\n command: command.method,\n params: command.params,\n ...(command.meta !== undefined && { meta: command.meta }),\n failure: { fate: \"lost\", cause: \"session-lost\" },\n ts: now,\n seq: command.seq,\n });\n }\n parked += failed.length;\n restamped += laneRestamped;\n lanes[protocol] =\n failed.length === 0 && laneRestamped === 0\n ? lane\n : {\n ...lane,\n commands: kept,\n ...((failed.length > 0 || lane.failed !== undefined) && {\n failed: [...(lane.failed ?? []), ...failed],\n }),\n };\n }\n return parked === 0 && restamped === 0\n ? { record, parked, restamped }\n : { record: { ...record, lanes }, parked, restamped };\n}\n\n/**\n * Whether `error` is the browser refusing a write for lack of room, under\n * every name the engines use — `QuotaExceededError` (Chromium, WebKit, current\n * Firefox), `NS_ERROR_DOM_QUOTA_REACHED` (older Firefox), the legacy\n * `DOMException` codes 22 (WebKit) and 1014 (Firefox) — or a plain error whose\n * message carries one of those (storage proxies and WebViews rewrap the\n * exception). Olympus's `isStorageQuotaError` recognises the same set; the two\n * stay in step.\n */\nexport function isStorageQuotaError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n const { name, code, message } = error as {\n name?: unknown;\n code?: unknown;\n message?: unknown;\n };\n return (\n name === \"QuotaExceededError\" ||\n name === \"NS_ERROR_DOM_QUOTA_REACHED\" ||\n code === 22 ||\n code === 1014 ||\n (typeof message === \"string\" &&\n /exceeded the quota|quotaexceedederror|ns_error_dom_quota_reached/i.test(\n message\n ))\n );\n}\n\n/** The one quota shape statewire's retention sweep recognises. */\nfunction asStatewireQuotaError(error: unknown): Error {\n if (error instanceof Error && error.name === \"QuotaExceededError\")\n return error;\n const normalized = new Error(\n error instanceof Error ? error.message : \"storage quota exceeded\"\n );\n normalized.name = \"QuotaExceededError\";\n return normalized;\n}\n\n/**\n * Why `raw` is a stored record this build cannot read, or `undefined` when it\n * may be one. Mirrors the two decode failures statewire raises for a record it\n * cannot read — invalid JSON, and a `statewireStorageVersion` newer than the\n * ones this build's statewire decodes (a tab left open across a\n * statewire upgrade, reading the record a newer tab keeps) — because statewire\n * throws those out of the resource at mount instead of treating the record as\n * absent. A structurally invalid record of the right version still fails\n * inside statewire.\n */\nfunction unreadableRecord(raw: string): Error | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n return error instanceof Error\n ? error\n : new Error(\"stored session record is not JSON\");\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return new Error(\"stored session record is not an object\");\n }\n const version = (parsed as { statewireStorageVersion?: unknown })\n .statewireStorageVersion;\n if (version !== undefined && !READABLE_STORAGE_VERSIONS.has(version)) {\n return new Error(\n `stored session record uses storage version ${String(version)}`\n );\n }\n return undefined;\n}\n\ntype SyncBackend = {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n getAllKeys: () => readonly string[];\n withUnused: (key: string, action: () => Promise<void>) => Promise<void>;\n};\n\n/**\n * The browser backend `@assistant-ui/react-statewire`'s `LocalStorageSession`\n * uses, reproduced here because that resource does not take a backend: raw\n * `localStorage`, with retention cleanup fenced by the same Web Locks so a\n * sweep never removes a record another tab is actively sharing.\n */\nfunction browserBackend({\n storage,\n locks,\n}: {\n storage: StorageLike;\n locks: LockManagerLike;\n}): SyncBackend {\n return {\n getItem: (key) => storage.getItem(key),\n setItem: (key, value) => storage.setItem(key, value),\n removeItem: (key) => storage.removeItem(key),\n getAllKeys: () =>\n Array.from({ length: storage.length }, (_, index) =>\n storage.key(index)\n ).filter((key): key is string => key !== null),\n withUnused: async (key, action) => {\n await locks.request(\n SESSION_ACTIVE_PREFIX + key,\n { ifAvailable: true },\n async (active) => {\n if (active === null) return;\n await locks.request(\n SESSION_LOCK_PREFIX + key.slice(SESSION_PREFIX.length),\n { ifAvailable: true },\n async (lock) => {\n if (lock === null) return;\n await action();\n }\n );\n }\n );\n },\n };\n}\n\n/**\n * Wraps a synchronous key-value backend so a failing origin degrades the\n * session to memory-only persistence instead of stopping the connection.\n *\n * statewire's session storage latches the first unrecognised write failure\n * and from then on rejects every send (`stopped/storage-error`, \"session\n * storage failed\" on the connection chip). It only recovers a\n * `QuotaExceededError` by that exact name — sweeping old session records and\n * retrying the write once — and latches again when the retry fails too. Here\n * the first quota failure per key is surfaced under that name so the sweep\n * runs; the retry that follows it and every other storage failure are absorbed\n * and reported through `onDegraded`, so chat keeps working.\n *\n * An absorbed write is kept in an in-memory overlay that `getItem` serves\n * first: statewire re-reads the record through `load()` on every shared-mode\n * transaction, so a stale persisted copy would otherwise win back its old\n * `nextSeq`, `clientId` and command journal. The overlay is per tab — another\n * tab sharing the thread still reads the last persisted copy, which is the\n * memory-only degradation this backend exists to allow. A later successful\n * write clears the overlay entry.\n *\n * A key whose read threw, or whose stored value this build cannot read (see\n * {@link unreadableRecord}), is served as absent and shielded: writes to it\n * stay in the overlay for good, so a fresh lane minted over an unreadable\n * record never overwrites what another tab or a newer build persisted.\n */\nexport function quotaTolerantBackend({\n inner,\n onDegraded,\n}: {\n inner: SyncBackend;\n onDegraded: (degradation: SessionStorageDegradation) => void;\n}): SyncBackend & KeyValueSessionStorage.Backend {\n // Keys whose write already surfaced a quota error to statewire: until a\n // write succeeds again, later failures on the key are absorbed instead of\n // surfaced, or every save would re-run statewire's sweep (which evicts\n // other threads' idle records) and the failure would latch on the retry.\n const quotaSurfaced = new Set<string>();\n // Absorbed writes, served ahead of the backend (see the function docs).\n const overlay = new Map<string, string>();\n // Keys served as absent and never written through (see the function docs).\n const shielded = new Set<string>();\n // statewire re-reads and re-decodes the record on every transaction; the\n // readability check is memoised on the raw string so it costs one string\n // comparison per read, not a second parse.\n const checked = new Map<\n string,\n { raw: string; verdict: Error | undefined }\n >();\n const readable = (key: string, raw: string): Error | undefined => {\n const previous = checked.get(key);\n if (previous !== undefined && previous.raw === raw) return previous.verdict;\n const verdict = unreadableRecord(raw);\n checked.set(key, { raw, verdict });\n return verdict;\n };\n return {\n getItem: (key) => {\n const shadowed = overlay.get(key);\n if (shadowed !== undefined) return shadowed;\n if (shielded.has(key)) return null;\n let raw: string | null;\n try {\n raw = inner.getItem(key);\n } catch (error) {\n shielded.add(key);\n onDegraded({ operation: \"getItem\", key, error });\n return null;\n }\n if (raw === null) return null;\n const unreadable = readable(key, raw);\n if (unreadable === undefined) return raw;\n shielded.add(key);\n onDegraded({ operation: \"record\", key, error: unreadable });\n return null;\n },\n setItem: (key, value) => {\n if (shielded.has(key)) {\n overlay.set(key, value);\n return;\n }\n try {\n inner.setItem(key, value);\n overlay.delete(key);\n quotaSurfaced.delete(key);\n } catch (error) {\n if (isStorageQuotaError(error) && !quotaSurfaced.has(key)) {\n quotaSurfaced.add(key);\n throw asStatewireQuotaError(error);\n }\n overlay.set(key, value);\n onDegraded({ operation: \"setItem\", key, error });\n }\n },\n removeItem: (key) => {\n overlay.delete(key);\n if (shielded.has(key)) return;\n try {\n inner.removeItem(key);\n } catch (error) {\n onDegraded({ operation: \"removeItem\", key, error });\n }\n },\n getAllKeys: () => {\n const keys = new Set<string>(overlay.keys());\n try {\n for (const key of inner.getAllKeys()) keys.add(key);\n } catch (error) {\n onDegraded({ operation: \"getAllKeys\", key: \"\", error });\n }\n return [...keys];\n },\n withUnused: async (key, action) => {\n try {\n await inner.withUnused(key, action);\n } catch (error) {\n onDegraded({ operation: \"withUnused\", key, error });\n }\n },\n };\n}\n\n/** A stored record's save stamp, or `undefined` when it carries none. */\nfunction savedAtOf(raw: string | null): number | undefined {\n if (raw === null) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof parsed !== \"object\" || parsed === null) return undefined;\n const { savedAt, updatedAt } = parsed as {\n savedAt?: unknown;\n updatedAt?: unknown;\n };\n const stamp = savedAt ?? updatedAt;\n return typeof stamp === \"number\" && Number.isFinite(stamp)\n ? stamp\n : undefined;\n}\n\n/**\n * Removes session records last saved more than `maxAgeMs` ago, skipping the\n * keys mounted in this tab and, through `withUnused`, those another tab holds.\n *\n * statewire's own retention sweep only retires records with nothing queued and\n * nothing failed: a record still carrying an unconfirmed or failed send is\n * exempt from both its age and count bounds, so every thread left with one\n * kept its key forever. Past the TTL those sends are long out of send\n * recovery's auto-retry window, so the record goes the same way an empty one\n * does.\n */\nexport async function retireExpiredSessionRecords({\n backend,\n mounted,\n maxAgeMs,\n now = Date.now(),\n}: {\n backend: Pick<\n SyncBackend,\n \"getItem\" | \"removeItem\" | \"getAllKeys\" | \"withUnused\"\n >;\n mounted: ReadonlyMap<string, number>;\n maxAgeMs: number;\n now?: number;\n}): Promise<void> {\n for (const key of backend.getAllKeys()) {\n if (!key.startsWith(SESSION_PREFIX) || mounted.has(key)) continue;\n const savedAt = savedAtOf(backend.getItem(key));\n if (savedAt === undefined || now - savedAt <= maxAgeMs) continue;\n await backend.withUnused(key, async () => {\n if (mounted.has(key) || savedAtOf(backend.getItem(key)) !== savedAt)\n return;\n backend.removeItem(key);\n });\n }\n}\n\ntype DegradationListener = (degradation: SessionStorageDegradation) => void;\n\ntype SharedBackend = {\n backend: SyncBackend & KeyValueSessionStorage.Backend;\n listeners: Set<DegradationListener>;\n /** Storage keys of the sessions mounted in this tab, with mount counts. */\n mounted: Map<string, number>;\n};\n\n/**\n * One backend per storage object — per origin, in a browser — shared by every\n * session mounted in the tab, exactly as the upstream resource's module-level\n * backend is. statewire keys its in-tab \"active\" bookkeeping by backend\n * identity, so a mount's retention sweep only skips the records of other\n * mounts on the *same* backend; and the absorbed-write overlay has to outlive\n * a remount of the same thread (a thread switch and back) or the remount would\n * read the stale persisted copy. Degradations fan out to every mounted\n * session's reporter.\n */\nconst sharedBackends = new WeakMap<StorageLike, SharedBackend>();\n\nfunction sharedBackend({\n storage,\n locks,\n}: {\n storage: StorageLike;\n locks: LockManagerLike;\n}): SharedBackend {\n let shared = sharedBackends.get(storage);\n if (shared === undefined) {\n const listeners = new Set<DegradationListener>();\n shared = {\n listeners,\n mounted: new Map(),\n backend: quotaTolerantBackend({\n inner: browserBackend({ storage, locks }),\n onDegraded: (degradation) => {\n for (const listener of listeners) listener(degradation);\n },\n }),\n };\n sharedBackends.set(storage, shared);\n }\n return shared;\n}\n\n/**\n * Athena's browser session store: `@assistant-ui/react-statewire`'s\n * `LocalStorageSession` contract (per-thread key under the shared prefix,\n * cross-tab Web Lock, storage-event subscription, retention) on top of\n * {@link quotaTolerantBackend}, with Athena's protocol lane and retention\n * policy.\n */\nconst useQuotaSafeLocalStorageSession = ({\n threadId,\n key = (id) => id,\n ttl = 7 * DAY_MS,\n max = 50,\n onStorageDegraded,\n}: QuotaSafeLocalStorageSession.Options): StatewireClient.SessionStorage => {\n const storage = browserGlobals.localStorage;\n const locks = browserGlobals.navigator?.locks;\n if (!storage)\n throw new Error(\n \"statewire: QuotaSafeLocalStorageSession requires localStorage\"\n );\n if (!locks)\n throw new Error(\n \"statewire: QuotaSafeLocalStorageSession requires the Web Locks API (navigator.locks)\"\n );\n const sessionKey = key(threadId);\n const storageKey = SESSION_PREFIX + sessionKey;\n const lockName = SESSION_LOCK_PREFIX + sessionKey;\n\n // One mounted store serves one lane scope (one principal, one backend) for\n // its whole life: the upstream `LocalStorageSession` contract, whose\n // principal guard this is. The statewire session over the store keeps the\n // client id, lane clocks and journal it loaded, so a store moved to another\n // principal's lane would carry them there and send the previous principal's\n // undelivered commands under the next one's credential. A thread switch keeps\n // the scope and re-targets the store; a change of scope refuses, and the host\n // remounts the account's thread (`useDeepAgentRuntime` does). The previous\n // principal's record is left as it is.\n const mountedScope = useRef<DeepAgentSessionLaneScope>({\n threadId,\n laneKey: sessionKey,\n });\n if (!isSameSessionLaneScope({ scope: mountedScope.current, key })) {\n throw new Error(\n \"statewire: principal changed; remount the account's thread/session\"\n );\n }\n\n const latestOnDegraded = useRef(onStorageDegraded);\n latestOnDegraded.current = onStorageDegraded;\n const reportDegradation = useMemo(() => {\n const reported = new Set<string>();\n return (degradation: SessionStorageDegradation) => {\n const handler = latestOnDegraded.current;\n if (handler) {\n try {\n handler(degradation);\n } catch {\n // Reporting runs inside the session's recovery path and must never\n // become the failure it is reporting.\n }\n return;\n }\n const dedupeKey = `${degradation.operation}:${degradation.key}`;\n if (reported.has(dedupeKey)) return;\n reported.add(dedupeKey);\n console.warn(\n `[statewire] session storage degraded to memory only (${degradation.operation} ${degradation.key})`,\n degradation.error\n );\n };\n }, []);\n\n const shared = sharedBackend({ storage, locks });\n // Registered during render as well as in the effect: the read statewire\n // makes while mounting below happens before any effect runs, and tap may\n // clean an effect up and re-run it within one commit.\n shared.listeners.add(reportDegradation);\n useEffect(() => {\n shared.listeners.add(reportDegradation);\n return () => {\n shared.listeners.delete(reportDegradation);\n };\n }, [shared, reportDegradation]);\n\n useEffect(() => {\n const { mounted } = shared;\n mounted.set(storageKey, (mounted.get(storageKey) ?? 0) + 1);\n retireExpiredSessionRecords({\n backend: shared.backend,\n mounted,\n maxAgeMs: ttl,\n }).catch((error: unknown) =>\n reportDegradation({ operation: \"withUnused\", key: storageKey, error })\n );\n return () => {\n const count = (mounted.get(storageKey) ?? 1) - 1;\n if (count === 0) mounted.delete(storageKey);\n else mounted.set(storageKey, count);\n };\n }, [shared, storageKey, ttl, reportDegradation]);\n\n // Hold the record's shared \"active\" lock while mounted so another tab's\n // retention sweep skips it (the same fence the upstream resource holds).\n useEffect(() => {\n let release: (() => void) | undefined;\n let disposed = false;\n Promise.resolve(\n locks.request(\n SESSION_ACTIVE_PREFIX + storageKey,\n { mode: \"shared\" },\n () => {\n if (disposed) return;\n return new Promise<void>((resolve) => {\n release = resolve;\n });\n }\n )\n ).catch((error: unknown) =>\n reportDegradation({ operation: \"lock\", key: storageKey, error })\n );\n return () => {\n disposed = true;\n release?.();\n };\n }, [locks, storageKey, reportDegradation]);\n\n // The storage resource includes migrate in its identity. A fresh callback\n // on every render replaces the store and prevents hydration from settling.\n const migrate = useCallback<\n NonNullable<StatewireClient.SessionStorage[\"migrate\"]>\n >(\n (record, current) => {\n const migrated = parkIncompatibleSessionCommands(record, current);\n if (migrated.parked === 0) return migrated.record;\n reportDegradation({\n operation: \"migrate\",\n key: storageKey,\n error: new Error(\n `${migrated.parked} queued statewire command(s) predate the current protocol range; parked as failed sends`\n ),\n });\n return migrated.record;\n },\n [reportDegradation, storageKey]\n );\n\n const sessionStorage = useResource(\n KeyValueSessionStorage({\n backend: shared.backend,\n key: sessionKey,\n namespace: SESSION_PREFIX,\n protocol: DEEP_AGENT_STATEWIRE_PROTOCOL,\n migrate,\n retention: { maxAgeMs: ttl, maxEntries: max },\n // A failure statewire raises itself (a structurally invalid stored\n // record) still stops the session; it is at least reported the same way.\n onError: (error) =>\n reportDegradation({ operation: \"session\", key: storageKey, error }),\n })\n );\n\n return useMemo(\n () => ({\n ...sessionStorage,\n lock: async <T>(fn: () => T | Promise<T>): Promise<T> => {\n let granted = false;\n try {\n return await locks.request(lockName, async () => {\n granted = true;\n return fn();\n });\n } catch (error) {\n if (granted) throw error;\n // The lock manager refused the request itself (a detached or\n // back/forward-cached document, a lockdown-mode origin): the\n // transaction runs unfenced rather than stopping the session.\n reportDegradation({ operation: \"lock\", key: storageKey, error });\n return fn();\n }\n },\n subscribe: (listener: () => void) => {\n const onStorage = (event: StorageEventLike) => {\n if (event.key === storageKey) listener();\n };\n browserGlobals.addEventListener?.(\"storage\", onStorage);\n return () => browserGlobals.removeEventListener?.(\"storage\", onStorage);\n },\n }),\n [sessionStorage, locks, storageKey, lockName, reportDegradation]\n );\n};\n\n/** Athena's browser session keys and retention policy. */\nexport const QuotaSafeLocalStorageSession = resource(\n useQuotaSafeLocalStorageSession\n);\n\nexport namespace QuotaSafeLocalStorageSession {\n export type Options = {\n threadId: string;\n /**\n * The lane's storage key for a thread, scoped by the principal (and the\n * sync host) the lane belongs to. It must keep naming the same principal's\n * lanes for the life of the mounted store: a change throws (\"principal\n * changed\"), as the upstream `LocalStorageSession` does, and the host\n * remounts the account's thread.\n */\n key?: (threadId: string) => string;\n ttl?: number;\n max?: number;\n /**\n * Called when a storage operation failed and the session carried on in\n * memory. Defaults to one `console.warn` per operation and key.\n */\n onStorageDegraded?: (degradation: SessionStorageDegradation) => void;\n };\n}\n"],"names":["storage","failed","useRef","isSameSessionLaneScope","useMemo","useEffect","useCallback","useResource","KeyValueSessionStorage","DEEP_AGENT_STATEWIRE_PROTOCOL","_a","resource"],"mappings":";;;;;;;AAUA,MAAM,iBAAiB;AACvB,MAAM,sBAAsB;AAC5B,MAAM,wBAAwB;AAC9B,MAAM,SAAS,KAAK,KAAK,KAAK;AAE9B,MAAM,4BAAkD,oBAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;AA0CzE,MAAM,iBAAiB;AAQhB,SAAS,8BACd,YACoC;AACpC,QAAMA,WAAU,eAAe;AAC/B,MAAI,CAACA,SAAS,QAAO;AACrB,MAAI;AACJ,MAAI;AACF,UAAM,MAAMA,SAAQ,QAAQ,iBAAiB,UAAU;AACvD,aACE,QAAQ,OAAO,OAAQ,KAAK,MAAM,GAAG;AAAA,EACzC,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO,+BAA+B,MAAM;AAC9C;AAYO,SAAS,+BACd,QACoC;;AACpC,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,6BAAa,IAAA;AACnB,QAAM,QACJ,OAAO,SAAS,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ,CAAA;AACpE,QAAM,SAAS;AAAA,IACb,GAAI,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,SAAS,CAAA;AAAA,IACnD,GAAG,OAAO,OAAO,KAAK,EAAE;AAAA,MAAQ,CAAC,SAC/B,MAAM,QAAQ,6BAAM,MAAM,IAAI,KAAK,SAAS,CAAA;AAAA,IAAC;AAAA,EAC/C;AAEF,aAAW,SAAS,QAAQ;AAC1B,UAAMC,UAAS;AAIf,UAAM,aAAYA,oDAAQ,WAARA,mBAAiB,OAAjBA,mBAAqB,YAArBA,mBAA8B;AAChD,QAAI,OAAO,cAAc,YAAY,QAAOA,mCAAQ,QAAO,UAAU;AACnE,aAAO,IAAI,WAAWA,QAAO,EAAE;AAAA,IACjC;AAAA,EACF;AACA,SAAO;AACT;AAgCA,MAAM,UAAU,CAAC,OAAe,UAC9B,UAAU,MAAM,cAAc,MAAM,YAAY,SAAS,MAAM;AAGjE,MAAM,0BAA0B,CAC9B,UACA,SACA,YACY;AACZ,MACE,CAAC,QAAQ,YACT,CAAC,QAAQ,QAAQ,SAAS,KAAK,SAAS,QAAQ,IAAI;AAEpD,WAAO;AACT,MAAI,QAAQ,cAAc,IAAK,QAAO;AACtC,MAAI,QAAQ,SAAS,cAAc,IAAK,QAAO;AAC/C,QAAM,WAAW,QAAQ,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC3E,QAAM,QAAQ,QAAQ,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC/D,SACE,aAAa,UACb,UAAU,UACV,QAAQ,SAAS,SAAS,KAAK;AAEnC;AAUO,MAAM,8BAA8B;AAG3C,MAAM,0BAA0B,CAC9B,UACA,SACA,YAEA,QAAQ,aAAa,UACrB,QAAQ,QAAQ,SAAS,KAAK,SAAS;AAAA,EACrC,SAAS,QAAQ,KAAK;AAAA,EACtB,YAAY;AACd,CAAC,KACD;AAAA,EACE;AAAA,EACA,EAAE,GAAG,SAAS,UAAU,EAAE,GAAG,QAAQ,UAAU,MAAM,QAAQ,OAAK;AAAA,EAClE;AACF;AAkBK,SAAS,gCACd,QACA,SACA,MAAc,KAAK,OAC2D;AAC9E,MAAI,SAAS;AACb,MAAI,YAAY;AAChB,QAAM,QAAqD,CAAA;AAC3D,aAAW,CAAC,UAAU,IAAI,KAAK,OAAO,QAAQ,OAAO,KAAK,GAAG;AAC3D,UAAM,OAAyC,CAAA;AAC/C,UAAM,SAA0C,CAAA;AAChD,QAAI,gBAAgB;AACpB,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,wBAAwB,UAAU,SAAS,OAAO,GAAG;AACvD,aAAK,KAAK,OAAO;AACjB;AAAA,MACF;AACA,UAAI,wBAAwB,UAAU,SAAS,OAAO,GAAG;AACvD,aAAK,KAAK,EAAE,GAAG,SAAS,UAAU,SAAS;AAC3C,yBAAiB;AACjB;AAAA,MACF;AACA,aAAO,KAAK;AAAA,QACV;AAAA,QACA,UAAU;AAAA,QACV,SAAS,QAAQ;AAAA,QACjB,QAAQ,QAAQ;AAAA,QAChB,GAAI,QAAQ,SAAS,UAAa,EAAE,MAAM,QAAQ,KAAA;AAAA,QAClD,SAAS,EAAE,MAAM,QAAQ,OAAO,eAAA;AAAA,QAChC,IAAI;AAAA,QACJ,KAAK,QAAQ;AAAA,MAAA,CACd;AAAA,IACH;AACA,cAAU,OAAO;AACjB,iBAAa;AACb,UAAM,QAAQ,IACZ,OAAO,WAAW,KAAK,kBAAkB,IACrC,OACA;AAAA,MACE,GAAG;AAAA,MACH,UAAU;AAAA,MACV,IAAK,OAAO,SAAS,KAAK,KAAK,WAAW,WAAc;AAAA,QACtD,QAAQ,CAAC,GAAI,KAAK,UAAU,CAAA,GAAK,GAAG,MAAM;AAAA,MAAA;AAAA,IAC5C;AAAA,EAEV;AACA,SAAO,WAAW,KAAK,cAAc,IACjC,EAAE,QAAQ,QAAQ,UAAA,IAClB,EAAE,QAAQ,EAAE,GAAG,QAAQ,MAAA,GAAS,QAAQ,UAAA;AAC9C;AAWO,SAAS,oBAAoB,OAAyB;AAC3D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,EAAE,MAAM,MAAM,QAAA,IAAY;AAKhC,SACE,SAAS,wBACT,SAAS,gCACT,SAAS,MACT,SAAS,QACR,OAAO,YAAY,YAClB,oEAAoE;AAAA,IAClE;AAAA,EAAA;AAGR;AAGA,SAAS,sBAAsB,OAAuB;AACpD,MAAI,iBAAiB,SAAS,MAAM,SAAS;AAC3C,WAAO;AACT,QAAM,aAAa,IAAI;AAAA,IACrB,iBAAiB,QAAQ,MAAM,UAAU;AAAA,EAAA;AAE3C,aAAW,OAAO;AAClB,SAAO;AACT;AAYA,SAAS,iBAAiB,KAAgC;AACxD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,SAAS,OAAO;AACd,WAAO,iBAAiB,QACpB,QACA,IAAI,MAAM,mCAAmC;AAAA,EACnD;AACA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,WAAO,IAAI,MAAM,wCAAwC;AAAA,EAC3D;AACA,QAAM,UAAW,OACd;AACH,MAAI,YAAY,UAAa,CAAC,0BAA0B,IAAI,OAAO,GAAG;AACpE,WAAO,IAAI;AAAA,MACT,8CAA8C,OAAO,OAAO,CAAC;AAAA,IAAA;AAAA,EAEjE;AACA,SAAO;AACT;AAgBA,SAAS,eAAe;AAAA,EACtB,SAAAD;AAAA,EACA;AACF,GAGgB;AACd,SAAO;AAAA,IACL,SAAS,CAAC,QAAQA,SAAQ,QAAQ,GAAG;AAAA,IACrC,SAAS,CAAC,KAAK,UAAUA,SAAQ,QAAQ,KAAK,KAAK;AAAA,IACnD,YAAY,CAAC,QAAQA,SAAQ,WAAW,GAAG;AAAA,IAC3C,YAAY,MACV,MAAM;AAAA,MAAK,EAAE,QAAQA,SAAQ,OAAA;AAAA,MAAU,CAAC,GAAG,UACzCA,SAAQ,IAAI,KAAK;AAAA,IAAA,EACjB,OAAO,CAAC,QAAuB,QAAQ,IAAI;AAAA,IAC/C,YAAY,OAAO,KAAK,WAAW;AACjC,YAAM,MAAM;AAAA,QACV,wBAAwB;AAAA,QACxB,EAAE,aAAa,KAAA;AAAA,QACf,OAAO,WAAW;AAChB,cAAI,WAAW,KAAM;AACrB,gBAAM,MAAM;AAAA,YACV,sBAAsB,IAAI,MAAM,eAAe,MAAM;AAAA,YACrD,EAAE,aAAa,KAAA;AAAA,YACf,OAAO,SAAS;AACd,kBAAI,SAAS,KAAM;AACnB,oBAAM,OAAA;AAAA,YACR;AAAA,UAAA;AAAA,QAEJ;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAEJ;AA4BO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AACF,GAGiD;AAK/C,QAAM,oCAAoB,IAAA;AAE1B,QAAM,8BAAc,IAAA;AAEpB,QAAM,+BAAe,IAAA;AAIrB,QAAM,8BAAc,IAAA;AAIpB,QAAM,WAAW,CAAC,KAAa,QAAmC;AAChE,UAAM,WAAW,QAAQ,IAAI,GAAG;AAChC,QAAI,aAAa,UAAa,SAAS,QAAQ,YAAY,SAAS;AACpE,UAAM,UAAU,iBAAiB,GAAG;AACpC,YAAQ,IAAI,KAAK,EAAE,KAAK,SAAS;AACjC,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,SAAS,CAAC,QAAQ;AAChB,YAAM,WAAW,QAAQ,IAAI,GAAG;AAChC,UAAI,aAAa,OAAW,QAAO;AACnC,UAAI,SAAS,IAAI,GAAG,EAAG,QAAO;AAC9B,UAAI;AACJ,UAAI;AACF,cAAM,MAAM,QAAQ,GAAG;AAAA,MACzB,SAAS,OAAO;AACd,iBAAS,IAAI,GAAG;AAChB,mBAAW,EAAE,WAAW,WAAW,KAAK,OAAO;AAC/C,eAAO;AAAA,MACT;AACA,UAAI,QAAQ,KAAM,QAAO;AACzB,YAAM,aAAa,SAAS,KAAK,GAAG;AACpC,UAAI,eAAe,OAAW,QAAO;AACrC,eAAS,IAAI,GAAG;AAChB,iBAAW,EAAE,WAAW,UAAU,KAAK,OAAO,YAAY;AAC1D,aAAO;AAAA,IACT;AAAA,IACA,SAAS,CAAC,KAAK,UAAU;AACvB,UAAI,SAAS,IAAI,GAAG,GAAG;AACrB,gBAAQ,IAAI,KAAK,KAAK;AACtB;AAAA,MACF;AACA,UAAI;AACF,cAAM,QAAQ,KAAK,KAAK;AACxB,gBAAQ,OAAO,GAAG;AAClB,sBAAc,OAAO,GAAG;AAAA,MAC1B,SAAS,OAAO;AACd,YAAI,oBAAoB,KAAK,KAAK,CAAC,cAAc,IAAI,GAAG,GAAG;AACzD,wBAAc,IAAI,GAAG;AACrB,gBAAM,sBAAsB,KAAK;AAAA,QACnC;AACA,gBAAQ,IAAI,KAAK,KAAK;AACtB,mBAAW,EAAE,WAAW,WAAW,KAAK,OAAO;AAAA,MACjD;AAAA,IACF;AAAA,IACA,YAAY,CAAC,QAAQ;AACnB,cAAQ,OAAO,GAAG;AAClB,UAAI,SAAS,IAAI,GAAG,EAAG;AACvB,UAAI;AACF,cAAM,WAAW,GAAG;AAAA,MACtB,SAAS,OAAO;AACd,mBAAW,EAAE,WAAW,cAAc,KAAK,OAAO;AAAA,MACpD;AAAA,IACF;AAAA,IACA,YAAY,MAAM;AAChB,YAAM,OAAO,IAAI,IAAY,QAAQ,MAAM;AAC3C,UAAI;AACF,mBAAW,OAAO,MAAM,WAAA,EAAc,MAAK,IAAI,GAAG;AAAA,MACpD,SAAS,OAAO;AACd,mBAAW,EAAE,WAAW,cAAc,KAAK,IAAI,OAAO;AAAA,MACxD;AACA,aAAO,CAAC,GAAG,IAAI;AAAA,IACjB;AAAA,IACA,YAAY,OAAO,KAAK,WAAW;AACjC,UAAI;AACF,cAAM,MAAM,WAAW,KAAK,MAAM;AAAA,MACpC,SAAS,OAAO;AACd,mBAAW,EAAE,WAAW,cAAc,KAAK,OAAO;AAAA,MACpD;AAAA,IACF;AAAA,EAAA;AAEJ;AAGA,SAAS,UAAU,KAAwC;AACzD,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,WAAW,YAAY,WAAW,KAAM,QAAO;AAC1D,QAAM,EAAE,SAAS,UAAA,IAAc;AAI/B,QAAM,QAAQ,WAAW;AACzB,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IACrD,QACA;AACN;AAaA,eAAsB,4BAA4B;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM,KAAK,IAAA;AACb,GAQkB;AAChB,aAAW,OAAO,QAAQ,cAAc;AACtC,QAAI,CAAC,IAAI,WAAW,cAAc,KAAK,QAAQ,IAAI,GAAG,EAAG;AACzD,UAAM,UAAU,UAAU,QAAQ,QAAQ,GAAG,CAAC;AAC9C,QAAI,YAAY,UAAa,MAAM,WAAW,SAAU;AACxD,UAAM,QAAQ,WAAW,KAAK,YAAY;AACxC,UAAI,QAAQ,IAAI,GAAG,KAAK,UAAU,QAAQ,QAAQ,GAAG,CAAC,MAAM;AAC1D;AACF,cAAQ,WAAW,GAAG;AAAA,IACxB,CAAC;AAAA,EACH;AACF;AAqBA,MAAM,qCAAqB,QAAA;AAE3B,SAAS,cAAc;AAAA,EACrB,SAAAA;AAAA,EACA;AACF,GAGkB;AAChB,MAAI,SAAS,eAAe,IAAIA,QAAO;AACvC,MAAI,WAAW,QAAW;AACxB,UAAM,gCAAgB,IAAA;AACtB,aAAS;AAAA,MACP;AAAA,MACA,6BAAa,IAAA;AAAA,MACb,SAAS,qBAAqB;AAAA,QAC5B,OAAO,eAAe,EAAE,SAAAA,UAAS,OAAO;AAAA,QACxC,YAAY,CAAC,gBAAgB;AAC3B,qBAAW,YAAY,UAAW,UAAS,WAAW;AAAA,QACxD;AAAA,MAAA,CACD;AAAA,IAAA;AAEH,mBAAe,IAAIA,UAAS,MAAM;AAAA,EACpC;AACA,SAAO;AACT;AASA,MAAM,kCAAkC,CAAC;AAAA,EACvC;AAAA,EACA,MAAM,CAAC,OAAO;AAAA,EACd,MAAM,IAAI;AAAA,EACV,MAAM;AAAA,EACN;AACF,MAA4E;;AAC1E,QAAMA,YAAU,eAAe;AAC/B,QAAM,SAAQ,oBAAe,cAAf,mBAA0B;AACxC,MAAI,CAACA;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAEJ,MAAI,CAAC;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAEJ,QAAM,aAAa,IAAI,QAAQ;AAC/B,QAAM,aAAa,iBAAiB;AACpC,QAAM,WAAW,sBAAsB;AAWvC,QAAM,eAAeE,WAAAA,OAAkC;AAAA,IACrD;AAAA,IACA,SAAS;AAAA,EAAA,CACV;AACD,MAAI,CAACC,iBAAAA,uBAAuB,EAAE,OAAO,aAAa,SAAS,IAAA,CAAK,GAAG;AACjE,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,mBAAmBD,WAAAA,OAAO,iBAAiB;AACjD,mBAAiB,UAAU;AAC3B,QAAM,oBAAoBE,WAAAA,QAAQ,MAAM;AACtC,UAAM,+BAAe,IAAA;AACrB,WAAO,CAAC,gBAA2C;AACjD,YAAM,UAAU,iBAAiB;AACjC,UAAI,SAAS;AACX,YAAI;AACF,kBAAQ,WAAW;AAAA,QACrB,QAAQ;AAAA,QAGR;AACA;AAAA,MACF;AACA,YAAM,YAAY,GAAG,YAAY,SAAS,IAAI,YAAY,GAAG;AAC7D,UAAI,SAAS,IAAI,SAAS,EAAG;AAC7B,eAAS,IAAI,SAAS;AACtB,cAAQ;AAAA,QACN,wDAAwD,YAAY,SAAS,IAAI,YAAY,GAAG;AAAA,QAChG,YAAY;AAAA,MAAA;AAAA,IAEhB;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,SAAS,cAAc,WAAEJ,WAAS,OAAO;AAI/C,SAAO,UAAU,IAAI,iBAAiB;AACtCK,aAAAA,UAAU,MAAM;AACd,WAAO,UAAU,IAAI,iBAAiB;AACtC,WAAO,MAAM;AACX,aAAO,UAAU,OAAO,iBAAiB;AAAA,IAC3C;AAAA,EACF,GAAG,CAAC,QAAQ,iBAAiB,CAAC;AAE9BA,aAAAA,UAAU,MAAM;AACd,UAAM,EAAE,YAAY;AACpB,YAAQ,IAAI,aAAa,QAAQ,IAAI,UAAU,KAAK,KAAK,CAAC;AAC1D,gCAA4B;AAAA,MAC1B,SAAS,OAAO;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,IAAA,CACX,EAAE;AAAA,MAAM,CAAC,UACR,kBAAkB,EAAE,WAAW,cAAc,KAAK,YAAY,MAAA,CAAO;AAAA,IAAA;AAEvE,WAAO,MAAM;AACX,YAAM,SAAS,QAAQ,IAAI,UAAU,KAAK,KAAK;AAC/C,UAAI,UAAU,EAAG,SAAQ,OAAO,UAAU;AAAA,UACrC,SAAQ,IAAI,YAAY,KAAK;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,QAAQ,YAAY,KAAK,iBAAiB,CAAC;AAI/CA,aAAAA,UAAU,MAAM;AACd,QAAI;AACJ,QAAI,WAAW;AACf,YAAQ;AAAA,MACN,MAAM;AAAA,QACJ,wBAAwB;AAAA,QACxB,EAAE,MAAM,SAAA;AAAA,QACR,MAAM;AACJ,cAAI,SAAU;AACd,iBAAO,IAAI,QAAc,CAAC,YAAY;AACpC,sBAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MAAA;AAAA,IACF,EACA;AAAA,MAAM,CAAC,UACP,kBAAkB,EAAE,WAAW,QAAQ,KAAK,YAAY,MAAA,CAAO;AAAA,IAAA;AAEjE,WAAO,MAAM;AACX,iBAAW;AACX;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,YAAY,iBAAiB,CAAC;AAIzC,QAAM,UAAUC,WAAAA;AAAAA,IAGd,CAAC,QAAQ,YAAY;AACnB,YAAM,WAAW,gCAAgC,QAAQ,OAAO;AAChE,UAAI,SAAS,WAAW,EAAG,QAAO,SAAS;AAC3C,wBAAkB;AAAA,QAChB,WAAW;AAAA,QACX,KAAK;AAAA,QACL,OAAO,IAAI;AAAA,UACT,GAAG,SAAS,MAAM;AAAA,QAAA;AAAA,MACpB,CACD;AACD,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,CAAC,mBAAmB,UAAU;AAAA,EAAA;AAGhC,QAAM,iBAAiBC,IAAAA;AAAAA,IACrBC,+BAAuB;AAAA,MACrB,SAAS,OAAO;AAAA,MAChB,KAAK;AAAA,MACL,WAAW;AAAA,MACX,UAAUC,mBAAAA;AAAAA,MACV;AAAA,MACA,WAAW,EAAE,UAAU,KAAK,YAAY,IAAA;AAAA;AAAA;AAAA,MAGxC,SAAS,CAAC,UACR,kBAAkB,EAAE,WAAW,WAAW,KAAK,YAAY,MAAA,CAAO;AAAA,IAAA,CACrE;AAAA,EAAA;AAGH,SAAOL,WAAAA;AAAAA,IACL,OAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,OAAU,OAAyC;AACvD,YAAI,UAAU;AACd,YAAI;AACF,iBAAO,MAAM,MAAM,QAAQ,UAAU,YAAY;AAC/C,sBAAU;AACV,mBAAO,GAAA;AAAA,UACT,CAAC;AAAA,QACH,SAAS,OAAO;AACd,cAAI,QAAS,OAAM;AAInB,4BAAkB,EAAE,WAAW,QAAQ,KAAK,YAAY,OAAO;AAC/D,iBAAO,GAAA;AAAA,QACT;AAAA,MACF;AAAA,MACA,WAAW,CAAC,aAAyB;;AACnC,cAAM,YAAY,CAAC,UAA4B;AAC7C,cAAI,MAAM,QAAQ,WAAY,UAAA;AAAA,QAChC;AACA,SAAAM,MAAA,eAAe,qBAAf,gBAAAA,IAAA,qBAAkC,WAAW;AAC7C,eAAO;;AAAM,kBAAAA,MAAA,eAAe,wBAAf,gBAAAA,IAAA,qBAAqC,WAAW;AAAA;AAAA,MAC/D;AAAA,IAAA;AAAA,IAEF,CAAC,gBAAgB,OAAO,YAAY,UAAU,iBAAiB;AAAA,EAAA;AAEnE;AAGO,MAAM,+BAA+BC,IAAAA;AAAAA,EAC1C;AACF;;;;;;;;;"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function filterAndSortCatalogModels({
4
+ models,
5
+ isAdmin,
6
+ approvedModelIds,
7
+ deniedModelIds
8
+ }) {
9
+ const approved = new Set(approvedModelIds);
10
+ const denied = new Set(deniedModelIds);
11
+ const hasAllowlist = approved.size > 0;
12
+ return models.filter(
13
+ (model) => (!model.adminOnly || isAdmin) && (hasAllowlist ? approved.has(model.id) : !denied.has(model.id))
14
+ ).sort(
15
+ (left, right) => left.sortOrder - right.sortOrder || left.variantOrder - right.variantOrder || left.name.localeCompare(right.name)
16
+ );
17
+ }
18
+ function normalizeCatalogAgentOptions({
19
+ assets
20
+ }) {
21
+ return assets.filter((asset) => asset.id.trim().length > 0).map((asset) => {
22
+ var _a;
23
+ return { id: asset.id, name: ((_a = asset.title) == null ? void 0 : _a.trim()) || "Untitled agent" };
24
+ }).sort((left, right) => left.name.localeCompare(right.name));
25
+ }
26
+ function normalizeCatalogAgentModelEntries({
27
+ rows
28
+ }) {
29
+ const entries = [];
30
+ for (const row of rows) {
31
+ const model = typeof row.model === "string" ? row.model.trim() : "";
32
+ if (!model) continue;
33
+ const id = typeof row.id === "string" && row.id !== "" ? row.id : model;
34
+ const label = typeof row.label === "string" ? row.label.trim() : "";
35
+ entries.push({ id, model, label: label || model, isDefault: row.isDefault === true });
36
+ }
37
+ return entries;
38
+ }
39
+ exports.filterAndSortCatalogModels = filterAndSortCatalogModels;
40
+ exports.normalizeCatalogAgentModelEntries = normalizeCatalogAgentModelEntries;
41
+ exports.normalizeCatalogAgentOptions = normalizeCatalogAgentOptions;
42
+ //# sourceMappingURL=runtime-catalog.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-catalog.cjs","sources":["../../../../agent-runtime/src/runtime-catalog.ts"],"sourcesContent":["interface CatalogModelRow {\n id: string;\n name: string;\n adminOnly: boolean;\n sortOrder: number;\n variantOrder: number;\n}\n\n/** Workspace eligibility and display order, retaining each host's original model rows. */\nexport function filterAndSortCatalogModels<Model extends CatalogModelRow>({\n models,\n isAdmin,\n approvedModelIds,\n deniedModelIds,\n}: {\n models: readonly Model[];\n isAdmin: boolean;\n approvedModelIds: readonly string[];\n deniedModelIds: readonly string[];\n}): Model[] {\n const approved = new Set(approvedModelIds);\n const denied = new Set(deniedModelIds);\n const hasAllowlist = approved.size > 0;\n return models\n .filter(\n (model) =>\n (!model.adminOnly || isAdmin) && (hasAllowlist ? approved.has(model.id) : !denied.has(model.id)),\n )\n .sort(\n (left, right) =>\n left.sortOrder - right.sortOrder ||\n left.variantOrder - right.variantOrder ||\n left.name.localeCompare(right.name),\n );\n}\n\n/** Asset titles name picker rows; nonblank asset identifiers remain unchanged. */\nexport function normalizeCatalogAgentOptions({\n assets,\n}: {\n assets: ReadonlyArray<{ id: string; title: string | null }>;\n}): Array<{ id: string; name: string }> {\n return assets\n .filter((asset) => asset.id.trim().length > 0)\n .map((asset) => ({ id: asset.id, name: asset.title?.trim() || 'Untitled agent' }))\n .sort((left, right) => left.name.localeCompare(right.name));\n}\n\ninterface CatalogAgentModelEntry {\n id: string;\n model: string;\n label: string;\n isDefault: boolean;\n}\n\n/** Authored model entries, preserving their identifiers, duplicates and order. */\nexport function normalizeCatalogAgentModelEntries({\n rows,\n}: {\n rows: ReadonlyArray<Readonly<Record<string, unknown>>>;\n}): CatalogAgentModelEntry[] {\n const entries: CatalogAgentModelEntry[] = [];\n for (const row of rows) {\n const model = typeof row.model === 'string' ? row.model.trim() : '';\n if (!model) continue;\n const id = typeof row.id === 'string' && row.id !== '' ? row.id : model;\n const label = typeof row.label === 'string' ? row.label.trim() : '';\n entries.push({ id, model, label: label || model, isDefault: row.isDefault === true });\n }\n return entries;\n}\n"],"names":[],"mappings":";;AASO,SAAS,2BAA0D;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKY;AACV,QAAM,WAAW,IAAI,IAAI,gBAAgB;AACzC,QAAM,SAAS,IAAI,IAAI,cAAc;AACrC,QAAM,eAAe,SAAS,OAAO;AACrC,SAAO,OACJ;AAAA,IACC,CAAC,WACE,CAAC,MAAM,aAAa,aAAa,eAAe,SAAS,IAAI,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE;AAAA,EAAA,EAEjG;AAAA,IACC,CAAC,MAAM,UACL,KAAK,YAAY,MAAM,aACvB,KAAK,eAAe,MAAM,gBAC1B,KAAK,KAAK,cAAc,MAAM,IAAI;AAAA,EAAA;AAE1C;AAGO,SAAS,6BAA6B;AAAA,EAC3C;AACF,GAEwC;AACtC,SAAO,OACJ,OAAO,CAAC,UAAU,MAAM,GAAG,KAAA,EAAO,SAAS,CAAC,EAC5C,IAAI,CAAC,UAAA;;AAAW,aAAE,IAAI,MAAM,IAAI,QAAM,WAAM,UAAN,mBAAa,WAAU,iBAAA;AAAA,GAAmB,EAChF,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;AAC9D;AAUO,SAAS,kCAAkC;AAAA,EAChD;AACF,GAE6B;AAC3B,QAAM,UAAoC,CAAA;AAC1C,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,MAAM,SAAS;AACjE,QAAI,CAAC,MAAO;AACZ,UAAM,KAAK,OAAO,IAAI,OAAO,YAAY,IAAI,OAAO,KAAK,IAAI,KAAK;AAClE,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,MAAM,SAAS;AACjE,YAAQ,KAAK,EAAE,IAAI,OAAO,OAAO,SAAS,OAAO,WAAW,IAAI,cAAc,KAAA,CAAM;AAAA,EACtF;AACA,SAAO;AACT;;;;"}
@@ -0,0 +1,35 @@
1
+ interface CatalogModelRow {
2
+ id: string;
3
+ name: string;
4
+ adminOnly: boolean;
5
+ sortOrder: number;
6
+ variantOrder: number;
7
+ }
8
+ /** Workspace eligibility and display order, retaining each host's original model rows. */
9
+ export declare function filterAndSortCatalogModels<Model extends CatalogModelRow>({ models, isAdmin, approvedModelIds, deniedModelIds, }: {
10
+ models: readonly Model[];
11
+ isAdmin: boolean;
12
+ approvedModelIds: readonly string[];
13
+ deniedModelIds: readonly string[];
14
+ }): Model[];
15
+ /** Asset titles name picker rows; nonblank asset identifiers remain unchanged. */
16
+ export declare function normalizeCatalogAgentOptions({ assets, }: {
17
+ assets: ReadonlyArray<{
18
+ id: string;
19
+ title: string | null;
20
+ }>;
21
+ }): Array<{
22
+ id: string;
23
+ name: string;
24
+ }>;
25
+ interface CatalogAgentModelEntry {
26
+ id: string;
27
+ model: string;
28
+ label: string;
29
+ isDefault: boolean;
30
+ }
31
+ /** Authored model entries, preserving their identifiers, duplicates and order. */
32
+ export declare function normalizeCatalogAgentModelEntries({ rows, }: {
33
+ rows: ReadonlyArray<Readonly<Record<string, unknown>>>;
34
+ }): CatalogAgentModelEntry[];
35
+ export {};
@@ -0,0 +1,42 @@
1
+ function filterAndSortCatalogModels({
2
+ models,
3
+ isAdmin,
4
+ approvedModelIds,
5
+ deniedModelIds
6
+ }) {
7
+ const approved = new Set(approvedModelIds);
8
+ const denied = new Set(deniedModelIds);
9
+ const hasAllowlist = approved.size > 0;
10
+ return models.filter(
11
+ (model) => (!model.adminOnly || isAdmin) && (hasAllowlist ? approved.has(model.id) : !denied.has(model.id))
12
+ ).sort(
13
+ (left, right) => left.sortOrder - right.sortOrder || left.variantOrder - right.variantOrder || left.name.localeCompare(right.name)
14
+ );
15
+ }
16
+ function normalizeCatalogAgentOptions({
17
+ assets
18
+ }) {
19
+ return assets.filter((asset) => asset.id.trim().length > 0).map((asset) => {
20
+ var _a;
21
+ return { id: asset.id, name: ((_a = asset.title) == null ? void 0 : _a.trim()) || "Untitled agent" };
22
+ }).sort((left, right) => left.name.localeCompare(right.name));
23
+ }
24
+ function normalizeCatalogAgentModelEntries({
25
+ rows
26
+ }) {
27
+ const entries = [];
28
+ for (const row of rows) {
29
+ const model = typeof row.model === "string" ? row.model.trim() : "";
30
+ if (!model) continue;
31
+ const id = typeof row.id === "string" && row.id !== "" ? row.id : model;
32
+ const label = typeof row.label === "string" ? row.label.trim() : "";
33
+ entries.push({ id, model, label: label || model, isDefault: row.isDefault === true });
34
+ }
35
+ return entries;
36
+ }
37
+ export {
38
+ filterAndSortCatalogModels,
39
+ normalizeCatalogAgentModelEntries,
40
+ normalizeCatalogAgentOptions
41
+ };
42
+ //# sourceMappingURL=runtime-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-catalog.js","sources":["../../../../agent-runtime/src/runtime-catalog.ts"],"sourcesContent":["interface CatalogModelRow {\n id: string;\n name: string;\n adminOnly: boolean;\n sortOrder: number;\n variantOrder: number;\n}\n\n/** Workspace eligibility and display order, retaining each host's original model rows. */\nexport function filterAndSortCatalogModels<Model extends CatalogModelRow>({\n models,\n isAdmin,\n approvedModelIds,\n deniedModelIds,\n}: {\n models: readonly Model[];\n isAdmin: boolean;\n approvedModelIds: readonly string[];\n deniedModelIds: readonly string[];\n}): Model[] {\n const approved = new Set(approvedModelIds);\n const denied = new Set(deniedModelIds);\n const hasAllowlist = approved.size > 0;\n return models\n .filter(\n (model) =>\n (!model.adminOnly || isAdmin) && (hasAllowlist ? approved.has(model.id) : !denied.has(model.id)),\n )\n .sort(\n (left, right) =>\n left.sortOrder - right.sortOrder ||\n left.variantOrder - right.variantOrder ||\n left.name.localeCompare(right.name),\n );\n}\n\n/** Asset titles name picker rows; nonblank asset identifiers remain unchanged. */\nexport function normalizeCatalogAgentOptions({\n assets,\n}: {\n assets: ReadonlyArray<{ id: string; title: string | null }>;\n}): Array<{ id: string; name: string }> {\n return assets\n .filter((asset) => asset.id.trim().length > 0)\n .map((asset) => ({ id: asset.id, name: asset.title?.trim() || 'Untitled agent' }))\n .sort((left, right) => left.name.localeCompare(right.name));\n}\n\ninterface CatalogAgentModelEntry {\n id: string;\n model: string;\n label: string;\n isDefault: boolean;\n}\n\n/** Authored model entries, preserving their identifiers, duplicates and order. */\nexport function normalizeCatalogAgentModelEntries({\n rows,\n}: {\n rows: ReadonlyArray<Readonly<Record<string, unknown>>>;\n}): CatalogAgentModelEntry[] {\n const entries: CatalogAgentModelEntry[] = [];\n for (const row of rows) {\n const model = typeof row.model === 'string' ? row.model.trim() : '';\n if (!model) continue;\n const id = typeof row.id === 'string' && row.id !== '' ? row.id : model;\n const label = typeof row.label === 'string' ? row.label.trim() : '';\n entries.push({ id, model, label: label || model, isDefault: row.isDefault === true });\n }\n return entries;\n}\n"],"names":[],"mappings":"AASO,SAAS,2BAA0D;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKY;AACV,QAAM,WAAW,IAAI,IAAI,gBAAgB;AACzC,QAAM,SAAS,IAAI,IAAI,cAAc;AACrC,QAAM,eAAe,SAAS,OAAO;AACrC,SAAO,OACJ;AAAA,IACC,CAAC,WACE,CAAC,MAAM,aAAa,aAAa,eAAe,SAAS,IAAI,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE;AAAA,EAAA,EAEjG;AAAA,IACC,CAAC,MAAM,UACL,KAAK,YAAY,MAAM,aACvB,KAAK,eAAe,MAAM,gBAC1B,KAAK,KAAK,cAAc,MAAM,IAAI;AAAA,EAAA;AAE1C;AAGO,SAAS,6BAA6B;AAAA,EAC3C;AACF,GAEwC;AACtC,SAAO,OACJ,OAAO,CAAC,UAAU,MAAM,GAAG,KAAA,EAAO,SAAS,CAAC,EAC5C,IAAI,CAAC,UAAA;AAnCH;AAmCc,aAAE,IAAI,MAAM,IAAI,QAAM,WAAM,UAAN,mBAAa,WAAU,iBAAA;AAAA,GAAmB,EAChF,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;AAC9D;AAUO,SAAS,kCAAkC;AAAA,EAChD;AACF,GAE6B;AAC3B,QAAM,UAAoC,CAAA;AAC1C,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,MAAM,SAAS;AACjE,QAAI,CAAC,MAAO;AACZ,UAAM,KAAK,OAAO,IAAI,OAAO,YAAY,IAAI,OAAO,KAAK,IAAI,KAAK;AAClE,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,MAAM,SAAS;AACjE,YAAQ,KAAK,EAAE,IAAI,OAAO,OAAO,SAAS,OAAO,WAAW,IAAI,cAAc,KAAA,CAAM;AAAA,EACtF;AACA,SAAO;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-messages.cjs","sources":["../../../../agent-runtime/src/runtime-messages.ts"],"sourcesContent":["/**\n * Typed runtime messages — the one description of \"the runtime ended this run\"\n * that every chat surface renders from.\n *\n * The deep-agent backend records how a run ended in two shapes that ride\n * ordinary `ai` messages (a new LangChain message type would crash the shipped\n * converter, whose convertible set is closed):\n *\n * - a **run-lifecycle marker** (`athena_run_marker`: `cancelled` / `failed`,\n * plus `athena_run_marker_source`) — see {@link readRunMarkerFromSourceMessages};\n * - a **handoff message** (`athena_handoff: true`) — the closing summary the\n * runtime asked the model to write when a guard or the step budget ended the\n * run, instead of fabricating an internal sentence.\n *\n * Both now carry the canonical `athena_termination_reason`\n * (`agora/graphs/athena_deep_agent/termination.py`). This module reads all of\n * that into one {@link AthenaRuntimeMessage} so Olympus, mobile, the Chrome\n * extension, and the Office add-in agree on kind, severity, copy, and the\n * sole-vs-grouped distinction — the last of which is load-bearing: a marker\n * appended after the assistant's own work is chunked into that message, and\n * replacing the whole row would hide completed prose and tool cards.\n */\n\nimport { getExternalStoreMessages } from '@assistant-ui/core';\nimport type { LangChainMessage } from '@assistant-ui/react-langgraph';\nimport {\n ATHENA_HANDOFF_KEY,\n ATHENA_RUN_MARKER_CANCELLED,\n ATHENA_RUN_MARKER_FAILED,\n ATHENA_RUN_MARKER_KEY,\n ATHENA_RUN_MARKER_SOURCE_KEY,\n ATHENA_STOP_SOURCE_SEND_NOW,\n ATHENA_TERMINATION_REASON_KEY,\n isServerUpdateStopSource,\n} from './messages';\n\n/** The backend's canonical reason vocabulary (`KNOWN_TERMINATION_REASONS`). */\nexport const TERMINATION_REASONS = [\n 'completed',\n 'user_stop',\n 'send_now',\n 'voice_steer',\n 'transport_cancel',\n 'pod_drain',\n 'fence_lost',\n 'instance_closed',\n 'unattributed_stop',\n 'recursion_limit',\n 'step_budget',\n 'duplicate_call_guard',\n 'synthetic_stop',\n 'ended_after_tools',\n 'error',\n 'model_refusal',\n 'abandoned',\n] as const;\n\nexport type AthenaTerminationReason = (typeof TERMINATION_REASONS)[number];\n\n/**\n * How a runtime ending renders:\n * - `stopped` — a cancellation the user (or a client action) asked for;\n * - `paused` — a pod-drain pause; the run resumes from its checkpoint;\n * - `failed` — the graph raised, hit the recursion limit, or was abandoned;\n * - `handoff` — the runtime ended the run and the model wrote a closing\n * summary (the message text), which renders as prose under a banner.\n */\nexport type AthenaRuntimeMessageKind = 'stopped' | 'paused' | 'failed' | 'handoff';\n\nexport type AthenaRuntimeMessageSeverity = 'info' | 'warning' | 'error';\n\nexport interface TerminationDescription {\n /** Short label for the banner / status row. */\n title: string;\n /** One sentence of reason-specific explanation, when it adds information. */\n detail: string | undefined;\n}\n\nexport interface AthenaRuntimeMessage {\n kind: AthenaRuntimeMessageKind;\n /** Canonical reason (may be a value newer than this client knows). */\n reason: string | undefined;\n severity: AthenaRuntimeMessageSeverity;\n title: string;\n detail: string | undefined;\n /** The message's own text: a marker's backend copy, or the handoff summary. */\n text: string | undefined;\n /**\n * A `send_now` promotion cancels the live run as plumbing, not as a\n * user-visible stop: keep it in the data, paint nothing.\n */\n silent: boolean;\n /**\n * True when the runtime message is the ONLY source message behind this\n * thread message (it owns the whole row). False when the chunk also holds\n * the assistant's own work, which must keep rendering.\n */\n isSoleSourceMessage: boolean;\n}\n\nconst MAX_STEPS_HINT = 'Raise “Max steps” in the agent settings for longer runs.';\n\n/**\n * Copy for a runtime ending. Reasons this client does not know fall back to\n * the kind's generic title, so a newer backend never renders as an empty row.\n */\nexport function describeTerminationReason(\n kind: AthenaRuntimeMessageKind,\n reason: string | undefined\n): TerminationDescription {\n switch (kind) {\n case 'paused':\n return {\n title: 'Paused by a server update',\n detail: 'Progress up to this point is saved — send a message to continue.',\n };\n case 'stopped':\n switch (reason) {\n case 'voice_steer':\n return {\n title: 'Redirected by a spoken follow-up',\n detail:\n 'The voice conversation changed the request; the work continues with the new instructions.',\n };\n case 'transport_cancel':\n return {\n title: 'Run cancelled',\n detail:\n 'Cancelled by a page reload, navigation, or closed view — not an explicit Stop. Send a follow-up to continue.',\n };\n case 'fence_lost':\n return {\n title: 'Run superseded',\n detail: 'Another activation took over this thread.',\n };\n case 'instance_closed':\n return {\n title: 'Run stopped',\n detail: 'The client that started it went away.',\n };\n default:\n return { title: 'Conversation stopped', detail: undefined };\n }\n case 'failed':\n switch (reason) {\n case 'recursion_limit':\n return {\n title: 'Step limit reached',\n detail: `The run was stopped before finishing; the work so far is saved. ${MAX_STEPS_HINT}`,\n };\n case 'abandoned':\n return {\n title: 'Run stopped unexpectedly',\n detail:\n 'The server handling it went away mid-run (a crash, restart, or deploy). The work so far is saved.',\n };\n default:\n return { title: 'Run failed', detail: undefined };\n }\n case 'handoff':\n switch (reason) {\n case 'duplicate_call_guard':\n return {\n title: 'Run ended by the runtime',\n detail:\n 'The same tool calls were repeating with identical arguments and no new progress, so the agent was asked to wrap up.',\n };\n case 'step_budget':\n return {\n title: 'Run ended by the runtime',\n detail: `The step budget ran out, so the agent was asked to wrap up. ${MAX_STEPS_HINT}`,\n };\n default:\n return {\n title: 'Run ended by the runtime',\n detail: 'The agent was asked to wrap up.',\n };\n }\n }\n}\n\nconst SEVERITY: Record<AthenaRuntimeMessageKind, AthenaRuntimeMessageSeverity> = {\n stopped: 'info',\n paused: 'info',\n failed: 'error',\n handoff: 'warning',\n};\n\ntype Kwargs = Record<string, unknown> | undefined;\n\nfunction metadataOf(kwargs: Kwargs): Record<string, unknown> | undefined {\n const metadata = kwargs?.metadata;\n return typeof metadata === 'object' && metadata !== null\n ? (metadata as Record<string, unknown>)\n : undefined;\n}\n\n/** The termination reason stamped on `additional_kwargs` (top-level or mirror). */\nexport function readTerminationReason(kwargs: Kwargs): string | undefined {\n const top = kwargs?.[ATHENA_TERMINATION_REASON_KEY];\n if (typeof top === 'string') return top;\n const mirrored = metadataOf(kwargs)?.[ATHENA_TERMINATION_REASON_KEY];\n return typeof mirrored === 'string' ? mirrored : undefined;\n}\n\nfunction readHandoff(kwargs: Kwargs): boolean {\n return kwargs?.[ATHENA_HANDOFF_KEY] === true || metadataOf(kwargs)?.[ATHENA_HANDOFF_KEY] === true;\n}\n\nfunction textOf(content: unknown): string | undefined {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return undefined;\n const texts = content\n .map((block) =>\n typeof block === 'string'\n ? block\n : block && typeof block === 'object' && (block as { type?: unknown }).type === 'text'\n ? (block as { text?: unknown }).text\n : undefined\n )\n .filter((text): text is string => typeof text === 'string' && text.length > 0);\n return texts.length > 0 ? texts.join('\\n') : undefined;\n}\n\nfunction fromMarker(\n marker: string,\n source: string | undefined,\n reason: string | undefined\n): Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'> | undefined {\n if (marker === ATHENA_RUN_MARKER_CANCELLED) {\n const kind: AthenaRuntimeMessageKind = isServerUpdateStopSource(source) ? 'paused' : 'stopped';\n return {\n kind,\n reason: reason ?? (source === 'unattributed' ? 'unattributed_stop' : source),\n silent: source === ATHENA_STOP_SOURCE_SEND_NOW,\n };\n }\n if (marker === ATHENA_RUN_MARKER_FAILED) {\n return { kind: 'failed', reason: reason ?? 'error', silent: false };\n }\n return undefined;\n}\n\nfunction build(\n partial: Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'>,\n text: string | undefined,\n isSoleSourceMessage: boolean\n): AthenaRuntimeMessage {\n const description = describeTerminationReason(partial.kind, partial.reason);\n return {\n kind: partial.kind,\n reason: partial.reason,\n severity: SEVERITY[partial.kind],\n title: description.title,\n detail: description.detail,\n text,\n silent: partial.silent,\n isSoleSourceMessage,\n };\n}\n\n/**\n * Read the runtime ending behind a thread message, from its bound source\n * messages first (a marker or handoff chunked after the assistant's own turn\n * is never the first source, so the joined `metadata.custom` would miss it —\n * see {@link readRunMarkerFromSourceMessages}), then from joined metadata for\n * surfaces without bound sources.\n */\nexport function readRuntimeMessageFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n content?: unknown;\n }\n): AthenaRuntimeMessage | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (const source of sources) {\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Kwargs;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n const reason = readTerminationReason(kwargs);\n const text = textOf(source.content);\n if (typeof marker === 'string') {\n const markerSource = kwargs?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n marker,\n typeof markerSource === 'string' ? markerSource : undefined,\n reason\n );\n if (partial) return build(partial, text, sources.length === 1);\n }\n if (readHandoff(kwargs)) {\n return build({ kind: 'handoff', reason, silent: false }, text, sources.length === 1);\n }\n }\n const custom = message.metadata?.custom;\n if (!custom) return undefined;\n const parts = message.content;\n const sole = Array.isArray(parts) ? parts.length <= 1 : true;\n const joinedMarker = custom[ATHENA_RUN_MARKER_KEY];\n const joinedReason = readTerminationReason({ metadata: custom });\n if (typeof joinedMarker === 'string') {\n const joinedSource = custom[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n joinedMarker,\n typeof joinedSource === 'string' ? joinedSource : undefined,\n joinedReason\n );\n if (partial) return build(partial, undefined, sole);\n }\n if (custom[ATHENA_HANDOFF_KEY] === true) {\n return build({ kind: 'handoff', reason: joinedReason, silent: false }, undefined, sole);\n }\n return undefined;\n}\n\n/**\n * The backend marker copy worth showing under a runtime card, or `undefined`.\n *\n * A failure marker's text carries the specific error (\"The run failed:\n * provider returned 502\"), so it is shown when no reason-specific detail\n * exists. Stop/pause copy only restates the title, and a handoff's text is the\n * message body itself, so neither is repeated. Marker copy leads with an emoji\n * for raw-transcript readers; the card's icon plays that role, so it is\n * stripped. Shared by every presenter so mobile and DOM cannot drift.\n */\nexport function runtimeMessageMarkerText(message: AthenaRuntimeMessage): string | undefined {\n if (message.kind !== 'failed' || message.detail) return undefined;\n const text = message.text?.replace(/^(?:⏹️|⏸️|⚠️|\\s)+/u, '').trim();\n if (!text || text === message.title) return undefined;\n return text;\n}\n\n/**\n * The runtime message's kind when it owns the whole row, else `undefined`.\n *\n * Returns a primitive so it is safe as a `useAuiState` selector (the reader\n * above builds a fresh object per call; an object snapshot would loop the\n * render under `Object.is` comparison).\n */\nexport function readSoleRuntimeMessageKind(\n message: Parameters<typeof readRuntimeMessageFromSourceMessages>[0]\n): AthenaRuntimeMessageKind | undefined {\n const found = readRuntimeMessageFromSourceMessages(message);\n return found?.isSoleSourceMessage ? found.kind : undefined;\n}\n"],"names":["ATHENA_TERMINATION_REASON_KEY","ATHENA_HANDOFF_KEY","ATHENA_RUN_MARKER_CANCELLED","isServerUpdateStopSource","ATHENA_STOP_SOURCE_SEND_NOW","ATHENA_RUN_MARKER_FAILED","getExternalStoreMessages","ATHENA_RUN_MARKER_KEY","ATHENA_RUN_MARKER_SOURCE_KEY"],"mappings":"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"}
1
+ {"version":3,"file":"runtime-messages.cjs","sources":["../../../../agent-runtime/src/runtime-messages.ts"],"sourcesContent":["/**\n * Typed runtime messages — the one description of \"the runtime ended this run\"\n * that every chat surface renders from.\n *\n * The deep-agent backend records how a run ended in two shapes that ride\n * ordinary `ai` messages (a new LangChain message type would crash the shipped\n * converter, whose convertible set is closed):\n *\n * - a **run-lifecycle marker** (`athena_run_marker`: `cancelled` / `failed`,\n * plus `athena_run_marker_source`) — see {@link readRunMarkerFromSourceMessages};\n * - a **handoff message** (`athena_handoff: true`) — the closing summary the\n * runtime asked the model to write when a guard or the step budget ended the\n * run, instead of fabricating an internal sentence.\n *\n * Both now carry the canonical `athena_termination_reason`\n * (`agora/graphs/athena_deep_agent/termination.py`). This module reads all of\n * that into one {@link AthenaRuntimeMessage} so Olympus, mobile, the Chrome\n * extension, and the Office add-in agree on kind, severity, copy, and the\n * sole-vs-grouped distinction — the last of which is load-bearing: a marker\n * appended after the assistant's own work is chunked into that message, and\n * replacing the whole row would hide completed prose and tool cards.\n */\n\nimport { getExternalStoreMessages } from '@assistant-ui/core';\nimport type { LangChainMessage } from '@assistant-ui/react-langgraph';\nimport {\n ATHENA_HANDOFF_KEY,\n ATHENA_RUN_MARKER_CANCELLED,\n ATHENA_RUN_MARKER_FAILED,\n ATHENA_RUN_MARKER_KEY,\n ATHENA_RUN_MARKER_SOURCE_KEY,\n ATHENA_STOP_SOURCE_SEND_NOW,\n ATHENA_TERMINATION_REASON_KEY,\n isServerUpdateStopSource,\n} from './messages';\n\n/** The backend's canonical reason vocabulary (`KNOWN_TERMINATION_REASONS`). */\nexport const TERMINATION_REASONS = [\n 'completed',\n 'user_stop',\n 'send_now',\n 'voice_steer',\n 'double_text',\n 'transport_cancel',\n 'pod_drain',\n 'fence_lost',\n 'instance_closed',\n 'unattributed_stop',\n 'recursion_limit',\n 'step_budget',\n 'duplicate_call_guard',\n 'synthetic_stop',\n 'ended_after_tools',\n 'error',\n 'model_refusal',\n 'abandoned',\n] as const;\n\nexport type AthenaTerminationReason = (typeof TERMINATION_REASONS)[number];\n\n/**\n * How a runtime ending renders:\n * - `stopped` — a cancellation the user (or a client action) asked for;\n * - `paused` — a pod-drain pause; the run resumes from its checkpoint;\n * - `failed` — the graph raised, hit the recursion limit, or was abandoned;\n * - `handoff` — the runtime ended the run and the model wrote a closing\n * summary (the message text), which renders as prose under a banner.\n */\nexport type AthenaRuntimeMessageKind = 'stopped' | 'paused' | 'failed' | 'handoff';\n\nexport type AthenaRuntimeMessageSeverity = 'info' | 'warning' | 'error';\n\nexport interface TerminationDescription {\n /** Short label for the banner / status row. */\n title: string;\n /** One sentence of reason-specific explanation, when it adds information. */\n detail: string | undefined;\n}\n\nexport interface AthenaRuntimeMessage {\n kind: AthenaRuntimeMessageKind;\n /** Canonical reason (may be a value newer than this client knows). */\n reason: string | undefined;\n severity: AthenaRuntimeMessageSeverity;\n title: string;\n detail: string | undefined;\n /** The message's own text: a marker's backend copy, or the handoff summary. */\n text: string | undefined;\n /**\n * A `send_now` promotion cancels the live run as plumbing, not as a\n * user-visible stop: keep it in the data, paint nothing.\n */\n silent: boolean;\n /**\n * True when the runtime message is the ONLY source message behind this\n * thread message (it owns the whole row). False when the chunk also holds\n * the assistant's own work, which must keep rendering.\n */\n isSoleSourceMessage: boolean;\n}\n\nconst MAX_STEPS_HINT = 'Raise “Max steps” in the agent settings for longer runs.';\n\n/**\n * Copy for a runtime ending. Reasons this client does not know fall back to\n * the kind's generic title, so a newer backend never renders as an empty row.\n */\nexport function describeTerminationReason(\n kind: AthenaRuntimeMessageKind,\n reason: string | undefined\n): TerminationDescription {\n switch (kind) {\n case 'paused':\n return {\n title: 'Paused by a server update',\n detail: 'Progress up to this point is saved — send a message to continue.',\n };\n case 'stopped':\n switch (reason) {\n case 'voice_steer':\n return {\n title: 'Redirected by a spoken follow-up',\n detail:\n 'The voice conversation changed the request; the work continues with the new instructions.',\n };\n case 'transport_cancel':\n return {\n title: 'Run cancelled',\n detail:\n 'Cancelled by a page reload, navigation, or closed view — not an explicit Stop. Send a follow-up to continue.',\n };\n case 'fence_lost':\n return {\n title: 'Run superseded',\n detail: 'Another activation took over this thread.',\n };\n case 'instance_closed':\n return {\n title: 'Run stopped',\n detail: 'The client that started it went away.',\n };\n default:\n return { title: 'Conversation stopped', detail: undefined };\n }\n case 'failed':\n switch (reason) {\n case 'recursion_limit':\n return {\n title: 'Step limit reached',\n detail: `The run was stopped before finishing; the work so far is saved. ${MAX_STEPS_HINT}`,\n };\n case 'abandoned':\n return {\n title: 'Run stopped unexpectedly',\n detail:\n 'The server handling it went away mid-run (a crash, restart, or deploy). The work so far is saved.',\n };\n default:\n return { title: 'Run failed', detail: undefined };\n }\n case 'handoff':\n switch (reason) {\n case 'duplicate_call_guard':\n return {\n title: 'Run ended by the runtime',\n detail:\n 'The same tool calls were repeating with identical arguments and no new progress, so the agent was asked to wrap up.',\n };\n case 'step_budget':\n return {\n title: 'Run ended by the runtime',\n detail: `The step budget ran out, so the agent was asked to wrap up. ${MAX_STEPS_HINT}`,\n };\n default:\n return {\n title: 'Run ended by the runtime',\n detail: 'The agent was asked to wrap up.',\n };\n }\n }\n}\n\nconst SEVERITY: Record<AthenaRuntimeMessageKind, AthenaRuntimeMessageSeverity> = {\n stopped: 'info',\n paused: 'info',\n failed: 'error',\n handoff: 'warning',\n};\n\ntype Kwargs = Record<string, unknown> | undefined;\n\nfunction metadataOf(kwargs: Kwargs): Record<string, unknown> | undefined {\n const metadata = kwargs?.metadata;\n return typeof metadata === 'object' && metadata !== null\n ? (metadata as Record<string, unknown>)\n : undefined;\n}\n\n/** The termination reason stamped on `additional_kwargs` (top-level or mirror). */\nexport function readTerminationReason(kwargs: Kwargs): string | undefined {\n const top = kwargs?.[ATHENA_TERMINATION_REASON_KEY];\n if (typeof top === 'string') return top;\n const mirrored = metadataOf(kwargs)?.[ATHENA_TERMINATION_REASON_KEY];\n return typeof mirrored === 'string' ? mirrored : undefined;\n}\n\nfunction readHandoff(kwargs: Kwargs): boolean {\n return kwargs?.[ATHENA_HANDOFF_KEY] === true || metadataOf(kwargs)?.[ATHENA_HANDOFF_KEY] === true;\n}\n\nfunction textOf(content: unknown): string | undefined {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return undefined;\n const texts = content\n .map((block) =>\n typeof block === 'string'\n ? block\n : block && typeof block === 'object' && (block as { type?: unknown }).type === 'text'\n ? (block as { text?: unknown }).text\n : undefined\n )\n .filter((text): text is string => typeof text === 'string' && text.length > 0);\n return texts.length > 0 ? texts.join('\\n') : undefined;\n}\n\nfunction fromMarker(\n marker: string,\n source: string | undefined,\n reason: string | undefined\n): Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'> | undefined {\n if (marker === ATHENA_RUN_MARKER_CANCELLED) {\n const kind: AthenaRuntimeMessageKind = isServerUpdateStopSource(source) ? 'paused' : 'stopped';\n return {\n kind,\n reason: reason ?? (source === 'unattributed' ? 'unattributed_stop' : source),\n silent: source === ATHENA_STOP_SOURCE_SEND_NOW,\n };\n }\n if (marker === ATHENA_RUN_MARKER_FAILED) {\n return { kind: 'failed', reason: reason ?? 'error', silent: false };\n }\n return undefined;\n}\n\nfunction build(\n partial: Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'>,\n text: string | undefined,\n isSoleSourceMessage: boolean\n): AthenaRuntimeMessage {\n const description = describeTerminationReason(partial.kind, partial.reason);\n return {\n kind: partial.kind,\n reason: partial.reason,\n severity: SEVERITY[partial.kind],\n title: description.title,\n detail: description.detail,\n text,\n silent: partial.silent,\n isSoleSourceMessage,\n };\n}\n\n/**\n * Read the runtime ending behind a thread message, from its bound source\n * messages first (a marker or handoff chunked after the assistant's own turn\n * is never the first source, so the joined `metadata.custom` would miss it —\n * see {@link readRunMarkerFromSourceMessages}), then from joined metadata for\n * surfaces without bound sources.\n */\nexport function readRuntimeMessageFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n content?: unknown;\n }\n): AthenaRuntimeMessage | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (const source of sources) {\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Kwargs;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n const reason = readTerminationReason(kwargs);\n const text = textOf(source.content);\n if (typeof marker === 'string') {\n const markerSource = kwargs?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n marker,\n typeof markerSource === 'string' ? markerSource : undefined,\n reason\n );\n if (partial) return build(partial, text, sources.length === 1);\n }\n if (readHandoff(kwargs)) {\n return build({ kind: 'handoff', reason, silent: false }, text, sources.length === 1);\n }\n }\n const custom = message.metadata?.custom;\n if (!custom) return undefined;\n const parts = message.content;\n const sole = Array.isArray(parts) ? parts.length <= 1 : true;\n const joinedMarker = custom[ATHENA_RUN_MARKER_KEY];\n const joinedReason = readTerminationReason({ metadata: custom });\n if (typeof joinedMarker === 'string') {\n const joinedSource = custom[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n joinedMarker,\n typeof joinedSource === 'string' ? joinedSource : undefined,\n joinedReason\n );\n if (partial) return build(partial, undefined, sole);\n }\n if (custom[ATHENA_HANDOFF_KEY] === true) {\n return build({ kind: 'handoff', reason: joinedReason, silent: false }, undefined, sole);\n }\n return undefined;\n}\n\n/**\n * The backend marker copy worth showing under a runtime card, or `undefined`.\n *\n * A failure marker's text carries the specific error (\"The run failed:\n * provider returned 502\"), so it is shown when no reason-specific detail\n * exists. Stop/pause copy only restates the title, and a handoff's text is the\n * message body itself, so neither is repeated. Marker copy leads with an emoji\n * for raw-transcript readers; the card's icon plays that role, so it is\n * stripped. Shared by every presenter so mobile and DOM cannot drift.\n */\nexport function runtimeMessageMarkerText(message: AthenaRuntimeMessage): string | undefined {\n if (message.kind !== 'failed' || message.detail) return undefined;\n const text = message.text?.replace(/^(?:⏹️|⏸️|⚠️|\\s)+/u, '').trim();\n if (!text || text === message.title) return undefined;\n return text;\n}\n\n/**\n * The runtime message's kind when it owns the whole row, else `undefined`.\n *\n * Returns a primitive so it is safe as a `useAuiState` selector (the reader\n * above builds a fresh object per call; an object snapshot would loop the\n * render under `Object.is` comparison).\n */\nexport function readSoleRuntimeMessageKind(\n message: Parameters<typeof readRuntimeMessageFromSourceMessages>[0]\n): AthenaRuntimeMessageKind | undefined {\n const found = readRuntimeMessageFromSourceMessages(message);\n return found?.isSoleSourceMessage ? found.kind : undefined;\n}\n"],"names":["ATHENA_TERMINATION_REASON_KEY","ATHENA_HANDOFF_KEY","ATHENA_RUN_MARKER_CANCELLED","isServerUpdateStopSource","ATHENA_STOP_SOURCE_SEND_NOW","ATHENA_RUN_MARKER_FAILED","getExternalStoreMessages","ATHENA_RUN_MARKER_KEY","ATHENA_RUN_MARKER_SOURCE_KEY"],"mappings":"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"}
@@ -22,7 +22,7 @@
22
22
  */
23
23
  import { getExternalStoreMessages } from '@assistant-ui/core';
24
24
  /** The backend's canonical reason vocabulary (`KNOWN_TERMINATION_REASONS`). */
25
- export declare const TERMINATION_REASONS: readonly ['completed', 'user_stop', 'send_now', 'voice_steer', 'transport_cancel', 'pod_drain', 'fence_lost', 'instance_closed', 'unattributed_stop', 'recursion_limit', 'step_budget', 'duplicate_call_guard', 'synthetic_stop', 'ended_after_tools', 'error', 'model_refusal', 'abandoned'];
25
+ export declare const TERMINATION_REASONS: readonly ['completed', 'user_stop', 'send_now', 'voice_steer', 'double_text', 'transport_cancel', 'pod_drain', 'fence_lost', 'instance_closed', 'unattributed_stop', 'recursion_limit', 'step_budget', 'duplicate_call_guard', 'synthetic_stop', 'ended_after_tools', 'error', 'model_refusal', 'abandoned'];
26
26
  export type AthenaTerminationReason = (typeof TERMINATION_REASONS)[number];
27
27
  /**
28
28
  * How a runtime ending renders:
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-messages.js","sources":["../../../../agent-runtime/src/runtime-messages.ts"],"sourcesContent":["/**\n * Typed runtime messages — the one description of \"the runtime ended this run\"\n * that every chat surface renders from.\n *\n * The deep-agent backend records how a run ended in two shapes that ride\n * ordinary `ai` messages (a new LangChain message type would crash the shipped\n * converter, whose convertible set is closed):\n *\n * - a **run-lifecycle marker** (`athena_run_marker`: `cancelled` / `failed`,\n * plus `athena_run_marker_source`) — see {@link readRunMarkerFromSourceMessages};\n * - a **handoff message** (`athena_handoff: true`) — the closing summary the\n * runtime asked the model to write when a guard or the step budget ended the\n * run, instead of fabricating an internal sentence.\n *\n * Both now carry the canonical `athena_termination_reason`\n * (`agora/graphs/athena_deep_agent/termination.py`). This module reads all of\n * that into one {@link AthenaRuntimeMessage} so Olympus, mobile, the Chrome\n * extension, and the Office add-in agree on kind, severity, copy, and the\n * sole-vs-grouped distinction — the last of which is load-bearing: a marker\n * appended after the assistant's own work is chunked into that message, and\n * replacing the whole row would hide completed prose and tool cards.\n */\n\nimport { getExternalStoreMessages } from '@assistant-ui/core';\nimport type { LangChainMessage } from '@assistant-ui/react-langgraph';\nimport {\n ATHENA_HANDOFF_KEY,\n ATHENA_RUN_MARKER_CANCELLED,\n ATHENA_RUN_MARKER_FAILED,\n ATHENA_RUN_MARKER_KEY,\n ATHENA_RUN_MARKER_SOURCE_KEY,\n ATHENA_STOP_SOURCE_SEND_NOW,\n ATHENA_TERMINATION_REASON_KEY,\n isServerUpdateStopSource,\n} from './messages';\n\n/** The backend's canonical reason vocabulary (`KNOWN_TERMINATION_REASONS`). */\nexport const TERMINATION_REASONS = [\n 'completed',\n 'user_stop',\n 'send_now',\n 'voice_steer',\n 'transport_cancel',\n 'pod_drain',\n 'fence_lost',\n 'instance_closed',\n 'unattributed_stop',\n 'recursion_limit',\n 'step_budget',\n 'duplicate_call_guard',\n 'synthetic_stop',\n 'ended_after_tools',\n 'error',\n 'model_refusal',\n 'abandoned',\n] as const;\n\nexport type AthenaTerminationReason = (typeof TERMINATION_REASONS)[number];\n\n/**\n * How a runtime ending renders:\n * - `stopped` — a cancellation the user (or a client action) asked for;\n * - `paused` — a pod-drain pause; the run resumes from its checkpoint;\n * - `failed` — the graph raised, hit the recursion limit, or was abandoned;\n * - `handoff` — the runtime ended the run and the model wrote a closing\n * summary (the message text), which renders as prose under a banner.\n */\nexport type AthenaRuntimeMessageKind = 'stopped' | 'paused' | 'failed' | 'handoff';\n\nexport type AthenaRuntimeMessageSeverity = 'info' | 'warning' | 'error';\n\nexport interface TerminationDescription {\n /** Short label for the banner / status row. */\n title: string;\n /** One sentence of reason-specific explanation, when it adds information. */\n detail: string | undefined;\n}\n\nexport interface AthenaRuntimeMessage {\n kind: AthenaRuntimeMessageKind;\n /** Canonical reason (may be a value newer than this client knows). */\n reason: string | undefined;\n severity: AthenaRuntimeMessageSeverity;\n title: string;\n detail: string | undefined;\n /** The message's own text: a marker's backend copy, or the handoff summary. */\n text: string | undefined;\n /**\n * A `send_now` promotion cancels the live run as plumbing, not as a\n * user-visible stop: keep it in the data, paint nothing.\n */\n silent: boolean;\n /**\n * True when the runtime message is the ONLY source message behind this\n * thread message (it owns the whole row). False when the chunk also holds\n * the assistant's own work, which must keep rendering.\n */\n isSoleSourceMessage: boolean;\n}\n\nconst MAX_STEPS_HINT = 'Raise “Max steps” in the agent settings for longer runs.';\n\n/**\n * Copy for a runtime ending. Reasons this client does not know fall back to\n * the kind's generic title, so a newer backend never renders as an empty row.\n */\nexport function describeTerminationReason(\n kind: AthenaRuntimeMessageKind,\n reason: string | undefined\n): TerminationDescription {\n switch (kind) {\n case 'paused':\n return {\n title: 'Paused by a server update',\n detail: 'Progress up to this point is saved — send a message to continue.',\n };\n case 'stopped':\n switch (reason) {\n case 'voice_steer':\n return {\n title: 'Redirected by a spoken follow-up',\n detail:\n 'The voice conversation changed the request; the work continues with the new instructions.',\n };\n case 'transport_cancel':\n return {\n title: 'Run cancelled',\n detail:\n 'Cancelled by a page reload, navigation, or closed view — not an explicit Stop. Send a follow-up to continue.',\n };\n case 'fence_lost':\n return {\n title: 'Run superseded',\n detail: 'Another activation took over this thread.',\n };\n case 'instance_closed':\n return {\n title: 'Run stopped',\n detail: 'The client that started it went away.',\n };\n default:\n return { title: 'Conversation stopped', detail: undefined };\n }\n case 'failed':\n switch (reason) {\n case 'recursion_limit':\n return {\n title: 'Step limit reached',\n detail: `The run was stopped before finishing; the work so far is saved. ${MAX_STEPS_HINT}`,\n };\n case 'abandoned':\n return {\n title: 'Run stopped unexpectedly',\n detail:\n 'The server handling it went away mid-run (a crash, restart, or deploy). The work so far is saved.',\n };\n default:\n return { title: 'Run failed', detail: undefined };\n }\n case 'handoff':\n switch (reason) {\n case 'duplicate_call_guard':\n return {\n title: 'Run ended by the runtime',\n detail:\n 'The same tool calls were repeating with identical arguments and no new progress, so the agent was asked to wrap up.',\n };\n case 'step_budget':\n return {\n title: 'Run ended by the runtime',\n detail: `The step budget ran out, so the agent was asked to wrap up. ${MAX_STEPS_HINT}`,\n };\n default:\n return {\n title: 'Run ended by the runtime',\n detail: 'The agent was asked to wrap up.',\n };\n }\n }\n}\n\nconst SEVERITY: Record<AthenaRuntimeMessageKind, AthenaRuntimeMessageSeverity> = {\n stopped: 'info',\n paused: 'info',\n failed: 'error',\n handoff: 'warning',\n};\n\ntype Kwargs = Record<string, unknown> | undefined;\n\nfunction metadataOf(kwargs: Kwargs): Record<string, unknown> | undefined {\n const metadata = kwargs?.metadata;\n return typeof metadata === 'object' && metadata !== null\n ? (metadata as Record<string, unknown>)\n : undefined;\n}\n\n/** The termination reason stamped on `additional_kwargs` (top-level or mirror). */\nexport function readTerminationReason(kwargs: Kwargs): string | undefined {\n const top = kwargs?.[ATHENA_TERMINATION_REASON_KEY];\n if (typeof top === 'string') return top;\n const mirrored = metadataOf(kwargs)?.[ATHENA_TERMINATION_REASON_KEY];\n return typeof mirrored === 'string' ? mirrored : undefined;\n}\n\nfunction readHandoff(kwargs: Kwargs): boolean {\n return kwargs?.[ATHENA_HANDOFF_KEY] === true || metadataOf(kwargs)?.[ATHENA_HANDOFF_KEY] === true;\n}\n\nfunction textOf(content: unknown): string | undefined {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return undefined;\n const texts = content\n .map((block) =>\n typeof block === 'string'\n ? block\n : block && typeof block === 'object' && (block as { type?: unknown }).type === 'text'\n ? (block as { text?: unknown }).text\n : undefined\n )\n .filter((text): text is string => typeof text === 'string' && text.length > 0);\n return texts.length > 0 ? texts.join('\\n') : undefined;\n}\n\nfunction fromMarker(\n marker: string,\n source: string | undefined,\n reason: string | undefined\n): Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'> | undefined {\n if (marker === ATHENA_RUN_MARKER_CANCELLED) {\n const kind: AthenaRuntimeMessageKind = isServerUpdateStopSource(source) ? 'paused' : 'stopped';\n return {\n kind,\n reason: reason ?? (source === 'unattributed' ? 'unattributed_stop' : source),\n silent: source === ATHENA_STOP_SOURCE_SEND_NOW,\n };\n }\n if (marker === ATHENA_RUN_MARKER_FAILED) {\n return { kind: 'failed', reason: reason ?? 'error', silent: false };\n }\n return undefined;\n}\n\nfunction build(\n partial: Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'>,\n text: string | undefined,\n isSoleSourceMessage: boolean\n): AthenaRuntimeMessage {\n const description = describeTerminationReason(partial.kind, partial.reason);\n return {\n kind: partial.kind,\n reason: partial.reason,\n severity: SEVERITY[partial.kind],\n title: description.title,\n detail: description.detail,\n text,\n silent: partial.silent,\n isSoleSourceMessage,\n };\n}\n\n/**\n * Read the runtime ending behind a thread message, from its bound source\n * messages first (a marker or handoff chunked after the assistant's own turn\n * is never the first source, so the joined `metadata.custom` would miss it —\n * see {@link readRunMarkerFromSourceMessages}), then from joined metadata for\n * surfaces without bound sources.\n */\nexport function readRuntimeMessageFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n content?: unknown;\n }\n): AthenaRuntimeMessage | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (const source of sources) {\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Kwargs;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n const reason = readTerminationReason(kwargs);\n const text = textOf(source.content);\n if (typeof marker === 'string') {\n const markerSource = kwargs?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n marker,\n typeof markerSource === 'string' ? markerSource : undefined,\n reason\n );\n if (partial) return build(partial, text, sources.length === 1);\n }\n if (readHandoff(kwargs)) {\n return build({ kind: 'handoff', reason, silent: false }, text, sources.length === 1);\n }\n }\n const custom = message.metadata?.custom;\n if (!custom) return undefined;\n const parts = message.content;\n const sole = Array.isArray(parts) ? parts.length <= 1 : true;\n const joinedMarker = custom[ATHENA_RUN_MARKER_KEY];\n const joinedReason = readTerminationReason({ metadata: custom });\n if (typeof joinedMarker === 'string') {\n const joinedSource = custom[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n joinedMarker,\n typeof joinedSource === 'string' ? joinedSource : undefined,\n joinedReason\n );\n if (partial) return build(partial, undefined, sole);\n }\n if (custom[ATHENA_HANDOFF_KEY] === true) {\n return build({ kind: 'handoff', reason: joinedReason, silent: false }, undefined, sole);\n }\n return undefined;\n}\n\n/**\n * The backend marker copy worth showing under a runtime card, or `undefined`.\n *\n * A failure marker's text carries the specific error (\"The run failed:\n * provider returned 502\"), so it is shown when no reason-specific detail\n * exists. Stop/pause copy only restates the title, and a handoff's text is the\n * message body itself, so neither is repeated. Marker copy leads with an emoji\n * for raw-transcript readers; the card's icon plays that role, so it is\n * stripped. Shared by every presenter so mobile and DOM cannot drift.\n */\nexport function runtimeMessageMarkerText(message: AthenaRuntimeMessage): string | undefined {\n if (message.kind !== 'failed' || message.detail) return undefined;\n const text = message.text?.replace(/^(?:⏹️|⏸️|⚠️|\\s)+/u, '').trim();\n if (!text || text === message.title) return undefined;\n return text;\n}\n\n/**\n * The runtime message's kind when it owns the whole row, else `undefined`.\n *\n * Returns a primitive so it is safe as a `useAuiState` selector (the reader\n * above builds a fresh object per call; an object snapshot would loop the\n * render under `Object.is` comparison).\n */\nexport function readSoleRuntimeMessageKind(\n message: Parameters<typeof readRuntimeMessageFromSourceMessages>[0]\n): AthenaRuntimeMessageKind | undefined {\n const found = readRuntimeMessageFromSourceMessages(message);\n return found?.isSoleSourceMessage ? found.kind : undefined;\n}\n"],"names":[],"mappings":";;AAoGA,MAAM,iBAAiB;AAMhB,SAAS,0BACd,MACA,QACwB;AACxB,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,MAAA;AAAA,IAEZ,KAAK;AACH,cAAQ,QAAA;AAAA,QACN,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QACE;AAAA,UAAA;AAAA,QAEN,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QACE;AAAA,UAAA;AAAA,QAEN,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA;AAAA,QAEZ,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA;AAAA,QAEZ;AACE,iBAAO,EAAE,OAAO,wBAAwB,QAAQ,OAAA;AAAA,MAAU;AAAA,IAEhE,KAAK;AACH,cAAQ,QAAA;AAAA,QACN,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ,mEAAmE,cAAc;AAAA,UAAA;AAAA,QAE7F,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QACE;AAAA,UAAA;AAAA,QAEN;AACE,iBAAO,EAAE,OAAO,cAAc,QAAQ,OAAA;AAAA,MAAU;AAAA,IAEtD,KAAK;AACH,cAAQ,QAAA;AAAA,QACN,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QACE;AAAA,UAAA;AAAA,QAEN,KAAK;AACH,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ,+DAA+D,cAAc;AAAA,UAAA;AAAA,QAEzF;AACE,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA;AAAA,MACV;AAAA,EACJ;AAEN;AAEA,MAAM,WAA2E;AAAA,EAC/E,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;AAIA,SAAS,WAAW,QAAqD;AACvE,QAAM,WAAW,iCAAQ;AACzB,SAAO,OAAO,aAAa,YAAY,aAAa,OAC/C,WACD;AACN;AAGO,SAAS,sBAAsB,QAAoC;;AACxE,QAAM,MAAM,iCAAS;AACrB,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,YAAW,gBAAW,MAAM,MAAjB,mBAAqB;AACtC,SAAO,OAAO,aAAa,WAAW,WAAW;AACnD;AAEA,SAAS,YAAY,QAAyB;;AAC5C,UAAO,iCAAS,yBAAwB,UAAQ,gBAAW,MAAM,MAAjB,mBAAqB,yBAAwB;AAC/F;AAEA,SAAS,OAAO,SAAsC;AACpD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,QAAM,QAAQ,QACX;AAAA,IAAI,CAAC,UACJ,OAAO,UAAU,WACb,QACA,SAAS,OAAO,UAAU,YAAa,MAA6B,SAAS,SAC1E,MAA6B,OAC9B;AAAA,EAAA,EAEP,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS,CAAC;AAC/E,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAC/C;AAEA,SAAS,WACP,QACA,QACA,QACsE;AACtE,MAAI,WAAW,6BAA6B;AAC1C,UAAM,OAAiC,yBAAyB,MAAM,IAAI,WAAW;AACrF,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,WAAW,WAAW,iBAAiB,sBAAsB;AAAA,MACrE,QAAQ,WAAW;AAAA,IAAA;AAAA,EAEvB;AACA,MAAI,WAAW,0BAA0B;AACvC,WAAO,EAAE,MAAM,UAAU,QAAQ,UAAU,SAAS,QAAQ,MAAA;AAAA,EAC9D;AACA,SAAO;AACT;AAEA,SAAS,MACP,SACA,MACA,qBACsB;AACtB,QAAM,cAAc,0BAA0B,QAAQ,MAAM,QAAQ,MAAM;AAC1E,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,UAAU,SAAS,QAAQ,IAAI;AAAA,IAC/B,OAAO,YAAY;AAAA,IACnB,QAAQ,YAAY;AAAA,IACpB;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB;AAAA,EAAA;AAEJ;AASO,SAAS,qCACd,SAIkC;;AAClC,QAAM,UAAU,yBAA2C,OAAO;AAClE,aAAW,UAAU,SAAS;AAC5B,SAAI,iCAAQ,UAAS,KAAM;AAC3B,UAAM,SAAS,OAAO;AACtB,UAAM,SAAS,iCAAS;AACxB,UAAM,SAAS,sBAAsB,MAAM;AAC3C,UAAM,OAAO,OAAO,OAAO,OAAO;AAClC,QAAI,OAAO,WAAW,UAAU;AAC9B,YAAM,eAAe,iCAAS;AAC9B,YAAM,UAAU;AAAA,QACd;AAAA,QACA,OAAO,iBAAiB,WAAW,eAAe;AAAA,QAClD;AAAA,MAAA;AAEF,UAAI,QAAS,QAAO,MAAM,SAAS,MAAM,QAAQ,WAAW,CAAC;AAAA,IAC/D;AACA,QAAI,YAAY,MAAM,GAAG;AACvB,aAAO,MAAM,EAAE,MAAM,WAAW,QAAQ,QAAQ,MAAA,GAAS,MAAM,QAAQ,WAAW,CAAC;AAAA,IACrF;AAAA,EACF;AACA,QAAM,UAAS,aAAQ,aAAR,mBAAkB;AACjC,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,QAAQ;AACtB,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,UAAU,IAAI;AACxD,QAAM,eAAe,OAAO,qBAAqB;AACjD,QAAM,eAAe,sBAAsB,EAAE,UAAU,QAAQ;AAC/D,MAAI,OAAO,iBAAiB,UAAU;AACpC,UAAM,eAAe,OAAO,4BAA4B;AACxD,UAAM,UAAU;AAAA,MACd;AAAA,MACA,OAAO,iBAAiB,WAAW,eAAe;AAAA,MAClD;AAAA,IAAA;AAEF,QAAI,QAAS,QAAO,MAAM,SAAS,QAAW,IAAI;AAAA,EACpD;AACA,MAAI,OAAO,kBAAkB,MAAM,MAAM;AACvC,WAAO,MAAM,EAAE,MAAM,WAAW,QAAQ,cAAc,QAAQ,MAAA,GAAS,QAAW,IAAI;AAAA,EACxF;AACA,SAAO;AACT;AAYO,SAAS,yBAAyB,SAAmD;;AAC1F,MAAI,QAAQ,SAAS,YAAY,QAAQ,OAAQ,QAAO;AACxD,QAAM,QAAO,aAAQ,SAAR,mBAAc,QAAQ,sBAAsB,IAAI;AAC7D,MAAI,CAAC,QAAQ,SAAS,QAAQ,MAAO,QAAO;AAC5C,SAAO;AACT;AASO,SAAS,2BACd,SACsC;AACtC,QAAM,QAAQ,qCAAqC,OAAO;AAC1D,UAAO,+BAAO,uBAAsB,MAAM,OAAO;AACnD;"}
1
+ {"version":3,"file":"runtime-messages.js","sources":["../../../../agent-runtime/src/runtime-messages.ts"],"sourcesContent":["/**\n * Typed runtime messages — the one description of \"the runtime ended this run\"\n * that every chat surface renders from.\n *\n * The deep-agent backend records how a run ended in two shapes that ride\n * ordinary `ai` messages (a new LangChain message type would crash the shipped\n * converter, whose convertible set is closed):\n *\n * - a **run-lifecycle marker** (`athena_run_marker`: `cancelled` / `failed`,\n * plus `athena_run_marker_source`) — see {@link readRunMarkerFromSourceMessages};\n * - a **handoff message** (`athena_handoff: true`) — the closing summary the\n * runtime asked the model to write when a guard or the step budget ended the\n * run, instead of fabricating an internal sentence.\n *\n * Both now carry the canonical `athena_termination_reason`\n * (`agora/graphs/athena_deep_agent/termination.py`). This module reads all of\n * that into one {@link AthenaRuntimeMessage} so Olympus, mobile, the Chrome\n * extension, and the Office add-in agree on kind, severity, copy, and the\n * sole-vs-grouped distinction — the last of which is load-bearing: a marker\n * appended after the assistant's own work is chunked into that message, and\n * replacing the whole row would hide completed prose and tool cards.\n */\n\nimport { getExternalStoreMessages } from '@assistant-ui/core';\nimport type { LangChainMessage } from '@assistant-ui/react-langgraph';\nimport {\n ATHENA_HANDOFF_KEY,\n ATHENA_RUN_MARKER_CANCELLED,\n ATHENA_RUN_MARKER_FAILED,\n ATHENA_RUN_MARKER_KEY,\n ATHENA_RUN_MARKER_SOURCE_KEY,\n ATHENA_STOP_SOURCE_SEND_NOW,\n ATHENA_TERMINATION_REASON_KEY,\n isServerUpdateStopSource,\n} from './messages';\n\n/** The backend's canonical reason vocabulary (`KNOWN_TERMINATION_REASONS`). */\nexport const TERMINATION_REASONS = [\n 'completed',\n 'user_stop',\n 'send_now',\n 'voice_steer',\n 'double_text',\n 'transport_cancel',\n 'pod_drain',\n 'fence_lost',\n 'instance_closed',\n 'unattributed_stop',\n 'recursion_limit',\n 'step_budget',\n 'duplicate_call_guard',\n 'synthetic_stop',\n 'ended_after_tools',\n 'error',\n 'model_refusal',\n 'abandoned',\n] as const;\n\nexport type AthenaTerminationReason = (typeof TERMINATION_REASONS)[number];\n\n/**\n * How a runtime ending renders:\n * - `stopped` — a cancellation the user (or a client action) asked for;\n * - `paused` — a pod-drain pause; the run resumes from its checkpoint;\n * - `failed` — the graph raised, hit the recursion limit, or was abandoned;\n * - `handoff` — the runtime ended the run and the model wrote a closing\n * summary (the message text), which renders as prose under a banner.\n */\nexport type AthenaRuntimeMessageKind = 'stopped' | 'paused' | 'failed' | 'handoff';\n\nexport type AthenaRuntimeMessageSeverity = 'info' | 'warning' | 'error';\n\nexport interface TerminationDescription {\n /** Short label for the banner / status row. */\n title: string;\n /** One sentence of reason-specific explanation, when it adds information. */\n detail: string | undefined;\n}\n\nexport interface AthenaRuntimeMessage {\n kind: AthenaRuntimeMessageKind;\n /** Canonical reason (may be a value newer than this client knows). */\n reason: string | undefined;\n severity: AthenaRuntimeMessageSeverity;\n title: string;\n detail: string | undefined;\n /** The message's own text: a marker's backend copy, or the handoff summary. */\n text: string | undefined;\n /**\n * A `send_now` promotion cancels the live run as plumbing, not as a\n * user-visible stop: keep it in the data, paint nothing.\n */\n silent: boolean;\n /**\n * True when the runtime message is the ONLY source message behind this\n * thread message (it owns the whole row). False when the chunk also holds\n * the assistant's own work, which must keep rendering.\n */\n isSoleSourceMessage: boolean;\n}\n\nconst MAX_STEPS_HINT = 'Raise “Max steps” in the agent settings for longer runs.';\n\n/**\n * Copy for a runtime ending. Reasons this client does not know fall back to\n * the kind's generic title, so a newer backend never renders as an empty row.\n */\nexport function describeTerminationReason(\n kind: AthenaRuntimeMessageKind,\n reason: string | undefined\n): TerminationDescription {\n switch (kind) {\n case 'paused':\n return {\n title: 'Paused by a server update',\n detail: 'Progress up to this point is saved — send a message to continue.',\n };\n case 'stopped':\n switch (reason) {\n case 'voice_steer':\n return {\n title: 'Redirected by a spoken follow-up',\n detail:\n 'The voice conversation changed the request; the work continues with the new instructions.',\n };\n case 'transport_cancel':\n return {\n title: 'Run cancelled',\n detail:\n 'Cancelled by a page reload, navigation, or closed view — not an explicit Stop. Send a follow-up to continue.',\n };\n case 'fence_lost':\n return {\n title: 'Run superseded',\n detail: 'Another activation took over this thread.',\n };\n case 'instance_closed':\n return {\n title: 'Run stopped',\n detail: 'The client that started it went away.',\n };\n default:\n return { title: 'Conversation stopped', detail: undefined };\n }\n case 'failed':\n switch (reason) {\n case 'recursion_limit':\n return {\n title: 'Step limit reached',\n detail: `The run was stopped before finishing; the work so far is saved. ${MAX_STEPS_HINT}`,\n };\n case 'abandoned':\n return {\n title: 'Run stopped unexpectedly',\n detail:\n 'The server handling it went away mid-run (a crash, restart, or deploy). The work so far is saved.',\n };\n default:\n return { title: 'Run failed', detail: undefined };\n }\n case 'handoff':\n switch (reason) {\n case 'duplicate_call_guard':\n return {\n title: 'Run ended by the runtime',\n detail:\n 'The same tool calls were repeating with identical arguments and no new progress, so the agent was asked to wrap up.',\n };\n case 'step_budget':\n return {\n title: 'Run ended by the runtime',\n detail: `The step budget ran out, so the agent was asked to wrap up. ${MAX_STEPS_HINT}`,\n };\n default:\n return {\n title: 'Run ended by the runtime',\n detail: 'The agent was asked to wrap up.',\n };\n }\n }\n}\n\nconst SEVERITY: Record<AthenaRuntimeMessageKind, AthenaRuntimeMessageSeverity> = {\n stopped: 'info',\n paused: 'info',\n failed: 'error',\n handoff: 'warning',\n};\n\ntype Kwargs = Record<string, unknown> | undefined;\n\nfunction metadataOf(kwargs: Kwargs): Record<string, unknown> | undefined {\n const metadata = kwargs?.metadata;\n return typeof metadata === 'object' && metadata !== null\n ? (metadata as Record<string, unknown>)\n : undefined;\n}\n\n/** The termination reason stamped on `additional_kwargs` (top-level or mirror). */\nexport function readTerminationReason(kwargs: Kwargs): string | undefined {\n const top = kwargs?.[ATHENA_TERMINATION_REASON_KEY];\n if (typeof top === 'string') return top;\n const mirrored = metadataOf(kwargs)?.[ATHENA_TERMINATION_REASON_KEY];\n return typeof mirrored === 'string' ? mirrored : undefined;\n}\n\nfunction readHandoff(kwargs: Kwargs): boolean {\n return kwargs?.[ATHENA_HANDOFF_KEY] === true || metadataOf(kwargs)?.[ATHENA_HANDOFF_KEY] === true;\n}\n\nfunction textOf(content: unknown): string | undefined {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return undefined;\n const texts = content\n .map((block) =>\n typeof block === 'string'\n ? block\n : block && typeof block === 'object' && (block as { type?: unknown }).type === 'text'\n ? (block as { text?: unknown }).text\n : undefined\n )\n .filter((text): text is string => typeof text === 'string' && text.length > 0);\n return texts.length > 0 ? texts.join('\\n') : undefined;\n}\n\nfunction fromMarker(\n marker: string,\n source: string | undefined,\n reason: string | undefined\n): Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'> | undefined {\n if (marker === ATHENA_RUN_MARKER_CANCELLED) {\n const kind: AthenaRuntimeMessageKind = isServerUpdateStopSource(source) ? 'paused' : 'stopped';\n return {\n kind,\n reason: reason ?? (source === 'unattributed' ? 'unattributed_stop' : source),\n silent: source === ATHENA_STOP_SOURCE_SEND_NOW,\n };\n }\n if (marker === ATHENA_RUN_MARKER_FAILED) {\n return { kind: 'failed', reason: reason ?? 'error', silent: false };\n }\n return undefined;\n}\n\nfunction build(\n partial: Pick<AthenaRuntimeMessage, 'kind' | 'reason' | 'silent'>,\n text: string | undefined,\n isSoleSourceMessage: boolean\n): AthenaRuntimeMessage {\n const description = describeTerminationReason(partial.kind, partial.reason);\n return {\n kind: partial.kind,\n reason: partial.reason,\n severity: SEVERITY[partial.kind],\n title: description.title,\n detail: description.detail,\n text,\n silent: partial.silent,\n isSoleSourceMessage,\n };\n}\n\n/**\n * Read the runtime ending behind a thread message, from its bound source\n * messages first (a marker or handoff chunked after the assistant's own turn\n * is never the first source, so the joined `metadata.custom` would miss it —\n * see {@link readRunMarkerFromSourceMessages}), then from joined metadata for\n * surfaces without bound sources.\n */\nexport function readRuntimeMessageFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n content?: unknown;\n }\n): AthenaRuntimeMessage | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (const source of sources) {\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Kwargs;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n const reason = readTerminationReason(kwargs);\n const text = textOf(source.content);\n if (typeof marker === 'string') {\n const markerSource = kwargs?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n marker,\n typeof markerSource === 'string' ? markerSource : undefined,\n reason\n );\n if (partial) return build(partial, text, sources.length === 1);\n }\n if (readHandoff(kwargs)) {\n return build({ kind: 'handoff', reason, silent: false }, text, sources.length === 1);\n }\n }\n const custom = message.metadata?.custom;\n if (!custom) return undefined;\n const parts = message.content;\n const sole = Array.isArray(parts) ? parts.length <= 1 : true;\n const joinedMarker = custom[ATHENA_RUN_MARKER_KEY];\n const joinedReason = readTerminationReason({ metadata: custom });\n if (typeof joinedMarker === 'string') {\n const joinedSource = custom[ATHENA_RUN_MARKER_SOURCE_KEY];\n const partial = fromMarker(\n joinedMarker,\n typeof joinedSource === 'string' ? joinedSource : undefined,\n joinedReason\n );\n if (partial) return build(partial, undefined, sole);\n }\n if (custom[ATHENA_HANDOFF_KEY] === true) {\n return build({ kind: 'handoff', reason: joinedReason, silent: false }, undefined, sole);\n }\n return undefined;\n}\n\n/**\n * The backend marker copy worth showing under a runtime card, or `undefined`.\n *\n * A failure marker's text carries the specific error (\"The run failed:\n * provider returned 502\"), so it is shown when no reason-specific detail\n * exists. Stop/pause copy only restates the title, and a handoff's text is the\n * message body itself, so neither is repeated. Marker copy leads with an emoji\n * for raw-transcript readers; the card's icon plays that role, so it is\n * stripped. Shared by every presenter so mobile and DOM cannot drift.\n */\nexport function runtimeMessageMarkerText(message: AthenaRuntimeMessage): string | undefined {\n if (message.kind !== 'failed' || message.detail) return undefined;\n const text = message.text?.replace(/^(?:⏹️|⏸️|⚠️|\\s)+/u, '').trim();\n if (!text || text === message.title) return undefined;\n return text;\n}\n\n/**\n * The runtime message's kind when it owns the whole row, else `undefined`.\n *\n * Returns a primitive so it is safe as a `useAuiState` selector (the reader\n * above builds a fresh object per call; an object snapshot would loop the\n * render under `Object.is` comparison).\n */\nexport function readSoleRuntimeMessageKind(\n message: Parameters<typeof readRuntimeMessageFromSourceMessages>[0]\n): AthenaRuntimeMessageKind | undefined {\n const found = readRuntimeMessageFromSourceMessages(message);\n return found?.isSoleSourceMessage ? found.kind : undefined;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /** Shared chat runtime exports, without initializing optional handoff controllers. */
2
+ export { answerLabelText, type DeepAgentAnsweredBy, readMessageAnswers, showsAnswerLabel, threadShowsAnswerLabels, } from "./answer-label";
3
+ export { type ChatAssetUploadResponse, uploadChatAsset, uploadedChatAsset, } from "./asset-attachment";
4
+ export { CHAT_EDIT_UNREACHABLE_LABEL, CHAT_OUTBOX_ASK_AFTER_MS, CHAT_OUTBOX_CLAIM_LEASE_MS, type ChatOutbox, type ChatOutboxEvent, type ChatOutboxRow, } from "./chat-outbox";
5
+ export { type ChatOutboxAttachmentCheck, chatOutboxAttachmentPath, createChatOutboxAttachmentCheck, } from "./chat-outbox-attachments";
6
+ export { type ChatOutboxRecord, createMemoryChatOutboxStore, parseChatOutboxEntry, readChatOutboxClaim, readChatOutboxFailure, withChatOutboxMemoryFallback, } from "./chat-outbox-store";
7
+ export { type ClientToolBridgeTool, useStatewireClientToolBridge, } from "./client-tool-bridge";
8
+ export { createClientToolRequestTracker } from "./client-tools";
9
+ export { pickThreadConfigCustom, type ThreadConfigPatch, } from "./config-mutations";
10
+ export { type ConversationIndexEntry, conversationIndexFingerprint, useConversationIndex, } from "./conversation-index";
11
+ export { type ConversationListPage, type ConversationSummary, mergeConversationIndexIntoPage, } from "./conversation-list";
12
+ export { isLegacyThreadReadOnlyRejection, isStatewireChannelTeardown, isStatewireRewindAnchorRejection, statewireRejectionDetailMessage, statewireRejectionPayload, } from "./errors";
13
+ export { asHitlApproval, findAbandonedInterrupt, HITL_PENDING_RESUME_GRACE_MS, type HitlApprovalPayload, hitlResumeApprove, hitlResumeReject, interruptResumeDecline, isApprovalCardInterrupt, readAbandonedInputRequests, readInterruptMessage, useApprovalResumeLock, } from "./interrupts";
14
+ export { type DeepAgentMessageWindowDeclaration } from "./message-window";
15
+ export { ATHENA_RUN_MARKER_KEY, isQueuedLaneMessage, } from "./messages";
16
+ export { isDeepAgentHostState } from "./protocol";
17
+ export { parkIncompatibleSessionCommands } from "./quota-safe-local-storage-session";
18
+ export { type AthenaRuntimeMessageKind, readRuntimeMessageFromSourceMessages, readSoleRuntimeMessageKind, runtimeMessageMarkerText, } from "./runtime-messages";
19
+ export { createStatewireDiagnosticsRecorder } from "./statewire-diagnostics";
20
+ export { isDeepAgentStateHydrated } from "./statewire-state";
21
+ export { DEEP_AGENT_STATEWIRE_PROTOCOL } from "./statewire-transport";
22
+ export { hideUnterminatedMarkdownLink } from "./streaming-markdown";
23
+ export { nestedMessagesFromArtifact } from "./subagents";
24
+ export { hasStatewireThreadExtras } from "./thread-extras";
25
+ export { createDeepAgentThreadSnapshotCache, type DeepAgentThreadSnapshotCache, } from "./thread-snapshot-cache";
26
+ export { useDeepAgentThreadStatus } from "./thread-status";
27
+ export { describeToolArgs, formatToolName, getCategoryEmoji, getToolDisplayMeta, knownToolNames, } from "./tool-metadata";
28
+ export { createDeepAgentToolOutputStore, type DeepAgentToolOutputStore, } from "./tool-outputs";
29
+ export { classifyToolResult } from "./tool-result";
30
+ export { type DeepAgentConnectionState, type DeepAgentStreamValues, } from "./types";
31
+ export { DeepAgentChatOutboxContext, useChatOutboxReachable, useChatOutboxSnapshot, useDeepAgentChatOutbox, useDeepAgentChatOutboxContext, } from "./use-deep-agent-chat-outbox";
32
+ export { type DeepAgentConfigWriteResult, isConfigWriteForbiddenRejection, useDeepAgentConfig, } from "./use-deep-agent-config";
33
+ export { useDeepAgentMessageEditSubmit } from "./use-deep-agent-edit-submit";
34
+ export { type DeepAgentThreadElement, logUnhandledStatewireError, useDeepAgentRuntime, } from "./use-deep-agent-runtime";
35
+ export { describeVoiceFailure, describeVoiceLiveElsewhere, type DeepAgentVoiceSurface, useDeepAgentVoice, type UseDeepAgentVoiceReturn, useVoiceElapsed, useVoiceMovedNotice, VOICE_CONTINUE_BY_VOICE_LABEL, VOICE_MOVE_CALL_HERE_LABEL, VOICE_MOVE_HERE_ACTION, } from "./use-deep-agent-voice";
36
+ export { useDeepAgentWindowSync } from "./use-deep-agent-window-sync";
37
+ export { describeVoiceUpdateToolCall, isVoiceDelegationMessage, VOICE_LIVE_TYPED_HINT, VOICE_UPDATE_TOOL_NAME, voiceProvenanceLabel, voiceUpdateStatusLabel, } from "./voice-presentation";
38
+ export { type ResumeExtras } from "./interrupts";
39
+ export { resumeValueApproves } from "./interrupts";
40
+ export { statewireAnswerDescriptors } from "./decision-checks";
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const tap = require("@assistant-ui/tap");
4
- const react = require("react");
4
+ const require$$0 = require("react");
5
5
  const statewire = require("statewire");
6
6
  const suspendedCommands = () => new Proxy({}, {
7
7
  get: (_target, method) => {
@@ -10,9 +10,9 @@ const suspendedCommands = () => new Proxy({}, {
10
10
  }
11
11
  });
12
12
  const useSuspendedStatewire = (options) => {
13
- const latest = react.useRef(options);
13
+ const latest = require$$0.useRef(options);
14
14
  latest.current = options;
15
- const [value] = react.useState(() => {
15
+ const [value] = require$$0.useState(() => {
16
16
  const connection = {
17
17
  status: "standby",
18
18
  reason: "deferred",