@athenaintel/react 0.20.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/README.md +86 -0
  2. package/dist/assets/use-asset-embed.cjs +8 -0
  3. package/dist/assets/use-asset-embed.cjs.map +1 -1
  4. package/dist/assets/use-asset-embed.js +8 -0
  5. package/dist/assets/use-asset-embed.js.map +1 -1
  6. package/dist/chat/StatewireApprovalCard.cjs +22 -4
  7. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  8. package/dist/chat/StatewireApprovalCard.d.ts +14 -0
  9. package/dist/chat/StatewireApprovalCard.js +23 -5
  10. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  11. package/dist/chat/StatewireClientToolBridge.cjs +2 -1
  12. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  13. package/dist/chat/StatewireClientToolBridge.js +2 -1
  14. package/dist/chat/StatewireClientToolBridge.js.map +1 -1
  15. package/dist/chat/StatewireQueuedMessages.cjs +2 -1
  16. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  17. package/dist/chat/StatewireQueuedMessages.js +2 -1
  18. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  19. package/dist/chat/athena-citation-links.cjs +17 -1
  20. package/dist/chat/athena-citation-links.cjs.map +1 -1
  21. package/dist/chat/athena-citation-links.js +17 -1
  22. package/dist/chat/athena-citation-links.js.map +1 -1
  23. package/dist/chat/statewire-client-tools.cjs +2 -1
  24. package/dist/chat/statewire-client-tools.cjs.map +1 -1
  25. package/dist/chat/statewire-client-tools.js +2 -1
  26. package/dist/chat/statewire-client-tools.js.map +1 -1
  27. package/dist/chat/super-grouping/SuperGroupingCard.cjs +69 -187
  28. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  29. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +10 -6
  30. package/dist/chat/super-grouping/SuperGroupingCard.js +73 -191
  31. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  32. package/dist/chat/super-grouping/ToolTimeline.cjs +131 -0
  33. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -0
  34. package/dist/chat/super-grouping/ToolTimeline.d.ts +16 -0
  35. package/dist/chat/super-grouping/ToolTimeline.js +131 -0
  36. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -0
  37. package/dist/chat/super-grouping/activity-timeline.cjs +14 -8
  38. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  39. package/dist/chat/super-grouping/activity-timeline.d.ts +3 -0
  40. package/dist/chat/super-grouping/activity-timeline.js +14 -8
  41. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  42. package/dist/chat/super-grouping/timeline-step.cjs +65 -0
  43. package/dist/chat/super-grouping/timeline-step.cjs.map +1 -0
  44. package/dist/chat/super-grouping/timeline-step.d.ts +17 -0
  45. package/dist/chat/super-grouping/timeline-step.js +65 -0
  46. package/dist/chat/super-grouping/timeline-step.js.map +1 -0
  47. package/dist/chat/tiptap-text.cjs +8 -8
  48. package/dist/chat/tiptap-text.cjs.map +1 -1
  49. package/dist/chat/use-athena-run-live.cjs +2 -1
  50. package/dist/chat/use-athena-run-live.cjs.map +1 -1
  51. package/dist/chat/use-athena-run-live.js +2 -1
  52. package/dist/chat/use-athena-run-live.js.map +1 -1
  53. package/dist/chat/use-statewire-approval-request.cjs +7 -2
  54. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  55. package/dist/chat/use-statewire-approval-request.d.ts +12 -2
  56. package/dist/chat/use-statewire-approval-request.js +8 -3
  57. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  58. package/dist/chat-ui/composer/tiptap-composer.cjs +24 -65
  59. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  60. package/dist/chat-ui/composer/tiptap-composer.js +24 -65
  61. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  62. package/dist/chat-ui/index.cjs +2 -1
  63. package/dist/chat-ui/index.cjs.map +1 -1
  64. package/dist/chat-ui/index.js +2 -1
  65. package/dist/chat-ui/index.js.map +1 -1
  66. package/dist/chat-ui/mentions/mention-chip.cjs +49 -4
  67. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  68. package/dist/chat-ui/mentions/mention-chip.d.ts +11 -0
  69. package/dist/chat-ui/mentions/mention-chip.js +50 -5
  70. package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
  71. package/dist/chat-ui/mentions/mention-extension.cjs +18 -6
  72. package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
  73. package/dist/chat-ui/mentions/mention-extension.d.ts +2 -0
  74. package/dist/chat-ui/mentions/mention-extension.js +18 -6
  75. package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
  76. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +1 -1
  77. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
  78. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +1 -1
  79. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
  80. package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs +9 -6
  81. package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs.map +1 -1
  82. package/dist/chat-ui/mentions/suggestions/components/menu-item.d.ts +2 -2
  83. package/dist/chat-ui/mentions/suggestions/components/menu-item.js +10 -7
  84. package/dist/chat-ui/mentions/suggestions/components/menu-item.js.map +1 -1
  85. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +2 -2
  86. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
  87. package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +2 -2
  88. package/dist/chat-ui/mentions/suggestions/components/menu-list.js +2 -2
  89. package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
  90. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +2 -1
  91. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  92. package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +3 -2
  93. package/dist/chat-ui/mentions/suggestions/data/api-client.js +2 -1
  94. package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
  95. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs +6 -6
  96. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs.map +1 -1
  97. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js +6 -6
  98. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js.map +1 -1
  99. package/dist/chat-ui/messages/message-components.cjs +6 -29
  100. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  101. package/dist/chat-ui/messages/message-components.d.ts +1 -13
  102. package/dist/chat-ui/messages/message-components.js +8 -31
  103. package/dist/chat-ui/messages/message-components.js.map +1 -1
  104. package/dist/chat-ui/messages/runtime-message.cjs +3 -2
  105. package/dist/chat-ui/messages/runtime-message.cjs.map +1 -1
  106. package/dist/chat-ui/messages/runtime-message.js +3 -2
  107. package/dist/chat-ui/messages/runtime-message.js.map +1 -1
  108. package/dist/chat-ui/messages/statewire-continue-run.cjs +23 -8
  109. package/dist/chat-ui/messages/statewire-continue-run.cjs.map +1 -1
  110. package/dist/chat-ui/messages/statewire-continue-run.d.ts +14 -4
  111. package/dist/chat-ui/messages/statewire-continue-run.js +23 -8
  112. package/dist/chat-ui/messages/statewire-continue-run.js.map +1 -1
  113. package/dist/chat-ui/messages/user-edit-composer.cjs +2 -1
  114. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  115. package/dist/chat-ui/messages/user-edit-composer.js +2 -1
  116. package/dist/chat-ui/messages/user-edit-composer.js.map +1 -1
  117. package/dist/chat-ui/rich-text/chat-message-body.cjs +76 -0
  118. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -0
  119. package/dist/chat-ui/rich-text/chat-message-body.d.ts +5 -0
  120. package/dist/chat-ui/rich-text/chat-message-body.js +76 -0
  121. package/dist/chat-ui/rich-text/chat-message-body.js.map +1 -0
  122. package/dist/chat-ui/rich-text/chat-node-views.cjs +51 -0
  123. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -0
  124. package/dist/chat-ui/rich-text/chat-node-views.d.ts +13 -0
  125. package/dist/chat-ui/rich-text/chat-node-views.js +51 -0
  126. package/dist/chat-ui/rich-text/chat-node-views.js.map +1 -0
  127. package/dist/chat-ui/rich-text/chat-text-schema.cjs +70 -0
  128. package/dist/chat-ui/rich-text/chat-text-schema.cjs.map +1 -0
  129. package/dist/chat-ui/rich-text/chat-text-schema.d.ts +7 -0
  130. package/dist/chat-ui/rich-text/chat-text-schema.js +70 -0
  131. package/dist/chat-ui/rich-text/chat-text-schema.js.map +1 -0
  132. package/dist/chat-ui/rich-text/dom-output-spec.cjs +83 -0
  133. package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -0
  134. package/dist/chat-ui/rich-text/dom-output-spec.d.ts +11 -0
  135. package/dist/chat-ui/rich-text/dom-output-spec.js +83 -0
  136. package/dist/chat-ui/rich-text/dom-output-spec.js.map +1 -0
  137. package/dist/chat-ui/statewire.cjs +2 -1
  138. package/dist/chat-ui/statewire.cjs.map +1 -1
  139. package/dist/chat-ui/statewire.js +2 -1
  140. package/dist/chat-ui/statewire.js.map +1 -1
  141. package/dist/chat-ui/thread/statewire-history-edge.cjs +2 -1
  142. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  143. package/dist/chat-ui/thread/statewire-history-edge.js +2 -1
  144. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  145. package/dist/index.cjs +2 -1
  146. package/dist/index.cjs.map +1 -1
  147. package/dist/index.js +2 -1
  148. package/dist/index.js.map +1 -1
  149. package/dist/node_modules/qrcode-generator/dist/qrcode.cjs +32 -0
  150. package/dist/node_modules/qrcode-generator/dist/qrcode.cjs.map +1 -0
  151. package/dist/node_modules/qrcode-generator/dist/qrcode.js +31 -0
  152. package/dist/node_modules/qrcode-generator/dist/qrcode.js.map +1 -0
  153. package/dist/node_modules/zod/v4/classic/errors.cjs +44 -0
  154. package/dist/node_modules/zod/v4/classic/errors.cjs.map +1 -0
  155. package/dist/node_modules/zod/v4/classic/errors.js +44 -0
  156. package/dist/node_modules/zod/v4/classic/errors.js.map +1 -0
  157. package/dist/node_modules/zod/v4/classic/iso.cjs +43 -0
  158. package/dist/node_modules/zod/v4/classic/iso.cjs.map +1 -0
  159. package/dist/node_modules/zod/v4/classic/iso.js +43 -0
  160. package/dist/node_modules/zod/v4/classic/iso.js.map +1 -0
  161. package/dist/node_modules/zod/v4/classic/parse.cjs +29 -0
  162. package/dist/node_modules/zod/v4/classic/parse.cjs.map +1 -0
  163. package/dist/node_modules/zod/v4/classic/parse.js +29 -0
  164. package/dist/node_modules/zod/v4/classic/parse.js.map +1 -0
  165. package/dist/node_modules/zod/v4/classic/schemas.cjs +871 -0
  166. package/dist/node_modules/zod/v4/classic/schemas.cjs.map +1 -0
  167. package/dist/node_modules/zod/v4/classic/schemas.js +871 -0
  168. package/dist/node_modules/zod/v4/classic/schemas.js.map +1 -0
  169. package/dist/node_modules/zod/v4/core/api.cjs +570 -0
  170. package/dist/node_modules/zod/v4/core/api.cjs.map +1 -0
  171. package/dist/node_modules/zod/v4/core/api.js +570 -0
  172. package/dist/node_modules/zod/v4/core/api.js.map +1 -0
  173. package/dist/node_modules/zod/v4/core/checks.cjs +411 -0
  174. package/dist/node_modules/zod/v4/core/checks.cjs.map +1 -0
  175. package/dist/node_modules/zod/v4/core/checks.js +411 -0
  176. package/dist/node_modules/zod/v4/core/checks.js.map +1 -0
  177. package/dist/node_modules/zod/v4/core/core.cjs +77 -0
  178. package/dist/node_modules/zod/v4/core/core.cjs.map +1 -0
  179. package/dist/node_modules/zod/v4/core/core.js +77 -0
  180. package/dist/node_modules/zod/v4/core/core.js.map +1 -0
  181. package/dist/node_modules/zod/v4/core/doc.cjs +38 -0
  182. package/dist/node_modules/zod/v4/core/doc.cjs.map +1 -0
  183. package/dist/node_modules/zod/v4/core/doc.js +38 -0
  184. package/dist/node_modules/zod/v4/core/doc.js.map +1 -0
  185. package/dist/node_modules/zod/v4/core/errors.cjs +76 -0
  186. package/dist/node_modules/zod/v4/core/errors.cjs.map +1 -0
  187. package/dist/node_modules/zod/v4/core/errors.js +76 -0
  188. package/dist/node_modules/zod/v4/core/errors.js.map +1 -0
  189. package/dist/node_modules/zod/v4/core/json-schema-processors.cjs +312 -0
  190. package/dist/node_modules/zod/v4/core/json-schema-processors.cjs.map +1 -0
  191. package/dist/node_modules/zod/v4/core/json-schema-processors.js +312 -0
  192. package/dist/node_modules/zod/v4/core/json-schema-processors.js.map +1 -0
  193. package/dist/node_modules/zod/v4/core/parse.cjs +96 -0
  194. package/dist/node_modules/zod/v4/core/parse.cjs.map +1 -0
  195. package/dist/node_modules/zod/v4/core/parse.js +96 -0
  196. package/dist/node_modules/zod/v4/core/parse.js.map +1 -0
  197. package/dist/node_modules/zod/v4/core/regexes.cjs +86 -0
  198. package/dist/node_modules/zod/v4/core/regexes.cjs.map +1 -0
  199. package/dist/node_modules/zod/v4/core/regexes.js +86 -0
  200. package/dist/node_modules/zod/v4/core/regexes.js.map +1 -0
  201. package/dist/node_modules/zod/v4/core/registries.cjs +52 -0
  202. package/dist/node_modules/zod/v4/core/registries.cjs.map +1 -0
  203. package/dist/node_modules/zod/v4/core/registries.js +52 -0
  204. package/dist/node_modules/zod/v4/core/registries.js.map +1 -0
  205. package/dist/node_modules/zod/v4/core/schemas.cjs +1412 -0
  206. package/dist/node_modules/zod/v4/core/schemas.cjs.map +1 -0
  207. package/dist/node_modules/zod/v4/core/schemas.js +1413 -0
  208. package/dist/node_modules/zod/v4/core/schemas.js.map +1 -0
  209. package/dist/node_modules/zod/v4/core/to-json-schema.cjs +370 -0
  210. package/dist/node_modules/zod/v4/core/to-json-schema.cjs.map +1 -0
  211. package/dist/node_modules/zod/v4/core/to-json-schema.js +370 -0
  212. package/dist/node_modules/zod/v4/core/to-json-schema.js.map +1 -0
  213. package/dist/node_modules/zod/v4/core/util.cjs +444 -0
  214. package/dist/node_modules/zod/v4/core/util.cjs.map +1 -0
  215. package/dist/node_modules/zod/v4/core/util.js +444 -0
  216. package/dist/node_modules/zod/v4/core/util.js.map +1 -0
  217. package/dist/node_modules/zod/v4/core/versions.cjs +9 -0
  218. package/dist/node_modules/zod/v4/core/versions.cjs.map +1 -0
  219. package/dist/node_modules/zod/v4/core/versions.js +9 -0
  220. package/dist/node_modules/zod/v4/core/versions.js.map +1 -0
  221. package/dist/packages/agent-runtime/src/client-tool-bridge.cjs +7 -1
  222. package/dist/packages/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  223. package/dist/packages/agent-runtime/src/client-tool-bridge.js +7 -1
  224. package/dist/packages/agent-runtime/src/client-tool-bridge.js.map +1 -1
  225. package/dist/packages/agent-runtime/src/conversation-index.cjs +19 -10
  226. package/dist/packages/agent-runtime/src/conversation-index.cjs.map +1 -1
  227. package/dist/packages/agent-runtime/src/conversation-index.js +19 -10
  228. package/dist/packages/agent-runtime/src/conversation-index.js.map +1 -1
  229. package/dist/packages/agent-runtime/src/conversation-list.cjs +4 -0
  230. package/dist/packages/agent-runtime/src/conversation-list.cjs.map +1 -1
  231. package/dist/packages/agent-runtime/src/conversation-list.js +4 -0
  232. package/dist/packages/agent-runtime/src/conversation-list.js.map +1 -1
  233. package/dist/packages/agent-runtime/src/edit-command.cjs.map +1 -1
  234. package/dist/packages/agent-runtime/src/edit-command.js.map +1 -1
  235. package/dist/packages/agent-runtime/src/generated/runconfig-contract.cjs +2 -0
  236. package/dist/packages/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  237. package/dist/packages/agent-runtime/src/generated/runconfig-contract.js +2 -0
  238. package/dist/packages/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  239. package/dist/packages/agent-runtime/src/interrupts.cjs +31 -7
  240. package/dist/packages/agent-runtime/src/interrupts.cjs.map +1 -1
  241. package/dist/packages/agent-runtime/src/interrupts.js +31 -7
  242. package/dist/packages/agent-runtime/src/interrupts.js.map +1 -1
  243. package/dist/packages/agent-runtime/src/messages.cjs +35 -5
  244. package/dist/packages/agent-runtime/src/messages.cjs.map +1 -1
  245. package/dist/packages/agent-runtime/src/messages.js +35 -5
  246. package/dist/packages/agent-runtime/src/messages.js.map +1 -1
  247. package/dist/packages/agent-runtime/src/protocol.cjs +4 -6
  248. package/dist/packages/agent-runtime/src/protocol.cjs.map +1 -1
  249. package/dist/packages/agent-runtime/src/protocol.js +4 -6
  250. package/dist/packages/agent-runtime/src/protocol.js.map +1 -1
  251. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.cjs +296 -14
  252. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  253. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.js +293 -11
  254. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
  255. package/dist/packages/agent-runtime/src/screen-point.cjs +68 -0
  256. package/dist/packages/agent-runtime/src/screen-point.cjs.map +1 -0
  257. package/dist/packages/agent-runtime/src/screen-point.js +68 -0
  258. package/dist/packages/agent-runtime/src/screen-point.js.map +1 -0
  259. package/dist/packages/agent-runtime/src/statewire-transport.cjs +6 -1
  260. package/dist/packages/agent-runtime/src/statewire-transport.cjs.map +1 -1
  261. package/dist/packages/agent-runtime/src/statewire-transport.js +6 -1
  262. package/dist/packages/agent-runtime/src/statewire-transport.js.map +1 -1
  263. package/dist/packages/agent-runtime/src/thread-handoff.cjs +85 -0
  264. package/dist/packages/agent-runtime/src/thread-handoff.cjs.map +1 -0
  265. package/dist/packages/agent-runtime/src/thread-handoff.js +85 -0
  266. package/dist/packages/agent-runtime/src/thread-handoff.js.map +1 -0
  267. package/dist/packages/agent-runtime/src/thread-snapshot-cache.cjs +1 -1
  268. package/dist/packages/agent-runtime/src/thread-snapshot-cache.cjs.map +1 -1
  269. package/dist/packages/agent-runtime/src/thread-snapshot-cache.js +1 -1
  270. package/dist/packages/agent-runtime/src/thread-snapshot-cache.js.map +1 -1
  271. package/dist/packages/agent-runtime/src/tool-metadata.cjs +0 -8
  272. package/dist/packages/agent-runtime/src/tool-metadata.cjs.map +1 -1
  273. package/dist/packages/agent-runtime/src/tool-metadata.js +0 -8
  274. package/dist/packages/agent-runtime/src/tool-metadata.js.map +1 -1
  275. package/dist/packages/agent-runtime/src/use-deep-agent-config.cjs +14 -0
  276. package/dist/packages/agent-runtime/src/use-deep-agent-config.cjs.map +1 -0
  277. package/dist/packages/agent-runtime/src/use-deep-agent-config.js +14 -0
  278. package/dist/packages/agent-runtime/src/use-deep-agent-config.js.map +1 -0
  279. package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.cjs +21 -5
  280. package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  281. package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.js +21 -5
  282. package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.js.map +1 -1
  283. package/dist/packages/agent-runtime/src/use-deep-agent-runtime.cjs +13 -3
  284. package/dist/packages/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  285. package/dist/packages/agent-runtime/src/use-deep-agent-runtime.js +14 -4
  286. package/dist/packages/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
  287. package/dist/packages/agent-runtime/src/use-deep-agent-thread.cjs +35 -15
  288. package/dist/packages/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  289. package/dist/packages/agent-runtime/src/use-deep-agent-thread.js +35 -15
  290. package/dist/packages/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  291. package/dist/packages/agent-runtime/src/voice-presentation.cjs.map +1 -1
  292. package/dist/packages/agent-runtime/src/voice-presentation.js.map +1 -1
  293. package/dist/packages/react/package.json.cjs +1 -1
  294. package/dist/packages/react/package.json.js +1 -1
  295. package/dist/provider/AthenaProvider.cjs +2 -1
  296. package/dist/provider/AthenaProvider.cjs.map +1 -1
  297. package/dist/provider/AthenaProvider.js +2 -1
  298. package/dist/provider/AthenaProvider.js.map +1 -1
  299. package/dist/runtime/statewire-lifecycle.cjs +2 -1
  300. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  301. package/dist/runtime/statewire-lifecycle.js +2 -1
  302. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  303. package/dist/runtime/useAthenaStatewireRuntime.cjs +2 -1
  304. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  305. package/dist/runtime/useAthenaStatewireRuntime.js +2 -1
  306. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  307. package/dist/styles.css +1 -1
  308. package/dist/threads/api.cjs +29 -0
  309. package/dist/threads/api.cjs.map +1 -1
  310. package/dist/threads/api.d.ts +15 -0
  311. package/dist/threads/api.js +29 -0
  312. package/dist/threads/api.js.map +1 -1
  313. package/dist/threads/conversation-list-fetcher.cjs +4 -0
  314. package/dist/threads/conversation-list-fetcher.cjs.map +1 -1
  315. package/dist/threads/conversation-list-fetcher.js +4 -0
  316. package/dist/threads/conversation-list-fetcher.js.map +1 -1
  317. package/dist/threads/credential-shape.cjs +15 -0
  318. package/dist/threads/credential-shape.cjs.map +1 -0
  319. package/dist/threads/credential-shape.d.ts +17 -0
  320. package/dist/threads/credential-shape.js +15 -0
  321. package/dist/threads/credential-shape.js.map +1 -0
  322. package/dist/threads/statewire-thread-list.cjs +37 -4
  323. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  324. package/dist/threads/statewire-thread-list.js +38 -5
  325. package/dist/threads/statewire-thread-list.js.map +1 -1
  326. package/dist/threads/use-rest-conversation-history.cjs +2 -1
  327. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  328. package/dist/threads/use-rest-conversation-history.js +2 -1
  329. package/dist/threads/use-rest-conversation-history.js.map +1 -1
  330. package/dist/threads/use-statewire-conversation-history.cjs +5 -2
  331. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  332. package/dist/threads/use-statewire-conversation-history.d.ts +4 -1
  333. package/dist/threads/use-statewire-conversation-history.js +5 -2
  334. package/dist/threads/use-statewire-conversation-history.js.map +1 -1
  335. package/dist/toolkits/index.cjs +0 -7
  336. package/dist/toolkits/index.cjs.map +1 -1
  337. package/dist/toolkits/index.d.ts +0 -2
  338. package/dist/toolkits/index.js +0 -7
  339. package/dist/toolkits/index.js.map +1 -1
  340. package/dist/tools/index.cjs +2 -1
  341. package/dist/tools/index.cjs.map +1 -1
  342. package/dist/tools/index.js +2 -1
  343. package/dist/tools/index.js.map +1 -1
  344. package/dist/tools/misc-tool-uis.cjs +2 -1
  345. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  346. package/dist/tools/misc-tool-uis.js +2 -1
  347. package/dist/tools/misc-tool-uis.js.map +1 -1
  348. package/dist/tools/primitives.cjs +2 -1
  349. package/dist/tools/primitives.cjs.map +1 -1
  350. package/dist/tools/primitives.js +2 -1
  351. package/dist/tools/primitives.js.map +1 -1
  352. package/dist/tools/tool-fallback.cjs +2 -1
  353. package/dist/tools/tool-fallback.cjs.map +1 -1
  354. package/dist/tools/tool-fallback.js +2 -1
  355. package/dist/tools/tool-fallback.js.map +1 -1
  356. package/dist/tools/voice-update-tool-ui.cjs +2 -1
  357. package/dist/tools/voice-update-tool-ui.cjs.map +1 -1
  358. package/dist/tools/voice-update-tool-ui.js +2 -1
  359. package/dist/tools/voice-update-tool-ui.js.map +1 -1
  360. package/dist/voice/index.cjs +6 -0
  361. package/dist/voice/index.cjs.map +1 -0
  362. package/dist/voice/index.d.ts +2 -0
  363. package/dist/voice/index.js +6 -0
  364. package/dist/voice/index.js.map +1 -0
  365. package/dist/voice/use-athena-voice-session.cjs +315 -0
  366. package/dist/voice/use-athena-voice-session.cjs.map +1 -0
  367. package/dist/voice/use-athena-voice-session.d.ts +180 -0
  368. package/dist/voice/use-athena-voice-session.js +315 -0
  369. package/dist/voice/use-athena-voice-session.js.map +1 -0
  370. package/package.json +18 -4
@@ -7,18 +7,21 @@ import "../packages/agent-runtime/src/statewire-state.js";
7
7
  import "../packages/agent-runtime/src/messages.js";
8
8
  import "@assistant-ui/react-statewire";
9
9
  import "@assistant-ui/store";
10
- import "@assistant-ui/react-statewire/local-storage";
10
+ import "../packages/agent-runtime/src/quota-safe-local-storage-session.js";
11
11
  import "../packages/agent-runtime/src/statewire-suspended.js";
12
12
  import "@assistant-ui/tap";
13
13
  import "../packages/agent-runtime/src/statewire-attach-observer.js";
14
14
  import "statewire";
15
15
  import "../packages/agent-runtime/src/thread-status.js";
16
16
  import "@assistant-ui/core";
17
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
17
+ import "../packages/agent-runtime/src/thread-handoff.js";
18
+ import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
18
19
  import { useAuiState } from "@assistant-ui/react";
19
20
  import { AthenaAuthContext } from "../auth/AthenaAuthContext.js";
20
21
  import { resolveStatewireAuthToken, resolveStatewireAuthHeaders } from "../runtime/statewire-auth-headers.js";
22
+ import { fetchAccountIdentity } from "./api.js";
21
23
  import { createRestConversationListFetcher } from "./conversation-list-fetcher.js";
24
+ import { credentialShape, sameCredentialShape } from "./credential-shape.js";
22
25
  import { mintThreadId } from "./mint-thread-id.js";
23
26
  import { normalizeThreadTitle, isSerializedContentPartsTitle } from "./title.js";
24
27
  const AthenaStatewireThreadListContext = createContext(null);
@@ -40,7 +43,7 @@ function StatewireThreadListState({
40
43
  initialThreadId,
41
44
  children
42
45
  }) {
43
- var _a;
46
+ var _a, _b, _c;
44
47
  const [active, setActive] = useState(
45
48
  () => initialThreadId ? { id: initialThreadId, isNew: false } : { id: mintThreadId(), isNew: true }
46
49
  );
@@ -86,10 +89,40 @@ function StatewireThreadListState({
86
89
  ),
87
90
  []
88
91
  );
89
- const indexEnabled = syncUrl !== void 0 && principal.length > 0 && hasAuth;
92
+ const credentialsRef = useRef(credentialShape({ apiKey, token, getToken }));
93
+ const credentialGenerationRef = useRef(0);
94
+ const currentCredentials = credentialShape({ apiKey, token, getToken });
95
+ if (!sameCredentialShape(credentialsRef.current, currentCredentials)) {
96
+ credentialsRef.current = currentCredentials;
97
+ credentialGenerationRef.current += 1;
98
+ }
99
+ const credentialGeneration = credentialGenerationRef.current;
100
+ const identityEnabled = syncUrl !== void 0 && principal.length > 0 && hasAuth;
101
+ const identity = useQuery({
102
+ // Keyed by the non-secret principal and credential generation, never the
103
+ // credential itself.
104
+ queryKey: ["athena-sdk", "account-identity", backendUrl, principal, credentialGeneration],
105
+ queryFn: async ({ signal }) => fetchAccountIdentity(
106
+ backendUrl,
107
+ {
108
+ apiKey: apiKeyRef.current,
109
+ token: await resolveStatewireAuthToken(
110
+ { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },
111
+ { staleAuth: false }
112
+ )
113
+ },
114
+ { signal }
115
+ ),
116
+ enabled: identityEnabled,
117
+ staleTime: Number.POSITIVE_INFINITY
118
+ });
119
+ const indexWorkspaceId = ((_b = identity.data) == null ? void 0 : _b.workspaceId) ?? "";
120
+ const indexUserId = ((_c = identity.data) == null ? void 0 : _c.userId) ?? "";
121
+ const indexEnabled = identityEnabled && indexWorkspaceId.length > 0 && indexUserId.length > 0;
90
122
  const index = useConversationIndex({
91
123
  baseUrl: syncUrl === void 0 ? "" : conversationIndexUrlFromStatewireUrl(syncUrl),
92
- userId: principal || "pending-user",
124
+ workspaceId: indexWorkspaceId || "pending-workspace",
125
+ userId: indexUserId || "pending-user",
93
126
  headers: indexHeaders,
94
127
  enabled: indexEnabled
95
128
  });
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-thread-list.js","sources":["../../src/threads/statewire-thread-list.tsx"],"sourcesContent":["import {\n type ConversationListFilter,\n conversationIndexUrlFromStatewireUrl,\n type DeepAgentHeadersResolver,\n useConversationIndex,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useAuiState } from '@assistant-ui/react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n resolveStatewireAuthToken,\n} from '../runtime/statewire-auth-headers';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\nimport { mintThreadId } from './mint-thread-id';\nimport { isSerializedContentPartsTitle, normalizeThreadTitle } from './title';\n\nexport interface AthenaStatewireThreadSummary {\n id: string;\n title: string | null;\n}\n\n/**\n * Thread-list state. The list is the persisted Agora session list; the ACTIVE\n * thread is a plain id the statewire runtime attaches to — switching threads\n * remounts the statewire session against the new `…/v2/threads/{id}` URL\n * (the same model the mobile app uses).\n */\nexport interface AthenaStatewireThreadListState {\n threads: AthenaStatewireThreadSummary[];\n isLoading: boolean;\n activeThreadId: string;\n /** True while the active thread is a locally-minted chat with no server history. */\n isNewChat: boolean;\n selectThread: (threadId: string) => void;\n newThread: () => void;\n refresh: () => void;\n /**\n * Where titles come from. `'index'` once the signed-in user's live\n * conversation index has replicated — titles and newly created threads then\n * arrive as pushed updates; `'poll'` while it has not (no signed-in\n * principal, e.g. API-key mode, or before its snapshot), when a\n * freshly-started thread's title is picked up by the bounded REST poll.\n */\n titleSource: 'index' | 'poll';\n}\n\nexport const AthenaStatewireThreadListContext =\n createContext<AthenaStatewireThreadListState | null>(null);\n\n/** Read the statewire thread-list state, or null outside that mode. */\nexport function useAthenaStatewireThreadList(): AthenaStatewireThreadListState | null {\n return useContext(AthenaStatewireThreadListContext);\n}\n\n/** Trigger a re-fetch of the thread list. `null` outside `enableThreadList` mode. */\nexport function useRefreshThreadList(): (() => void) | null {\n return useAthenaStatewireThreadList()?.refresh ?? null;\n}\n\n/**\n * The statewire thread list reads one live page through the shared\n * conversation-list contract; the REST default page size predates the shared\n * pager and is preserved here.\n */\nconst THREAD_LIST_PAGE_SIZE = 50;\n\nfunction StatewireThreadListState({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n initialThreadId,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n initialThreadId?: string;\n children: ReactNode;\n}) {\n const [active, setActive] = useState<{ id: string; isNew: boolean }>(() =>\n initialThreadId\n ? { id: initialThreadId, isNew: false }\n : { id: mintThreadId(), isNew: true },\n );\n\n const tokenRef = useRef(token);\n tokenRef.current = token;\n const apiKeyRef = useRef(apiKey);\n apiKeyRef.current = apiKey;\n const getTokenRef = useRef(getToken);\n getTokenRef.current = getToken;\n\n // The cache must be keyed by WHO is asking. Keying on `backendUrl`/`appId`\n // alone let a token swap to a different user read the previous user's thread\n // titles out of the cache. The principal is a non-secret user id, so no\n // credential enters the key (or React Query's devtools). The shared pager\n // never serves placeholder rows across keys, so another principal's list is\n // never shown while the new one loads.\n const authContext = useContext(AthenaAuthContext);\n const principal = authContext?.user?.userId ?? '';\n // A live token getter is a credential too: a `getToken`-only host\n // authenticates its chat, so its list must not stay empty.\n const hasAuth = !!(apiKey || token || getToken);\n\n const fetchPage = useMemo(\n () =>\n createRestConversationListFetcher({\n backendUrl,\n // Resolved per request with the attach's token semantics (getter first,\n // host-held token as the fallback) so a rotated token is never stale.\n getAuth: async () => ({\n apiKey: apiKeyRef.current,\n token: await resolveStatewireAuthToken(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n { staleAuth: false },\n ),\n }),\n }),\n [backendUrl],\n );\n const filter = useMemo<ConversationListFilter>(\n () => (appId ? { appId } : {}),\n [appId],\n );\n const list = useConversationList({\n fetchPage,\n filter,\n pageSize: THREAD_LIST_PAGE_SIZE,\n scopeKey: `${backendUrl}::${principal}::${hasAuth ? 'auth' : 'anon'}`,\n enabled: hasAuth,\n });\n\n // Live titles ride the signed-in user's conversation index — the same push\n // channel the conversation-history panel renders from: the host replicates\n // title, lifecycle, and creation changes as ops, so a freshly-started\n // thread's server-generated title lands without polling. The index is keyed\n // by the principal, so it only attaches once one is known; API-key-only\n // hosts keep the bounded REST poll (`titleSource: 'poll'`).\n const indexHeaders = useCallback<DeepAgentHeadersResolver>(\n (ctx) =>\n resolveStatewireAuthHeaders(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n ctx,\n ),\n [],\n );\n const indexEnabled = syncUrl !== undefined && principal.length > 0 && hasAuth;\n const index = useConversationIndex({\n baseUrl: syncUrl === undefined ? '' : conversationIndexUrlFromStatewireUrl(syncUrl),\n userId: principal || 'pending-user',\n headers: indexHeaders,\n enabled: indexEnabled,\n });\n const indexTitles = useMemo(() => {\n const titles = new Map<string, string | null>();\n for (const entry of index.entries ?? []) {\n titles.set(entry.thread_id, normalizeThreadTitle(entry.title) ?? null);\n }\n return titles;\n }, [index.entries]);\n\n const data = useMemo(\n () =>\n list.conversations.map((conversation) => ({\n id: conversation.threadId,\n title:\n indexTitles.get(conversation.threadId) ??\n normalizeThreadTitle(conversation.title) ??\n null,\n })),\n [list.conversations, indexTitles],\n );\n const isLoading = list.isLoading;\n\n const listRefresh = list.refresh;\n const refresh = useCallback(() => {\n void listRefresh();\n }, [listRefresh]);\n\n // A thread the index knows — created here on first send, or elsewhere —\n // that the REST page does not list yet: refresh once per such id so the row\n // appears without the user pressing refresh. Rows for other app ids belong\n // to other lists and never trigger one.\n const refreshedForRef = useRef<Set<string>>(new Set());\n useEffect(() => {\n if (index.entries === null) return;\n const listed = new Set(list.conversations.map((conversation) => conversation.threadId));\n let pending = false;\n for (const entry of index.entries) {\n if (appId && entry.app_id !== appId) continue;\n if (listed.has(entry.thread_id) || refreshedForRef.current.has(entry.thread_id)) continue;\n refreshedForRef.current.add(entry.thread_id);\n pending = true;\n }\n if (pending) void listRefresh();\n }, [index.entries, list.conversations, appId, listRefresh]);\n\n const selectThread = useCallback((threadId: string) => {\n if (!threadId) return;\n setActive((current) =>\n current.id === threadId ? current : { id: threadId, isNew: false },\n );\n }, []);\n\n const newThread = useCallback(() => {\n setActive({ id: mintThreadId(), isNew: true });\n }, []);\n\n // A minted thread stops being \"new\" once the backend lists it: until then\n // `useAthenaThreadManager` reports a null id, so URL sync cannot name it.\n const isPersisted = data.some((thread) => thread.id === active.id);\n useEffect(() => {\n if (isPersisted) {\n setActive((current) => (current.isNew ? { ...current, isNew: false } : current));\n }\n }, [isPersisted]);\n\n const titleSource: AthenaStatewireThreadListState['titleSource'] =\n index.entries !== null ? 'index' : 'poll';\n\n const value = useMemo<AthenaStatewireThreadListState>(\n () => ({\n threads: data,\n isLoading,\n activeThreadId: active.id,\n isNewChat: active.isNew,\n selectThread,\n newThread,\n refresh,\n titleSource,\n }),\n [data, isLoading, active.id, active.isNew, selectThread, newThread, refresh, titleSource],\n );\n\n return (\n <AthenaStatewireThreadListContext.Provider value={value}>\n {children}\n </AthenaStatewireThreadListContext.Provider>\n );\n}\n\n/**\n * Provides the statewire thread-list state, with an SDK-scoped QueryClient so\n * consumers do not need their own QueryClientProvider. `syncUrl` (the\n * `…/v2/threads` mount) locates the conversation index beside it; without it\n * titles fall back to the REST poll.\n */\nexport function AthenaStatewireThreadListProvider({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n initialThreadId,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n initialThreadId?: string;\n children: ReactNode;\n}) {\n const [queryClient] = useState(() => new QueryClient());\n return (\n <QueryClientProvider client={queryClient}>\n <StatewireThreadListState\n backendUrl={backendUrl}\n syncUrl={syncUrl}\n apiKey={apiKey}\n token={token}\n getToken={getToken}\n appId={appId}\n initialThreadId={initialThreadId}\n >\n {children}\n </StatewireThreadListState>\n </QueryClientProvider>\n );\n}\n\nconst TITLE_POLL_DELAY_MS = 5000;\nconst TITLE_POLL_INTERVAL_MS = 2000;\nconst TITLE_POLL_MAX_DURATION_MS = 60_000;\n\n/**\n * Fallback for hosts without a live conversation index (`titleSource: 'poll'`,\n * i.e. no signed-in principal): refreshes the thread list until a\n * freshly-started thread's server-generated title appears. Idle while the\n * index carries titles. Mount inside the statewire runtime scope (needs aui\n * state).\n */\nexport function StatewireThreadTitlePoller(): null {\n const list = useAthenaStatewireThreadList();\n const hasMessages = useAuiState((s) => (s.optional.thread?.messages.length ?? 0) > 0);\n\n const activeThreadId = list?.activeThreadId ?? null;\n const titleSource = list?.titleSource ?? 'poll';\n const entry = list?.threads.find((thread) => thread.id === activeThreadId);\n const title = entry?.title?.trim() ?? '';\n const hasTitle = title.length > 0 && !isSerializedContentPartsTitle(title);\n\n const polledThreadsRef = useRef<Set<string>>(new Set());\n const refreshRef = useRef(list?.refresh);\n refreshRef.current = list?.refresh;\n\n useEffect(() => {\n if (!activeThreadId || !hasMessages || hasTitle || titleSource === 'index') return;\n if (polledThreadsRef.current.has(activeThreadId)) return;\n polledThreadsRef.current.add(activeThreadId);\n\n let intervalId: ReturnType<typeof setInterval> | null = null;\n const startId = setTimeout(() => {\n intervalId = setInterval(() => refreshRef.current?.(), TITLE_POLL_INTERVAL_MS);\n }, TITLE_POLL_DELAY_MS);\n const stopId = setTimeout(() => {\n if (intervalId !== null) clearInterval(intervalId);\n }, TITLE_POLL_MAX_DURATION_MS);\n\n return () => {\n clearTimeout(startId);\n clearTimeout(stopId);\n if (intervalId !== null) clearInterval(intervalId);\n };\n }, [activeThreadId, hasMessages, hasTitle, titleSource]);\n\n return null;\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"statewire-thread-list.js","sources":["../../src/threads/statewire-thread-list.tsx"],"sourcesContent":["import {\n type ConversationListFilter,\n conversationIndexUrlFromStatewireUrl,\n type DeepAgentHeadersResolver,\n useConversationIndex,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';\nimport { useAuiState } from '@assistant-ui/react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n resolveStatewireAuthToken,\n} from '../runtime/statewire-auth-headers';\nimport { fetchAccountIdentity } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\nimport { credentialShape, sameCredentialShape } from './credential-shape';\nimport { mintThreadId } from './mint-thread-id';\nimport { isSerializedContentPartsTitle, normalizeThreadTitle } from './title';\n\nexport interface AthenaStatewireThreadSummary {\n id: string;\n title: string | null;\n}\n\n/**\n * Thread-list state. The list is the persisted Agora session list; the ACTIVE\n * thread is a plain id the statewire runtime attaches to — switching threads\n * remounts the statewire session against the new `…/v2/threads/{id}` URL\n * (the same model the mobile app uses).\n */\nexport interface AthenaStatewireThreadListState {\n threads: AthenaStatewireThreadSummary[];\n isLoading: boolean;\n activeThreadId: string;\n /** True while the active thread is a locally-minted chat with no server history. */\n isNewChat: boolean;\n selectThread: (threadId: string) => void;\n newThread: () => void;\n refresh: () => void;\n /**\n * Where titles come from. `'index'` once the signed-in user's live\n * conversation index has replicated — titles and newly created threads then\n * arrive as pushed updates; `'poll'` while it has not (no signed-in\n * principal, e.g. API-key mode, or before its snapshot), when a\n * freshly-started thread's title is picked up by the bounded REST poll.\n */\n titleSource: 'index' | 'poll';\n}\n\nexport const AthenaStatewireThreadListContext =\n createContext<AthenaStatewireThreadListState | null>(null);\n\n/** Read the statewire thread-list state, or null outside that mode. */\nexport function useAthenaStatewireThreadList(): AthenaStatewireThreadListState | null {\n return useContext(AthenaStatewireThreadListContext);\n}\n\n/** Trigger a re-fetch of the thread list. `null` outside `enableThreadList` mode. */\nexport function useRefreshThreadList(): (() => void) | null {\n return useAthenaStatewireThreadList()?.refresh ?? null;\n}\n\n/**\n * The statewire thread list reads one live page through the shared\n * conversation-list contract; the REST default page size predates the shared\n * pager and is preserved here.\n */\nconst THREAD_LIST_PAGE_SIZE = 50;\n\nfunction StatewireThreadListState({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n initialThreadId,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n initialThreadId?: string;\n children: ReactNode;\n}) {\n const [active, setActive] = useState<{ id: string; isNew: boolean }>(() =>\n initialThreadId\n ? { id: initialThreadId, isNew: false }\n : { id: mintThreadId(), isNew: true },\n );\n\n const tokenRef = useRef(token);\n tokenRef.current = token;\n const apiKeyRef = useRef(apiKey);\n apiKeyRef.current = apiKey;\n const getTokenRef = useRef(getToken);\n getTokenRef.current = getToken;\n\n // The cache must be keyed by WHO is asking. Keying on `backendUrl`/`appId`\n // alone let a token swap to a different user read the previous user's thread\n // titles out of the cache. The principal is a non-secret user id, so no\n // credential enters the key (or React Query's devtools). The shared pager\n // never serves placeholder rows across keys, so another principal's list is\n // never shown while the new one loads.\n const authContext = useContext(AthenaAuthContext);\n const principal = authContext?.user?.userId ?? '';\n // A live token getter is a credential too: a `getToken`-only host\n // authenticates its chat, so its list must not stay empty.\n const hasAuth = !!(apiKey || token || getToken);\n\n const fetchPage = useMemo(\n () =>\n createRestConversationListFetcher({\n backendUrl,\n // Resolved per request with the attach's token semantics (getter first,\n // host-held token as the fallback) so a rotated token is never stale.\n getAuth: async () => ({\n apiKey: apiKeyRef.current,\n token: await resolveStatewireAuthToken(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n { staleAuth: false },\n ),\n }),\n }),\n [backendUrl],\n );\n const filter = useMemo<ConversationListFilter>(\n () => (appId ? { appId } : {}),\n [appId],\n );\n const list = useConversationList({\n fetchPage,\n filter,\n pageSize: THREAD_LIST_PAGE_SIZE,\n scopeKey: `${backendUrl}::${principal}::${hasAuth ? 'auth' : 'anon'}`,\n enabled: hasAuth,\n });\n\n // Live titles ride the signed-in user's conversation index — the same push\n // channel the conversation-history panel renders from: the host replicates\n // title, lifecycle, and creation changes as ops, so a freshly-started\n // thread's server-generated title lands without polling. The index is one\n // instance per `(workspace, user)` in agora's ids, so the pair is resolved\n // from the backend once a principal is known and the index only attaches\n // once both halves are; API-key-only hosts keep the bounded REST poll\n // (`titleSource: 'poll'`).\n const indexHeaders = useCallback<DeepAgentHeadersResolver>(\n (ctx) =>\n resolveStatewireAuthHeaders(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n ctx,\n ),\n [],\n );\n // The workspace half is the CREDENTIAL's: a scoped credential (sandbox,\n // preview, Office session) pins its own workspace, so swapping one for\n // another under the same principal must re-resolve the pair. The query is\n // therefore keyed by a credential generation — a counter that advances\n // whenever the host's credentials change — so no secret enters the key.\n const credentialsRef = useRef(credentialShape({ apiKey, token, getToken }));\n const credentialGenerationRef = useRef(0);\n const currentCredentials = credentialShape({ apiKey, token, getToken });\n if (!sameCredentialShape(credentialsRef.current, currentCredentials)) {\n credentialsRef.current = currentCredentials;\n credentialGenerationRef.current += 1;\n }\n const credentialGeneration = credentialGenerationRef.current;\n const identityEnabled = syncUrl !== undefined && principal.length > 0 && hasAuth;\n const identity = useQuery({\n // Keyed by the non-secret principal and credential generation, never the\n // credential itself.\n queryKey: ['athena-sdk', 'account-identity', backendUrl, principal, credentialGeneration],\n queryFn: async ({ signal }) =>\n fetchAccountIdentity(\n backendUrl,\n {\n apiKey: apiKeyRef.current,\n token: await resolveStatewireAuthToken(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n { staleAuth: false },\n ),\n },\n { signal },\n ),\n enabled: identityEnabled,\n staleTime: Number.POSITIVE_INFINITY,\n });\n const indexWorkspaceId = identity.data?.workspaceId ?? '';\n const indexUserId = identity.data?.userId ?? '';\n const indexEnabled = identityEnabled && indexWorkspaceId.length > 0 && indexUserId.length > 0;\n const index = useConversationIndex({\n baseUrl: syncUrl === undefined ? '' : conversationIndexUrlFromStatewireUrl(syncUrl),\n workspaceId: indexWorkspaceId || 'pending-workspace',\n userId: indexUserId || 'pending-user',\n headers: indexHeaders,\n enabled: indexEnabled,\n });\n const indexTitles = useMemo(() => {\n const titles = new Map<string, string | null>();\n for (const entry of index.entries ?? []) {\n titles.set(entry.thread_id, normalizeThreadTitle(entry.title) ?? null);\n }\n return titles;\n }, [index.entries]);\n\n const data = useMemo(\n () =>\n list.conversations.map((conversation) => ({\n id: conversation.threadId,\n title:\n indexTitles.get(conversation.threadId) ??\n normalizeThreadTitle(conversation.title) ??\n null,\n })),\n [list.conversations, indexTitles],\n );\n const isLoading = list.isLoading;\n\n const listRefresh = list.refresh;\n const refresh = useCallback(() => {\n void listRefresh();\n }, [listRefresh]);\n\n // A thread the index knows — created here on first send, or elsewhere —\n // that the REST page does not list yet: refresh once per such id so the row\n // appears without the user pressing refresh. Rows for other app ids belong\n // to other lists and never trigger one.\n const refreshedForRef = useRef<Set<string>>(new Set());\n useEffect(() => {\n if (index.entries === null) return;\n const listed = new Set(list.conversations.map((conversation) => conversation.threadId));\n let pending = false;\n for (const entry of index.entries) {\n if (appId && entry.app_id !== appId) continue;\n if (listed.has(entry.thread_id) || refreshedForRef.current.has(entry.thread_id)) continue;\n refreshedForRef.current.add(entry.thread_id);\n pending = true;\n }\n if (pending) void listRefresh();\n }, [index.entries, list.conversations, appId, listRefresh]);\n\n const selectThread = useCallback((threadId: string) => {\n if (!threadId) return;\n setActive((current) =>\n current.id === threadId ? current : { id: threadId, isNew: false },\n );\n }, []);\n\n const newThread = useCallback(() => {\n setActive({ id: mintThreadId(), isNew: true });\n }, []);\n\n // A minted thread stops being \"new\" once the backend lists it: until then\n // `useAthenaThreadManager` reports a null id, so URL sync cannot name it.\n const isPersisted = data.some((thread) => thread.id === active.id);\n useEffect(() => {\n if (isPersisted) {\n setActive((current) => (current.isNew ? { ...current, isNew: false } : current));\n }\n }, [isPersisted]);\n\n const titleSource: AthenaStatewireThreadListState['titleSource'] =\n index.entries !== null ? 'index' : 'poll';\n\n const value = useMemo<AthenaStatewireThreadListState>(\n () => ({\n threads: data,\n isLoading,\n activeThreadId: active.id,\n isNewChat: active.isNew,\n selectThread,\n newThread,\n refresh,\n titleSource,\n }),\n [data, isLoading, active.id, active.isNew, selectThread, newThread, refresh, titleSource],\n );\n\n return (\n <AthenaStatewireThreadListContext.Provider value={value}>\n {children}\n </AthenaStatewireThreadListContext.Provider>\n );\n}\n\n/**\n * Provides the statewire thread-list state, with an SDK-scoped QueryClient so\n * consumers do not need their own QueryClientProvider. `syncUrl` (the\n * `…/v2/threads` mount) locates the conversation index beside it; without it\n * titles fall back to the REST poll.\n */\nexport function AthenaStatewireThreadListProvider({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n initialThreadId,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n initialThreadId?: string;\n children: ReactNode;\n}) {\n const [queryClient] = useState(() => new QueryClient());\n return (\n <QueryClientProvider client={queryClient}>\n <StatewireThreadListState\n backendUrl={backendUrl}\n syncUrl={syncUrl}\n apiKey={apiKey}\n token={token}\n getToken={getToken}\n appId={appId}\n initialThreadId={initialThreadId}\n >\n {children}\n </StatewireThreadListState>\n </QueryClientProvider>\n );\n}\n\nconst TITLE_POLL_DELAY_MS = 5000;\nconst TITLE_POLL_INTERVAL_MS = 2000;\nconst TITLE_POLL_MAX_DURATION_MS = 60_000;\n\n/**\n * Fallback for hosts without a live conversation index (`titleSource: 'poll'`,\n * i.e. no signed-in principal): refreshes the thread list until a\n * freshly-started thread's server-generated title appears. Idle while the\n * index carries titles. Mount inside the statewire runtime scope (needs aui\n * state).\n */\nexport function StatewireThreadTitlePoller(): null {\n const list = useAthenaStatewireThreadList();\n const hasMessages = useAuiState((s) => (s.optional.thread?.messages.length ?? 0) > 0);\n\n const activeThreadId = list?.activeThreadId ?? null;\n const titleSource = list?.titleSource ?? 'poll';\n const entry = list?.threads.find((thread) => thread.id === activeThreadId);\n const title = entry?.title?.trim() ?? '';\n const hasTitle = title.length > 0 && !isSerializedContentPartsTitle(title);\n\n const polledThreadsRef = useRef<Set<string>>(new Set());\n const refreshRef = useRef(list?.refresh);\n refreshRef.current = list?.refresh;\n\n useEffect(() => {\n if (!activeThreadId || !hasMessages || hasTitle || titleSource === 'index') return;\n if (polledThreadsRef.current.has(activeThreadId)) return;\n polledThreadsRef.current.add(activeThreadId);\n\n let intervalId: ReturnType<typeof setInterval> | null = null;\n const startId = setTimeout(() => {\n intervalId = setInterval(() => refreshRef.current?.(), TITLE_POLL_INTERVAL_MS);\n }, TITLE_POLL_DELAY_MS);\n const stopId = setTimeout(() => {\n if (intervalId !== null) clearInterval(intervalId);\n }, TITLE_POLL_MAX_DURATION_MS);\n\n return () => {\n clearTimeout(startId);\n clearTimeout(stopId);\n if (intervalId !== null) clearInterval(intervalId);\n };\n }, [activeThreadId, hasMessages, hasTitle, titleSource]);\n\n return null;\n}\n"],"names":["_a"],"mappings":"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"}
@@ -10,10 +10,11 @@ require("../packages/agent-runtime/src/statewire-state.cjs");
10
10
  require("../packages/agent-runtime/src/messages.cjs");
11
11
  require("@assistant-ui/react-statewire");
12
12
  require("@assistant-ui/store");
13
- require("@assistant-ui/react-statewire/local-storage");
13
+ require("../packages/agent-runtime/src/quota-safe-local-storage-session.cjs");
14
14
  require("../packages/agent-runtime/src/statewire-attach-observer.cjs");
15
15
  require("../packages/agent-runtime/src/thread-status.cjs");
16
16
  require("@assistant-ui/core");
17
+ require("../packages/agent-runtime/src/thread-handoff.cjs");
17
18
  const reactQuery = require("@tanstack/react-query");
18
19
  const api = require("./api.cjs");
19
20
  const conversationListFetcher = require("./conversation-list-fetcher.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"use-rest-conversation-history.cjs","sources":["../../src/threads/use-rest-conversation-history.ts"],"sourcesContent":["import {\n type ConversationSummary,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { useMutation } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { archiveThread, setThreadReadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\n\nexport type RestConversationAuth = {\n apiKey?: string;\n token?: string | null;\n};\n\nexport interface UseRestConversationHistoryOptions {\n backendUrl: string;\n /** Non-secret identity included in the query cache boundary. */\n principalId: string;\n getAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n search?: string;\n enabled?: boolean;\n pageSize?: number;\n}\n\n/**\n * One inclusive, paginated conversation controller for satellite clients.\n * No app/channel filter is applied: authorization determines the user's rows,\n * while origin and automation metadata remain visible for UI filtering.\n */\nexport function useRestConversationHistory({\n backendUrl,\n principalId,\n getAuth,\n search,\n enabled = true,\n pageSize = 50,\n}: UseRestConversationHistoryOptions) {\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, getAuth }),\n [backendUrl, getAuth],\n );\n const list = useConversationList({\n fetchPage,\n filter: search?.trim() ? { search: search.trim() } : {},\n pageSize,\n scopeKey: `${backendUrl}::${principalId || 'unknown-principal'}`,\n enabled: enabled && principalId.length > 0,\n });\n\n const archive = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (threadId: string) => {\n await archiveThread(backendUrl, await getAuth(), threadId);\n return threadId;\n },\n onSuccess: (threadId) => list.removeConversation(threadId),\n });\n\n const readState = useMutation({\n mutationKey: ['conversation-history', 'read-state', backendUrl, principalId],\n mutationFn: async ({\n threadId,\n isUnread,\n }: {\n threadId: string;\n isUnread: boolean;\n }) => setThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n onSuccess: (result) =>\n list.patchConversation(result.thread_id, { isUnread: result.is_unread }),\n });\n\n return {\n ...list,\n archiveConversation: archive.mutate,\n archivePending: archive.isPending,\n setConversationReadState: readState.mutate,\n readStatePending: readState.isPending,\n };\n}\n\nconst GENERIC_TITLES = new Set([\n 'new chat',\n 'new conversation',\n 'untitled',\n 'untitled conversation',\n]);\n\n/** Prefer a useful server title, then a normalized last-message preview. */\nexport function conversationDisplayTitle(\n conversation: Pick<ConversationSummary, 'title' | 'preview'>,\n): string {\n const title = conversation.title.trim();\n if (title && !GENERIC_TITLES.has(title.toLowerCase())) return title;\n const preview = conversation.preview?.replace(/\\s+/g, ' ').trim();\n if (preview) return preview.length > 80 ? `${preview.slice(0, 77)}…` : preview;\n return 'Untitled conversation';\n}\n"],"names":["useMemo","createRestConversationListFetcher","useConversationList","useMutation","archiveThread","setThreadReadState"],"mappings":";;;;;;;;;;;;;;;;;;;AA6BO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,GAAsC;AACpC,QAAM,YAAYA,MAAAA;AAAAA,IAChB,MAAMC,0DAAkC,EAAE,YAAY,SAAS;AAAA,IAC/D,CAAC,YAAY,OAAO;AAAA,EAAA;AAEtB,QAAM,OAAOC,oBAAAA,oBAAoB;AAAA,IAC/B;AAAA,IACA,SAAQ,iCAAQ,UAAS,EAAE,QAAQ,OAAO,KAAA,EAAK,IAAM,CAAA;AAAA,IACrD;AAAA,IACA,UAAU,GAAG,UAAU,KAAK,eAAe,mBAAmB;AAAA,IAC9D,SAAS,WAAW,YAAY,SAAS;AAAA,EAAA,CAC1C;AAED,QAAM,UAAUC,WAAAA,YAAY;AAAA,IAC1B,aAAa,CAAC,wBAAwB,WAAW,YAAY,WAAW;AAAA,IACxE,YAAY,OAAO,aAAqB;AACtC,YAAMC,IAAAA,cAAc,YAAY,MAAM,QAAA,GAAW,QAAQ;AACzD,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,aAAa,KAAK,mBAAmB,QAAQ;AAAA,EAAA,CAC1D;AAED,QAAM,YAAYD,WAAAA,YAAY;AAAA,IAC5B,aAAa,CAAC,wBAAwB,cAAc,YAAY,WAAW;AAAA,IAC3E,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,MAIIE,IAAAA,mBAAmB,YAAY,MAAM,WAAW,EAAE,UAAU,UAAU;AAAA,IAC5E,WAAW,CAAC,WACV,KAAK,kBAAkB,OAAO,WAAW,EAAE,UAAU,OAAO,UAAA,CAAW;AAAA,EAAA,CAC1E;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,qBAAqB,QAAQ;AAAA,IAC7B,gBAAgB,QAAQ;AAAA,IACxB,0BAA0B,UAAU;AAAA,IACpC,kBAAkB,UAAU;AAAA,EAAA;AAEhC;AAEA,MAAM,qCAAqB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,yBACd,cACQ;;AACR,QAAM,QAAQ,aAAa,MAAM,KAAA;AACjC,MAAI,SAAS,CAAC,eAAe,IAAI,MAAM,YAAA,CAAa,EAAG,QAAO;AAC9D,QAAM,WAAU,kBAAa,YAAb,mBAAsB,QAAQ,QAAQ,KAAK;AAC3D,MAAI,QAAS,QAAO,QAAQ,SAAS,KAAK,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM;AACvE,SAAO;AACT;;;"}
1
+ {"version":3,"file":"use-rest-conversation-history.cjs","sources":["../../src/threads/use-rest-conversation-history.ts"],"sourcesContent":["import {\n type ConversationSummary,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { useMutation } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { archiveThread, setThreadReadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\n\nexport type RestConversationAuth = {\n apiKey?: string;\n token?: string | null;\n};\n\nexport interface UseRestConversationHistoryOptions {\n backendUrl: string;\n /** Non-secret identity included in the query cache boundary. */\n principalId: string;\n getAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n search?: string;\n enabled?: boolean;\n pageSize?: number;\n}\n\n/**\n * One inclusive, paginated conversation controller for satellite clients.\n * No app/channel filter is applied: authorization determines the user's rows,\n * while origin and automation metadata remain visible for UI filtering.\n */\nexport function useRestConversationHistory({\n backendUrl,\n principalId,\n getAuth,\n search,\n enabled = true,\n pageSize = 50,\n}: UseRestConversationHistoryOptions) {\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, getAuth }),\n [backendUrl, getAuth],\n );\n const list = useConversationList({\n fetchPage,\n filter: search?.trim() ? { search: search.trim() } : {},\n pageSize,\n scopeKey: `${backendUrl}::${principalId || 'unknown-principal'}`,\n enabled: enabled && principalId.length > 0,\n });\n\n const archive = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (threadId: string) => {\n await archiveThread(backendUrl, await getAuth(), threadId);\n return threadId;\n },\n onSuccess: (threadId) => list.removeConversation(threadId),\n });\n\n const readState = useMutation({\n mutationKey: ['conversation-history', 'read-state', backendUrl, principalId],\n mutationFn: async ({\n threadId,\n isUnread,\n }: {\n threadId: string;\n isUnread: boolean;\n }) => setThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n onSuccess: (result) =>\n list.patchConversation(result.thread_id, { isUnread: result.is_unread }),\n });\n\n return {\n ...list,\n archiveConversation: archive.mutate,\n archivePending: archive.isPending,\n setConversationReadState: readState.mutate,\n readStatePending: readState.isPending,\n };\n}\n\nconst GENERIC_TITLES = new Set([\n 'new chat',\n 'new conversation',\n 'untitled',\n 'untitled conversation',\n]);\n\n/** Prefer a useful server title, then a normalized last-message preview. */\nexport function conversationDisplayTitle(\n conversation: Pick<ConversationSummary, 'title' | 'preview'>,\n): string {\n const title = conversation.title.trim();\n if (title && !GENERIC_TITLES.has(title.toLowerCase())) return title;\n const preview = conversation.preview?.replace(/\\s+/g, ' ').trim();\n if (preview) return preview.length > 80 ? `${preview.slice(0, 77)}…` : preview;\n return 'Untitled conversation';\n}\n"],"names":["useMemo","createRestConversationListFetcher","useConversationList","useMutation","archiveThread","setThreadReadState"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6BO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,GAAsC;AACpC,QAAM,YAAYA,MAAAA;AAAAA,IAChB,MAAMC,0DAAkC,EAAE,YAAY,SAAS;AAAA,IAC/D,CAAC,YAAY,OAAO;AAAA,EAAA;AAEtB,QAAM,OAAOC,oBAAAA,oBAAoB;AAAA,IAC/B;AAAA,IACA,SAAQ,iCAAQ,UAAS,EAAE,QAAQ,OAAO,KAAA,EAAK,IAAM,CAAA;AAAA,IACrD;AAAA,IACA,UAAU,GAAG,UAAU,KAAK,eAAe,mBAAmB;AAAA,IAC9D,SAAS,WAAW,YAAY,SAAS;AAAA,EAAA,CAC1C;AAED,QAAM,UAAUC,WAAAA,YAAY;AAAA,IAC1B,aAAa,CAAC,wBAAwB,WAAW,YAAY,WAAW;AAAA,IACxE,YAAY,OAAO,aAAqB;AACtC,YAAMC,IAAAA,cAAc,YAAY,MAAM,QAAA,GAAW,QAAQ;AACzD,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,aAAa,KAAK,mBAAmB,QAAQ;AAAA,EAAA,CAC1D;AAED,QAAM,YAAYD,WAAAA,YAAY;AAAA,IAC5B,aAAa,CAAC,wBAAwB,cAAc,YAAY,WAAW;AAAA,IAC3E,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,MAIIE,IAAAA,mBAAmB,YAAY,MAAM,WAAW,EAAE,UAAU,UAAU;AAAA,IAC5E,WAAW,CAAC,WACV,KAAK,kBAAkB,OAAO,WAAW,EAAE,UAAU,OAAO,UAAA,CAAW;AAAA,EAAA,CAC1E;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,qBAAqB,QAAQ;AAAA,IAC7B,gBAAgB,QAAQ;AAAA,IACxB,0BAA0B,UAAU;AAAA,IACpC,kBAAkB,UAAU;AAAA,EAAA;AAEhC;AAEA,MAAM,qCAAqB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,yBACd,cACQ;;AACR,QAAM,QAAQ,aAAa,MAAM,KAAA;AACjC,MAAI,SAAS,CAAC,eAAe,IAAI,MAAM,YAAA,CAAa,EAAG,QAAO;AAC9D,QAAM,WAAU,kBAAa,YAAb,mBAAsB,QAAQ,QAAQ,KAAK;AAC3D,MAAI,QAAS,QAAO,QAAQ,SAAS,KAAK,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM;AACvE,SAAO;AACT;;;"}
@@ -8,10 +8,11 @@ import "../packages/agent-runtime/src/statewire-state.js";
8
8
  import "../packages/agent-runtime/src/messages.js";
9
9
  import "@assistant-ui/react-statewire";
10
10
  import "@assistant-ui/store";
11
- import "@assistant-ui/react-statewire/local-storage";
11
+ import "../packages/agent-runtime/src/quota-safe-local-storage-session.js";
12
12
  import "../packages/agent-runtime/src/statewire-attach-observer.js";
13
13
  import "../packages/agent-runtime/src/thread-status.js";
14
14
  import "@assistant-ui/core";
15
+ import "../packages/agent-runtime/src/thread-handoff.js";
15
16
  import { useMutation } from "@tanstack/react-query";
16
17
  import { archiveThread, setThreadReadState } from "./api.js";
17
18
  import { createRestConversationListFetcher } from "./conversation-list-fetcher.js";
@@ -1 +1 @@
1
- {"version":3,"file":"use-rest-conversation-history.js","sources":["../../src/threads/use-rest-conversation-history.ts"],"sourcesContent":["import {\n type ConversationSummary,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { useMutation } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { archiveThread, setThreadReadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\n\nexport type RestConversationAuth = {\n apiKey?: string;\n token?: string | null;\n};\n\nexport interface UseRestConversationHistoryOptions {\n backendUrl: string;\n /** Non-secret identity included in the query cache boundary. */\n principalId: string;\n getAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n search?: string;\n enabled?: boolean;\n pageSize?: number;\n}\n\n/**\n * One inclusive, paginated conversation controller for satellite clients.\n * No app/channel filter is applied: authorization determines the user's rows,\n * while origin and automation metadata remain visible for UI filtering.\n */\nexport function useRestConversationHistory({\n backendUrl,\n principalId,\n getAuth,\n search,\n enabled = true,\n pageSize = 50,\n}: UseRestConversationHistoryOptions) {\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, getAuth }),\n [backendUrl, getAuth],\n );\n const list = useConversationList({\n fetchPage,\n filter: search?.trim() ? { search: search.trim() } : {},\n pageSize,\n scopeKey: `${backendUrl}::${principalId || 'unknown-principal'}`,\n enabled: enabled && principalId.length > 0,\n });\n\n const archive = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (threadId: string) => {\n await archiveThread(backendUrl, await getAuth(), threadId);\n return threadId;\n },\n onSuccess: (threadId) => list.removeConversation(threadId),\n });\n\n const readState = useMutation({\n mutationKey: ['conversation-history', 'read-state', backendUrl, principalId],\n mutationFn: async ({\n threadId,\n isUnread,\n }: {\n threadId: string;\n isUnread: boolean;\n }) => setThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n onSuccess: (result) =>\n list.patchConversation(result.thread_id, { isUnread: result.is_unread }),\n });\n\n return {\n ...list,\n archiveConversation: archive.mutate,\n archivePending: archive.isPending,\n setConversationReadState: readState.mutate,\n readStatePending: readState.isPending,\n };\n}\n\nconst GENERIC_TITLES = new Set([\n 'new chat',\n 'new conversation',\n 'untitled',\n 'untitled conversation',\n]);\n\n/** Prefer a useful server title, then a normalized last-message preview. */\nexport function conversationDisplayTitle(\n conversation: Pick<ConversationSummary, 'title' | 'preview'>,\n): string {\n const title = conversation.title.trim();\n if (title && !GENERIC_TITLES.has(title.toLowerCase())) return title;\n const preview = conversation.preview?.replace(/\\s+/g, ' ').trim();\n if (preview) return preview.length > 80 ? `${preview.slice(0, 77)}…` : preview;\n return 'Untitled conversation';\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA6BO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,GAAsC;AACpC,QAAM,YAAY;AAAA,IAChB,MAAM,kCAAkC,EAAE,YAAY,SAAS;AAAA,IAC/D,CAAC,YAAY,OAAO;AAAA,EAAA;AAEtB,QAAM,OAAO,oBAAoB;AAAA,IAC/B;AAAA,IACA,SAAQ,iCAAQ,UAAS,EAAE,QAAQ,OAAO,KAAA,EAAK,IAAM,CAAA;AAAA,IACrD;AAAA,IACA,UAAU,GAAG,UAAU,KAAK,eAAe,mBAAmB;AAAA,IAC9D,SAAS,WAAW,YAAY,SAAS;AAAA,EAAA,CAC1C;AAED,QAAM,UAAU,YAAY;AAAA,IAC1B,aAAa,CAAC,wBAAwB,WAAW,YAAY,WAAW;AAAA,IACxE,YAAY,OAAO,aAAqB;AACtC,YAAM,cAAc,YAAY,MAAM,QAAA,GAAW,QAAQ;AACzD,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,aAAa,KAAK,mBAAmB,QAAQ;AAAA,EAAA,CAC1D;AAED,QAAM,YAAY,YAAY;AAAA,IAC5B,aAAa,CAAC,wBAAwB,cAAc,YAAY,WAAW;AAAA,IAC3E,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,MAII,mBAAmB,YAAY,MAAM,WAAW,EAAE,UAAU,UAAU;AAAA,IAC5E,WAAW,CAAC,WACV,KAAK,kBAAkB,OAAO,WAAW,EAAE,UAAU,OAAO,UAAA,CAAW;AAAA,EAAA,CAC1E;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,qBAAqB,QAAQ;AAAA,IAC7B,gBAAgB,QAAQ;AAAA,IACxB,0BAA0B,UAAU;AAAA,IACpC,kBAAkB,UAAU;AAAA,EAAA;AAEhC;AAEA,MAAM,qCAAqB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,yBACd,cACQ;;AACR,QAAM,QAAQ,aAAa,MAAM,KAAA;AACjC,MAAI,SAAS,CAAC,eAAe,IAAI,MAAM,YAAA,CAAa,EAAG,QAAO;AAC9D,QAAM,WAAU,kBAAa,YAAb,mBAAsB,QAAQ,QAAQ,KAAK;AAC3D,MAAI,QAAS,QAAO,QAAQ,SAAS,KAAK,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM;AACvE,SAAO;AACT;"}
1
+ {"version":3,"file":"use-rest-conversation-history.js","sources":["../../src/threads/use-rest-conversation-history.ts"],"sourcesContent":["import {\n type ConversationSummary,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { useMutation } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { archiveThread, setThreadReadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\n\nexport type RestConversationAuth = {\n apiKey?: string;\n token?: string | null;\n};\n\nexport interface UseRestConversationHistoryOptions {\n backendUrl: string;\n /** Non-secret identity included in the query cache boundary. */\n principalId: string;\n getAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n search?: string;\n enabled?: boolean;\n pageSize?: number;\n}\n\n/**\n * One inclusive, paginated conversation controller for satellite clients.\n * No app/channel filter is applied: authorization determines the user's rows,\n * while origin and automation metadata remain visible for UI filtering.\n */\nexport function useRestConversationHistory({\n backendUrl,\n principalId,\n getAuth,\n search,\n enabled = true,\n pageSize = 50,\n}: UseRestConversationHistoryOptions) {\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, getAuth }),\n [backendUrl, getAuth],\n );\n const list = useConversationList({\n fetchPage,\n filter: search?.trim() ? { search: search.trim() } : {},\n pageSize,\n scopeKey: `${backendUrl}::${principalId || 'unknown-principal'}`,\n enabled: enabled && principalId.length > 0,\n });\n\n const archive = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (threadId: string) => {\n await archiveThread(backendUrl, await getAuth(), threadId);\n return threadId;\n },\n onSuccess: (threadId) => list.removeConversation(threadId),\n });\n\n const readState = useMutation({\n mutationKey: ['conversation-history', 'read-state', backendUrl, principalId],\n mutationFn: async ({\n threadId,\n isUnread,\n }: {\n threadId: string;\n isUnread: boolean;\n }) => setThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n onSuccess: (result) =>\n list.patchConversation(result.thread_id, { isUnread: result.is_unread }),\n });\n\n return {\n ...list,\n archiveConversation: archive.mutate,\n archivePending: archive.isPending,\n setConversationReadState: readState.mutate,\n readStatePending: readState.isPending,\n };\n}\n\nconst GENERIC_TITLES = new Set([\n 'new chat',\n 'new conversation',\n 'untitled',\n 'untitled conversation',\n]);\n\n/** Prefer a useful server title, then a normalized last-message preview. */\nexport function conversationDisplayTitle(\n conversation: Pick<ConversationSummary, 'title' | 'preview'>,\n): string {\n const title = conversation.title.trim();\n if (title && !GENERIC_TITLES.has(title.toLowerCase())) return title;\n const preview = conversation.preview?.replace(/\\s+/g, ' ').trim();\n if (preview) return preview.length > 80 ? `${preview.slice(0, 77)}…` : preview;\n return 'Untitled conversation';\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AA6BO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,GAAsC;AACpC,QAAM,YAAY;AAAA,IAChB,MAAM,kCAAkC,EAAE,YAAY,SAAS;AAAA,IAC/D,CAAC,YAAY,OAAO;AAAA,EAAA;AAEtB,QAAM,OAAO,oBAAoB;AAAA,IAC/B;AAAA,IACA,SAAQ,iCAAQ,UAAS,EAAE,QAAQ,OAAO,KAAA,EAAK,IAAM,CAAA;AAAA,IACrD;AAAA,IACA,UAAU,GAAG,UAAU,KAAK,eAAe,mBAAmB;AAAA,IAC9D,SAAS,WAAW,YAAY,SAAS;AAAA,EAAA,CAC1C;AAED,QAAM,UAAU,YAAY;AAAA,IAC1B,aAAa,CAAC,wBAAwB,WAAW,YAAY,WAAW;AAAA,IACxE,YAAY,OAAO,aAAqB;AACtC,YAAM,cAAc,YAAY,MAAM,QAAA,GAAW,QAAQ;AACzD,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,aAAa,KAAK,mBAAmB,QAAQ;AAAA,EAAA,CAC1D;AAED,QAAM,YAAY,YAAY;AAAA,IAC5B,aAAa,CAAC,wBAAwB,cAAc,YAAY,WAAW;AAAA,IAC3E,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,MAII,mBAAmB,YAAY,MAAM,WAAW,EAAE,UAAU,UAAU;AAAA,IAC5E,WAAW,CAAC,WACV,KAAK,kBAAkB,OAAO,WAAW,EAAE,UAAU,OAAO,UAAA,CAAW;AAAA,EAAA,CAC1E;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,qBAAqB,QAAQ;AAAA,IAC7B,gBAAgB,QAAQ;AAAA,IACxB,0BAA0B,UAAU;AAAA,IACpC,kBAAkB,UAAU;AAAA,EAAA;AAEhC;AAEA,MAAM,qCAAqB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,yBACd,cACQ;;AACR,QAAM,QAAQ,aAAa,MAAM,KAAA;AACjC,MAAI,SAAS,CAAC,eAAe,IAAI,MAAM,YAAA,CAAa,EAAG,QAAO;AAC9D,QAAM,WAAU,kBAAa,YAAb,mBAAsB,QAAQ,QAAQ,KAAK;AAC3D,MAAI,QAAS,QAAO,QAAQ,SAAS,KAAK,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM;AACvE,SAAO;AACT;"}
@@ -8,13 +8,14 @@ require("../packages/agent-runtime/src/statewire-state.cjs");
8
8
  require("../packages/agent-runtime/src/messages.cjs");
9
9
  require("@assistant-ui/react-statewire");
10
10
  require("@assistant-ui/store");
11
- require("@assistant-ui/react-statewire/local-storage");
11
+ require("../packages/agent-runtime/src/quota-safe-local-storage-session.cjs");
12
12
  require("../packages/agent-runtime/src/statewire-suspended.cjs");
13
13
  require("@assistant-ui/tap");
14
14
  require("../packages/agent-runtime/src/statewire-attach-observer.cjs");
15
15
  require("statewire");
16
16
  require("../packages/agent-runtime/src/thread-status.cjs");
17
17
  require("@assistant-ui/core");
18
+ require("../packages/agent-runtime/src/thread-handoff.cjs");
18
19
  const api = require("./api.cjs");
19
20
  const useRestConversationHistory = require("./use-rest-conversation-history.cjs");
20
21
  function conversationSummaryFromIndexEntry(entry) {
@@ -69,6 +70,7 @@ function shouldUseRestConversationHistory({
69
70
  function useStatewireConversationHistory({
70
71
  backendUrl,
71
72
  conversationIndexBaseUrl,
73
+ workspaceId,
72
74
  principalId,
73
75
  getAuth,
74
76
  headers,
@@ -78,9 +80,10 @@ function useStatewireConversationHistory({
78
80
  }) {
79
81
  const index = conversationIndex.useConversationIndex({
80
82
  baseUrl: conversationIndexBaseUrl,
83
+ workspaceId: workspaceId || "pending-workspace",
81
84
  userId: principalId || "pending-user",
82
85
  headers,
83
- enabled: enabled && principalId.length > 0,
86
+ enabled: enabled && workspaceId.length > 0 && principalId.length > 0,
84
87
  sse
85
88
  });
86
89
  const supportsStatewirePaging = index.totalCount !== null;
@@ -1 +1 @@
1
- {"version":3,"file":"use-statewire-conversation-history.cjs","sources":["../../src/threads/use-statewire-conversation-history.ts"],"sourcesContent":["import {\n\ttype ConversationIndexEntry,\n\ttype ConversationSummary,\n\ttype UseConversationIndexOptions,\n\tuseConversationIndex,\n} from \"@athenaintel/agent-runtime\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { archiveThread, setThreadReadState } from \"./api\";\nimport {\n\ttype RestConversationAuth,\n\tuseRestConversationHistory,\n} from \"./use-rest-conversation-history\";\n\nexport interface UseStatewireConversationHistoryOptions {\n\tbackendUrl: string;\n\tconversationIndexBaseUrl: string;\n\tprincipalId: string;\n\tgetAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n\theaders: UseConversationIndexOptions[\"headers\"];\n\tsearch?: string;\n\tenabled?: boolean;\n\tsse?: boolean;\n}\n\n/** Convert the replicated wire row into the shared cross-surface contract. */\nexport function conversationSummaryFromIndexEntry(\n\tentry: ConversationIndexEntry,\n): ConversationSummary {\n\treturn {\n\t\tthreadId: entry.thread_id,\n\t\ttitle: entry.title,\n\t\tupdatedAt: entry.updated_at,\n\t\tcreatedAt: null,\n\t\tstate: entry.state,\n\t\truntime: entry.runtime,\n\t\tsourceChannel: entry.start_channel,\n\t\tassetType: entry.asset_type,\n\t\tassetId: entry.asset_id ?? null,\n\t\tappId: entry.app_id ?? null,\n\t\ttriggerType: entry.trigger_type ?? null,\n\t\tpreview: entry.last_message_preview ?? null,\n\t\tmessageCount: entry.message_count ?? null,\n\t\tisUnread: entry.is_unread ?? false,\n\t\tsessionStatus: entry.session_status ?? null,\n\t\trunStatus: entry.run_status ?? null,\n\t};\n}\n\nexport function conversationHistorySource({\n\tindexEntries,\n\trestConversations,\n\tsupportsStatewirePaging,\n\thasSearch,\n}: {\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\trestConversations: readonly ConversationSummary[];\n\tsupportsStatewirePaging: boolean;\n\thasSearch: boolean;\n}): ConversationSummary[] {\n\t// Search is server-backed so it covers the user's entire authorized history,\n\t// including rows older than the Statewire live window. An empty query uses\n\t// Statewire as the render source; REST only supplements rolling old hosts.\n\tif (hasSearch) return [...restConversations];\n\tconst statewireItems = (indexEntries ?? []).map(\n\t\tconversationSummaryFromIndexEntry,\n\t);\n\tif (supportsStatewirePaging) return statewireItems;\n\tconst statewireIds = new Set(statewireItems.map((item) => item.threadId));\n\treturn [\n\t\t...statewireItems,\n\t\t...restConversations.filter(\n\t\t\t(conversation) => !statewireIds.has(conversation.threadId),\n\t\t),\n\t];\n}\n\nexport function shouldUseRestConversationHistory({\n\thasSearch,\n\tindexEntries,\n\tsupportsStatewirePaging,\n\tconnectionStatus,\n}: {\n\thasSearch: boolean;\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\tsupportsStatewirePaging: boolean;\n\tconnectionStatus: string;\n}): boolean {\n\tif (hasSearch) return true;\n\tif (supportsStatewirePaging) return false;\n\t// An old host is identifiable once its snapshot arrives. A transport that\n\t// fails or is parked before any snapshot also needs the independent REST\n\t// path; otherwise entries stays null and the history panel loads forever.\n\treturn (\n\t\tindexEntries !== null ||\n\t\tconnectionStatus === \"reconnecting\" ||\n\t\tconnectionStatus === \"gone\"\n\t);\n}\n\n/**\n * Inclusive satellite conversation history backed by the user's Pinned\n * Statewire instance. The replicated window is the render source; refreshes,\n * pagination, thread creation, lifecycle changes, and title changes arrive on\n * that same channel. A non-empty search deliberately uses the authorized REST\n * list endpoint so matches are not limited to the replicated newest window.\n */\nexport function useStatewireConversationHistory({\n\tbackendUrl,\n\tconversationIndexBaseUrl,\n\tprincipalId,\n\tgetAuth,\n\theaders,\n\tsearch,\n\tenabled = true,\n\tsse = false,\n}: UseStatewireConversationHistoryOptions) {\n\tconst index = useConversationIndex({\n\t\tbaseUrl: conversationIndexBaseUrl,\n\t\tuserId: principalId || \"pending-user\",\n\t\theaders,\n\t\tenabled: enabled && principalId.length > 0,\n\t\tsse,\n\t});\n\t// Rolling deploy compatibility: the pre-paging index snapshot has no\n\t// total_count. It still renders live rows immediately, while the old REST\n\t// pager remains available only until the upgraded host activates.\n\tconst supportsStatewirePaging = index.totalCount !== null;\n\tconst normalizedSearch = search?.trim().toLowerCase() ?? \"\";\n\tconst hasSearch = normalizedSearch.length > 0;\n\tconst usesRestHistory = shouldUseRestConversationHistory({\n\t\thasSearch,\n\t\tindexEntries: index.entries,\n\t\tsupportsStatewirePaging,\n\t\tconnectionStatus: index.connection.status,\n\t});\n\tconst legacyHistory = useRestConversationHistory({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\tsearch,\n\t\tenabled: enabled && principalId.length > 0 && usesRestHistory,\n\t});\n\tconst [readOverrides, setReadOverrides] = useState<Record<string, boolean>>(\n\t\t{},\n\t);\n\tconst [archivedThreadIds, setArchivedThreadIds] = useState<\n\t\tReadonlySet<string>\n\t>(() => new Set());\n\n\tuseEffect(() => {\n\t\tif (index.entries === null || archivedThreadIds.size === 0) return;\n\t\tconst visibleIds = new Set(index.entries.map((entry) => entry.thread_id));\n\t\tsetArchivedThreadIds((current) => {\n\t\t\tconst next = new Set(\n\t\t\t\t[...current].filter((threadId) => visibleIds.has(threadId)),\n\t\t\t);\n\t\t\treturn next.size === current.size ? current : next;\n\t\t});\n\t}, [archivedThreadIds.size, index.entries]);\n\n\tconst conversations = useMemo(() => {\n\t\treturn conversationHistorySource({\n\t\t\tindexEntries: index.entries,\n\t\t\trestConversations: legacyHistory.conversations,\n\t\t\tsupportsStatewirePaging,\n\t\t\thasSearch,\n\t\t})\n\t\t\t.filter((conversation) => !archivedThreadIds.has(conversation.threadId))\n\t\t\t.map((conversation) => ({\n\t\t\t\t...conversation,\n\t\t\t\tisUnread: readOverrides[conversation.threadId] ?? conversation.isUnread,\n\t\t\t}));\n\t}, [\n\t\tarchivedThreadIds,\n\t\tindex.entries,\n\t\tlegacyHistory.conversations,\n\t\thasSearch,\n\t\treadOverrides,\n\t\tsupportsStatewirePaging,\n\t]);\n\n\tconst refreshMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"refresh\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.refresh() : index.refresh(),\n\t});\n\tconst loadMoreMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"load-more\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.fetchNextPage() : index.loadMore(),\n\t});\n\tconst archive = useMutation({\n\t\tmutationKey: [\"conversation-history\", \"archive\", backendUrl, principalId],\n\t\tmutationFn: async (threadId: string) => {\n\t\t\tawait archiveThread(backendUrl, await getAuth(), threadId);\n\t\t\treturn threadId;\n\t\t},\n\t\tonMutate: (threadId) => {\n\t\t\tsetArchivedThreadIds((current) => new Set(current).add(threadId));\n\t\t},\n\t\tonError: (_error, threadId) => {\n\t\t\tsetArchivedThreadIds((current) => {\n\t\t\t\tconst next = new Set(current);\n\t\t\t\tnext.delete(threadId);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\trefreshMutation.mutate();\n\t\t},\n\t});\n\tconst readState = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-history\",\n\t\t\t\"read-state\",\n\t\t\tbackendUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: async ({\n\t\t\tthreadId,\n\t\t\tisUnread,\n\t\t}: {\n\t\t\tthreadId: string;\n\t\t\tisUnread: boolean;\n\t\t}) =>\n\t\t\tsetThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n\t\tonMutate: ({ threadId, isUnread }) => {\n\t\t\tconst previous = readOverrides[threadId];\n\t\t\tsetReadOverrides((current) => ({ ...current, [threadId]: isUnread }));\n\t\t\treturn { previous, threadId };\n\t\t},\n\t\tonError: (_error, _variables, context) => {\n\t\t\tif (!context) return;\n\t\t\tsetReadOverrides((current) => {\n\t\t\t\tconst next = { ...current };\n\t\t\t\tif (context.previous === undefined) delete next[context.threadId];\n\t\t\t\telse next[context.threadId] = context.previous;\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: (result) => {\n\t\t\tsetReadOverrides((current) => ({\n\t\t\t\t...current,\n\t\t\t\t[result.thread_id]: result.is_unread,\n\t\t\t}));\n\t\t\trefreshMutation.mutate(undefined, {\n\t\t\t\tonSettled: () => {\n\t\t\t\t\tsetReadOverrides((current) => {\n\t\t\t\t\t\tconst next = { ...current };\n\t\t\t\t\t\tdelete next[result.thread_id];\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst refresh = useCallback(\n\t\t() => refreshMutation.mutateAsync(),\n\t\t[refreshMutation.mutateAsync],\n\t);\n\tconst fetchNextPage = useCallback(\n\t\t() => loadMoreMutation.mutateAsync(),\n\t\t[loadMoreMutation.mutateAsync],\n\t);\n\n\treturn {\n\t\tconversations,\n\t\ttotalCount: usesRestHistory ? legacyHistory.totalCount : index.totalCount,\n\t\tisLoading:\n\t\t\tenabled &&\n\t\t\t(usesRestHistory\n\t\t\t\t? !legacyHistory.hasResolvedFirstPage\n\t\t\t\t: index.entries === null),\n\t\tisFetching:\n\t\t\trefreshMutation.isPending ||\n\t\t\tloadMoreMutation.isPending ||\n\t\t\tlegacyHistory.isFetching,\n\t\tisRefreshing: refreshMutation.isPending,\n\t\thasResolvedFirstPage: usesRestHistory\n\t\t\t? legacyHistory.hasResolvedFirstPage\n\t\t\t: index.entries !== null,\n\t\thasNextPage: usesRestHistory\n\t\t\t? legacyHistory.hasNextPage\n\t\t\t: index.hasNextPage,\n\t\tisFetchingNextPage: loadMoreMutation.isPending,\n\t\tfetchNextPage,\n\t\trefresh,\n\t\tarchiveConversation: archive.mutate,\n\t\tarchivePending: archive.isPending,\n\t\tsetConversationReadState: readState.mutate,\n\t\treadStatePending: readState.isPending,\n\t\tconnection: index.connection,\n\t};\n}\n"],"names":["useConversationIndex","useRestConversationHistory","useState","useEffect","useMemo","useMutation","archiveThread","setThreadReadState","useCallback"],"mappings":"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"}
1
+ {"version":3,"file":"use-statewire-conversation-history.cjs","sources":["../../src/threads/use-statewire-conversation-history.ts"],"sourcesContent":["import {\n\ttype ConversationIndexEntry,\n\ttype ConversationSummary,\n\ttype UseConversationIndexOptions,\n\tuseConversationIndex,\n} from \"@athenaintel/agent-runtime\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { archiveThread, setThreadReadState } from \"./api\";\nimport {\n\ttype RestConversationAuth,\n\tuseRestConversationHistory,\n} from \"./use-rest-conversation-history\";\n\nexport interface UseStatewireConversationHistoryOptions {\n\tbackendUrl: string;\n\tconversationIndexBaseUrl: string;\n\t/** The workspace being viewed; the index is one instance per (workspace, user). */\n\tworkspaceId: string;\n\tprincipalId: string;\n\tgetAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n\theaders: UseConversationIndexOptions[\"headers\"];\n\tsearch?: string;\n\tenabled?: boolean;\n\tsse?: boolean;\n}\n\n/** Convert the replicated wire row into the shared cross-surface contract. */\nexport function conversationSummaryFromIndexEntry(\n\tentry: ConversationIndexEntry,\n): ConversationSummary {\n\treturn {\n\t\tthreadId: entry.thread_id,\n\t\ttitle: entry.title,\n\t\tupdatedAt: entry.updated_at,\n\t\tcreatedAt: null,\n\t\tstate: entry.state,\n\t\truntime: entry.runtime,\n\t\tsourceChannel: entry.start_channel,\n\t\tassetType: entry.asset_type,\n\t\tassetId: entry.asset_id ?? null,\n\t\tappId: entry.app_id ?? null,\n\t\ttriggerType: entry.trigger_type ?? null,\n\t\tpreview: entry.last_message_preview ?? null,\n\t\tmessageCount: entry.message_count ?? null,\n\t\tisUnread: entry.is_unread ?? false,\n\t\tsessionStatus: entry.session_status ?? null,\n\t\trunStatus: entry.run_status ?? null,\n\t};\n}\n\nexport function conversationHistorySource({\n\tindexEntries,\n\trestConversations,\n\tsupportsStatewirePaging,\n\thasSearch,\n}: {\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\trestConversations: readonly ConversationSummary[];\n\tsupportsStatewirePaging: boolean;\n\thasSearch: boolean;\n}): ConversationSummary[] {\n\t// Search is server-backed so it covers the user's entire authorized history,\n\t// including rows older than the Statewire live window. An empty query uses\n\t// Statewire as the render source; REST only supplements rolling old hosts.\n\tif (hasSearch) return [...restConversations];\n\tconst statewireItems = (indexEntries ?? []).map(\n\t\tconversationSummaryFromIndexEntry,\n\t);\n\tif (supportsStatewirePaging) return statewireItems;\n\tconst statewireIds = new Set(statewireItems.map((item) => item.threadId));\n\treturn [\n\t\t...statewireItems,\n\t\t...restConversations.filter(\n\t\t\t(conversation) => !statewireIds.has(conversation.threadId),\n\t\t),\n\t];\n}\n\nexport function shouldUseRestConversationHistory({\n\thasSearch,\n\tindexEntries,\n\tsupportsStatewirePaging,\n\tconnectionStatus,\n}: {\n\thasSearch: boolean;\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\tsupportsStatewirePaging: boolean;\n\tconnectionStatus: string;\n}): boolean {\n\tif (hasSearch) return true;\n\tif (supportsStatewirePaging) return false;\n\t// An old host is identifiable once its snapshot arrives. A transport that\n\t// fails or is parked before any snapshot also needs the independent REST\n\t// path; otherwise entries stays null and the history panel loads forever.\n\treturn (\n\t\tindexEntries !== null ||\n\t\tconnectionStatus === \"reconnecting\" ||\n\t\tconnectionStatus === \"gone\"\n\t);\n}\n\n/**\n * Inclusive satellite conversation history backed by the user's Pinned\n * Statewire instance. The replicated window is the render source; refreshes,\n * pagination, thread creation, lifecycle changes, and title changes arrive on\n * that same channel. A non-empty search deliberately uses the authorized REST\n * list endpoint so matches are not limited to the replicated newest window.\n */\nexport function useStatewireConversationHistory({\n\tbackendUrl,\n\tconversationIndexBaseUrl,\n\tworkspaceId,\n\tprincipalId,\n\tgetAuth,\n\theaders,\n\tsearch,\n\tenabled = true,\n\tsse = false,\n}: UseStatewireConversationHistoryOptions) {\n\tconst index = useConversationIndex({\n\t\tbaseUrl: conversationIndexBaseUrl,\n\t\tworkspaceId: workspaceId || \"pending-workspace\",\n\t\tuserId: principalId || \"pending-user\",\n\t\theaders,\n\t\tenabled: enabled && workspaceId.length > 0 && principalId.length > 0,\n\t\tsse,\n\t});\n\t// Rolling deploy compatibility: the pre-paging index snapshot has no\n\t// total_count. It still renders live rows immediately, while the old REST\n\t// pager remains available only until the upgraded host activates.\n\tconst supportsStatewirePaging = index.totalCount !== null;\n\tconst normalizedSearch = search?.trim().toLowerCase() ?? \"\";\n\tconst hasSearch = normalizedSearch.length > 0;\n\tconst usesRestHistory = shouldUseRestConversationHistory({\n\t\thasSearch,\n\t\tindexEntries: index.entries,\n\t\tsupportsStatewirePaging,\n\t\tconnectionStatus: index.connection.status,\n\t});\n\tconst legacyHistory = useRestConversationHistory({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\tsearch,\n\t\tenabled: enabled && principalId.length > 0 && usesRestHistory,\n\t});\n\tconst [readOverrides, setReadOverrides] = useState<Record<string, boolean>>(\n\t\t{},\n\t);\n\tconst [archivedThreadIds, setArchivedThreadIds] = useState<\n\t\tReadonlySet<string>\n\t>(() => new Set());\n\n\tuseEffect(() => {\n\t\tif (index.entries === null || archivedThreadIds.size === 0) return;\n\t\tconst visibleIds = new Set(index.entries.map((entry) => entry.thread_id));\n\t\tsetArchivedThreadIds((current) => {\n\t\t\tconst next = new Set(\n\t\t\t\t[...current].filter((threadId) => visibleIds.has(threadId)),\n\t\t\t);\n\t\t\treturn next.size === current.size ? current : next;\n\t\t});\n\t}, [archivedThreadIds.size, index.entries]);\n\n\tconst conversations = useMemo(() => {\n\t\treturn conversationHistorySource({\n\t\t\tindexEntries: index.entries,\n\t\t\trestConversations: legacyHistory.conversations,\n\t\t\tsupportsStatewirePaging,\n\t\t\thasSearch,\n\t\t})\n\t\t\t.filter((conversation) => !archivedThreadIds.has(conversation.threadId))\n\t\t\t.map((conversation) => ({\n\t\t\t\t...conversation,\n\t\t\t\tisUnread: readOverrides[conversation.threadId] ?? conversation.isUnread,\n\t\t\t}));\n\t}, [\n\t\tarchivedThreadIds,\n\t\tindex.entries,\n\t\tlegacyHistory.conversations,\n\t\thasSearch,\n\t\treadOverrides,\n\t\tsupportsStatewirePaging,\n\t]);\n\n\tconst refreshMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"refresh\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.refresh() : index.refresh(),\n\t});\n\tconst loadMoreMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"load-more\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.fetchNextPage() : index.loadMore(),\n\t});\n\tconst archive = useMutation({\n\t\tmutationKey: [\"conversation-history\", \"archive\", backendUrl, principalId],\n\t\tmutationFn: async (threadId: string) => {\n\t\t\tawait archiveThread(backendUrl, await getAuth(), threadId);\n\t\t\treturn threadId;\n\t\t},\n\t\tonMutate: (threadId) => {\n\t\t\tsetArchivedThreadIds((current) => new Set(current).add(threadId));\n\t\t},\n\t\tonError: (_error, threadId) => {\n\t\t\tsetArchivedThreadIds((current) => {\n\t\t\t\tconst next = new Set(current);\n\t\t\t\tnext.delete(threadId);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\trefreshMutation.mutate();\n\t\t},\n\t});\n\tconst readState = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-history\",\n\t\t\t\"read-state\",\n\t\t\tbackendUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: async ({\n\t\t\tthreadId,\n\t\t\tisUnread,\n\t\t}: {\n\t\t\tthreadId: string;\n\t\t\tisUnread: boolean;\n\t\t}) =>\n\t\t\tsetThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n\t\tonMutate: ({ threadId, isUnread }) => {\n\t\t\tconst previous = readOverrides[threadId];\n\t\t\tsetReadOverrides((current) => ({ ...current, [threadId]: isUnread }));\n\t\t\treturn { previous, threadId };\n\t\t},\n\t\tonError: (_error, _variables, context) => {\n\t\t\tif (!context) return;\n\t\t\tsetReadOverrides((current) => {\n\t\t\t\tconst next = { ...current };\n\t\t\t\tif (context.previous === undefined) delete next[context.threadId];\n\t\t\t\telse next[context.threadId] = context.previous;\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: (result) => {\n\t\t\tsetReadOverrides((current) => ({\n\t\t\t\t...current,\n\t\t\t\t[result.thread_id]: result.is_unread,\n\t\t\t}));\n\t\t\trefreshMutation.mutate(undefined, {\n\t\t\t\tonSettled: () => {\n\t\t\t\t\tsetReadOverrides((current) => {\n\t\t\t\t\t\tconst next = { ...current };\n\t\t\t\t\t\tdelete next[result.thread_id];\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst refresh = useCallback(\n\t\t() => refreshMutation.mutateAsync(),\n\t\t[refreshMutation.mutateAsync],\n\t);\n\tconst fetchNextPage = useCallback(\n\t\t() => loadMoreMutation.mutateAsync(),\n\t\t[loadMoreMutation.mutateAsync],\n\t);\n\n\treturn {\n\t\tconversations,\n\t\ttotalCount: usesRestHistory ? legacyHistory.totalCount : index.totalCount,\n\t\tisLoading:\n\t\t\tenabled &&\n\t\t\t(usesRestHistory\n\t\t\t\t? !legacyHistory.hasResolvedFirstPage\n\t\t\t\t: index.entries === null),\n\t\tisFetching:\n\t\t\trefreshMutation.isPending ||\n\t\t\tloadMoreMutation.isPending ||\n\t\t\tlegacyHistory.isFetching,\n\t\tisRefreshing: refreshMutation.isPending,\n\t\thasResolvedFirstPage: usesRestHistory\n\t\t\t? legacyHistory.hasResolvedFirstPage\n\t\t\t: index.entries !== null,\n\t\thasNextPage: usesRestHistory\n\t\t\t? legacyHistory.hasNextPage\n\t\t\t: index.hasNextPage,\n\t\tisFetchingNextPage: loadMoreMutation.isPending,\n\t\tfetchNextPage,\n\t\trefresh,\n\t\tarchiveConversation: archive.mutate,\n\t\tarchivePending: archive.isPending,\n\t\tsetConversationReadState: readState.mutate,\n\t\treadStatePending: readState.isPending,\n\t\tconnection: index.connection,\n\t};\n}\n"],"names":["useConversationIndex","useRestConversationHistory","useState","useEffect","useMemo","useMutation","archiveThread","setThreadReadState","useCallback"],"mappings":"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"}
@@ -3,6 +3,8 @@ import { type RestConversationAuth } from "./use-rest-conversation-history";
3
3
  export interface UseStatewireConversationHistoryOptions {
4
4
  backendUrl: string;
5
5
  conversationIndexBaseUrl: string;
6
+ /** The workspace being viewed; the index is one instance per (workspace, user). */
7
+ workspaceId: string;
6
8
  principalId: string;
7
9
  getAuth: () => RestConversationAuth | Promise<RestConversationAuth>;
8
10
  headers: UseConversationIndexOptions["headers"];
@@ -31,7 +33,7 @@ export declare function shouldUseRestConversationHistory({ hasSearch, indexEntri
31
33
  * that same channel. A non-empty search deliberately uses the authorized REST
32
34
  * list endpoint so matches are not limited to the replicated newest window.
33
35
  */
34
- export declare function useStatewireConversationHistory({ backendUrl, conversationIndexBaseUrl, principalId, getAuth, headers, search, enabled, sse, }: UseStatewireConversationHistoryOptions): {
36
+ export declare function useStatewireConversationHistory({ backendUrl, conversationIndexBaseUrl, workspaceId, principalId, getAuth, headers, search, enabled, sse, }: UseStatewireConversationHistoryOptions): {
35
37
  conversations: {
36
38
  threadId: string;
37
39
  title: string;
@@ -43,6 +45,7 @@ export declare function useStatewireConversationHistory({ backendUrl, conversati
43
45
  assetType: string | null;
44
46
  assetId: string | null;
45
47
  appId: string | null;
48
+ computerAssetId?: string | null;
46
49
  triggerType: string | null;
47
50
  preview: string | null;
48
51
  messageCount: number | null;
@@ -6,13 +6,14 @@ import "../packages/agent-runtime/src/statewire-state.js";
6
6
  import "../packages/agent-runtime/src/messages.js";
7
7
  import "@assistant-ui/react-statewire";
8
8
  import "@assistant-ui/store";
9
- import "@assistant-ui/react-statewire/local-storage";
9
+ import "../packages/agent-runtime/src/quota-safe-local-storage-session.js";
10
10
  import "../packages/agent-runtime/src/statewire-suspended.js";
11
11
  import "@assistant-ui/tap";
12
12
  import "../packages/agent-runtime/src/statewire-attach-observer.js";
13
13
  import "statewire";
14
14
  import "../packages/agent-runtime/src/thread-status.js";
15
15
  import "@assistant-ui/core";
16
+ import "../packages/agent-runtime/src/thread-handoff.js";
16
17
  import { archiveThread, setThreadReadState } from "./api.js";
17
18
  import { useRestConversationHistory } from "./use-rest-conversation-history.js";
18
19
  function conversationSummaryFromIndexEntry(entry) {
@@ -67,6 +68,7 @@ function shouldUseRestConversationHistory({
67
68
  function useStatewireConversationHistory({
68
69
  backendUrl,
69
70
  conversationIndexBaseUrl,
71
+ workspaceId,
70
72
  principalId,
71
73
  getAuth,
72
74
  headers,
@@ -76,9 +78,10 @@ function useStatewireConversationHistory({
76
78
  }) {
77
79
  const index = useConversationIndex({
78
80
  baseUrl: conversationIndexBaseUrl,
81
+ workspaceId: workspaceId || "pending-workspace",
79
82
  userId: principalId || "pending-user",
80
83
  headers,
81
- enabled: enabled && principalId.length > 0,
84
+ enabled: enabled && workspaceId.length > 0 && principalId.length > 0,
82
85
  sse
83
86
  });
84
87
  const supportsStatewirePaging = index.totalCount !== null;
@@ -1 +1 @@
1
- {"version":3,"file":"use-statewire-conversation-history.js","sources":["../../src/threads/use-statewire-conversation-history.ts"],"sourcesContent":["import {\n\ttype ConversationIndexEntry,\n\ttype ConversationSummary,\n\ttype UseConversationIndexOptions,\n\tuseConversationIndex,\n} from \"@athenaintel/agent-runtime\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { archiveThread, setThreadReadState } from \"./api\";\nimport {\n\ttype RestConversationAuth,\n\tuseRestConversationHistory,\n} from \"./use-rest-conversation-history\";\n\nexport interface UseStatewireConversationHistoryOptions {\n\tbackendUrl: string;\n\tconversationIndexBaseUrl: string;\n\tprincipalId: string;\n\tgetAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n\theaders: UseConversationIndexOptions[\"headers\"];\n\tsearch?: string;\n\tenabled?: boolean;\n\tsse?: boolean;\n}\n\n/** Convert the replicated wire row into the shared cross-surface contract. */\nexport function conversationSummaryFromIndexEntry(\n\tentry: ConversationIndexEntry,\n): ConversationSummary {\n\treturn {\n\t\tthreadId: entry.thread_id,\n\t\ttitle: entry.title,\n\t\tupdatedAt: entry.updated_at,\n\t\tcreatedAt: null,\n\t\tstate: entry.state,\n\t\truntime: entry.runtime,\n\t\tsourceChannel: entry.start_channel,\n\t\tassetType: entry.asset_type,\n\t\tassetId: entry.asset_id ?? null,\n\t\tappId: entry.app_id ?? null,\n\t\ttriggerType: entry.trigger_type ?? null,\n\t\tpreview: entry.last_message_preview ?? null,\n\t\tmessageCount: entry.message_count ?? null,\n\t\tisUnread: entry.is_unread ?? false,\n\t\tsessionStatus: entry.session_status ?? null,\n\t\trunStatus: entry.run_status ?? null,\n\t};\n}\n\nexport function conversationHistorySource({\n\tindexEntries,\n\trestConversations,\n\tsupportsStatewirePaging,\n\thasSearch,\n}: {\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\trestConversations: readonly ConversationSummary[];\n\tsupportsStatewirePaging: boolean;\n\thasSearch: boolean;\n}): ConversationSummary[] {\n\t// Search is server-backed so it covers the user's entire authorized history,\n\t// including rows older than the Statewire live window. An empty query uses\n\t// Statewire as the render source; REST only supplements rolling old hosts.\n\tif (hasSearch) return [...restConversations];\n\tconst statewireItems = (indexEntries ?? []).map(\n\t\tconversationSummaryFromIndexEntry,\n\t);\n\tif (supportsStatewirePaging) return statewireItems;\n\tconst statewireIds = new Set(statewireItems.map((item) => item.threadId));\n\treturn [\n\t\t...statewireItems,\n\t\t...restConversations.filter(\n\t\t\t(conversation) => !statewireIds.has(conversation.threadId),\n\t\t),\n\t];\n}\n\nexport function shouldUseRestConversationHistory({\n\thasSearch,\n\tindexEntries,\n\tsupportsStatewirePaging,\n\tconnectionStatus,\n}: {\n\thasSearch: boolean;\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\tsupportsStatewirePaging: boolean;\n\tconnectionStatus: string;\n}): boolean {\n\tif (hasSearch) return true;\n\tif (supportsStatewirePaging) return false;\n\t// An old host is identifiable once its snapshot arrives. A transport that\n\t// fails or is parked before any snapshot also needs the independent REST\n\t// path; otherwise entries stays null and the history panel loads forever.\n\treturn (\n\t\tindexEntries !== null ||\n\t\tconnectionStatus === \"reconnecting\" ||\n\t\tconnectionStatus === \"gone\"\n\t);\n}\n\n/**\n * Inclusive satellite conversation history backed by the user's Pinned\n * Statewire instance. The replicated window is the render source; refreshes,\n * pagination, thread creation, lifecycle changes, and title changes arrive on\n * that same channel. A non-empty search deliberately uses the authorized REST\n * list endpoint so matches are not limited to the replicated newest window.\n */\nexport function useStatewireConversationHistory({\n\tbackendUrl,\n\tconversationIndexBaseUrl,\n\tprincipalId,\n\tgetAuth,\n\theaders,\n\tsearch,\n\tenabled = true,\n\tsse = false,\n}: UseStatewireConversationHistoryOptions) {\n\tconst index = useConversationIndex({\n\t\tbaseUrl: conversationIndexBaseUrl,\n\t\tuserId: principalId || \"pending-user\",\n\t\theaders,\n\t\tenabled: enabled && principalId.length > 0,\n\t\tsse,\n\t});\n\t// Rolling deploy compatibility: the pre-paging index snapshot has no\n\t// total_count. It still renders live rows immediately, while the old REST\n\t// pager remains available only until the upgraded host activates.\n\tconst supportsStatewirePaging = index.totalCount !== null;\n\tconst normalizedSearch = search?.trim().toLowerCase() ?? \"\";\n\tconst hasSearch = normalizedSearch.length > 0;\n\tconst usesRestHistory = shouldUseRestConversationHistory({\n\t\thasSearch,\n\t\tindexEntries: index.entries,\n\t\tsupportsStatewirePaging,\n\t\tconnectionStatus: index.connection.status,\n\t});\n\tconst legacyHistory = useRestConversationHistory({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\tsearch,\n\t\tenabled: enabled && principalId.length > 0 && usesRestHistory,\n\t});\n\tconst [readOverrides, setReadOverrides] = useState<Record<string, boolean>>(\n\t\t{},\n\t);\n\tconst [archivedThreadIds, setArchivedThreadIds] = useState<\n\t\tReadonlySet<string>\n\t>(() => new Set());\n\n\tuseEffect(() => {\n\t\tif (index.entries === null || archivedThreadIds.size === 0) return;\n\t\tconst visibleIds = new Set(index.entries.map((entry) => entry.thread_id));\n\t\tsetArchivedThreadIds((current) => {\n\t\t\tconst next = new Set(\n\t\t\t\t[...current].filter((threadId) => visibleIds.has(threadId)),\n\t\t\t);\n\t\t\treturn next.size === current.size ? current : next;\n\t\t});\n\t}, [archivedThreadIds.size, index.entries]);\n\n\tconst conversations = useMemo(() => {\n\t\treturn conversationHistorySource({\n\t\t\tindexEntries: index.entries,\n\t\t\trestConversations: legacyHistory.conversations,\n\t\t\tsupportsStatewirePaging,\n\t\t\thasSearch,\n\t\t})\n\t\t\t.filter((conversation) => !archivedThreadIds.has(conversation.threadId))\n\t\t\t.map((conversation) => ({\n\t\t\t\t...conversation,\n\t\t\t\tisUnread: readOverrides[conversation.threadId] ?? conversation.isUnread,\n\t\t\t}));\n\t}, [\n\t\tarchivedThreadIds,\n\t\tindex.entries,\n\t\tlegacyHistory.conversations,\n\t\thasSearch,\n\t\treadOverrides,\n\t\tsupportsStatewirePaging,\n\t]);\n\n\tconst refreshMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"refresh\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.refresh() : index.refresh(),\n\t});\n\tconst loadMoreMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"load-more\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.fetchNextPage() : index.loadMore(),\n\t});\n\tconst archive = useMutation({\n\t\tmutationKey: [\"conversation-history\", \"archive\", backendUrl, principalId],\n\t\tmutationFn: async (threadId: string) => {\n\t\t\tawait archiveThread(backendUrl, await getAuth(), threadId);\n\t\t\treturn threadId;\n\t\t},\n\t\tonMutate: (threadId) => {\n\t\t\tsetArchivedThreadIds((current) => new Set(current).add(threadId));\n\t\t},\n\t\tonError: (_error, threadId) => {\n\t\t\tsetArchivedThreadIds((current) => {\n\t\t\t\tconst next = new Set(current);\n\t\t\t\tnext.delete(threadId);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\trefreshMutation.mutate();\n\t\t},\n\t});\n\tconst readState = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-history\",\n\t\t\t\"read-state\",\n\t\t\tbackendUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: async ({\n\t\t\tthreadId,\n\t\t\tisUnread,\n\t\t}: {\n\t\t\tthreadId: string;\n\t\t\tisUnread: boolean;\n\t\t}) =>\n\t\t\tsetThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n\t\tonMutate: ({ threadId, isUnread }) => {\n\t\t\tconst previous = readOverrides[threadId];\n\t\t\tsetReadOverrides((current) => ({ ...current, [threadId]: isUnread }));\n\t\t\treturn { previous, threadId };\n\t\t},\n\t\tonError: (_error, _variables, context) => {\n\t\t\tif (!context) return;\n\t\t\tsetReadOverrides((current) => {\n\t\t\t\tconst next = { ...current };\n\t\t\t\tif (context.previous === undefined) delete next[context.threadId];\n\t\t\t\telse next[context.threadId] = context.previous;\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: (result) => {\n\t\t\tsetReadOverrides((current) => ({\n\t\t\t\t...current,\n\t\t\t\t[result.thread_id]: result.is_unread,\n\t\t\t}));\n\t\t\trefreshMutation.mutate(undefined, {\n\t\t\t\tonSettled: () => {\n\t\t\t\t\tsetReadOverrides((current) => {\n\t\t\t\t\t\tconst next = { ...current };\n\t\t\t\t\t\tdelete next[result.thread_id];\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst refresh = useCallback(\n\t\t() => refreshMutation.mutateAsync(),\n\t\t[refreshMutation.mutateAsync],\n\t);\n\tconst fetchNextPage = useCallback(\n\t\t() => loadMoreMutation.mutateAsync(),\n\t\t[loadMoreMutation.mutateAsync],\n\t);\n\n\treturn {\n\t\tconversations,\n\t\ttotalCount: usesRestHistory ? legacyHistory.totalCount : index.totalCount,\n\t\tisLoading:\n\t\t\tenabled &&\n\t\t\t(usesRestHistory\n\t\t\t\t? !legacyHistory.hasResolvedFirstPage\n\t\t\t\t: index.entries === null),\n\t\tisFetching:\n\t\t\trefreshMutation.isPending ||\n\t\t\tloadMoreMutation.isPending ||\n\t\t\tlegacyHistory.isFetching,\n\t\tisRefreshing: refreshMutation.isPending,\n\t\thasResolvedFirstPage: usesRestHistory\n\t\t\t? legacyHistory.hasResolvedFirstPage\n\t\t\t: index.entries !== null,\n\t\thasNextPage: usesRestHistory\n\t\t\t? legacyHistory.hasNextPage\n\t\t\t: index.hasNextPage,\n\t\tisFetchingNextPage: loadMoreMutation.isPending,\n\t\tfetchNextPage,\n\t\trefresh,\n\t\tarchiveConversation: archive.mutate,\n\t\tarchivePending: archive.isPending,\n\t\tsetConversationReadState: readState.mutate,\n\t\treadStatePending: readState.isPending,\n\t\tconnection: index.connection,\n\t};\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-statewire-conversation-history.js","sources":["../../src/threads/use-statewire-conversation-history.ts"],"sourcesContent":["import {\n\ttype ConversationIndexEntry,\n\ttype ConversationSummary,\n\ttype UseConversationIndexOptions,\n\tuseConversationIndex,\n} from \"@athenaintel/agent-runtime\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { archiveThread, setThreadReadState } from \"./api\";\nimport {\n\ttype RestConversationAuth,\n\tuseRestConversationHistory,\n} from \"./use-rest-conversation-history\";\n\nexport interface UseStatewireConversationHistoryOptions {\n\tbackendUrl: string;\n\tconversationIndexBaseUrl: string;\n\t/** The workspace being viewed; the index is one instance per (workspace, user). */\n\tworkspaceId: string;\n\tprincipalId: string;\n\tgetAuth: () => RestConversationAuth | Promise<RestConversationAuth>;\n\theaders: UseConversationIndexOptions[\"headers\"];\n\tsearch?: string;\n\tenabled?: boolean;\n\tsse?: boolean;\n}\n\n/** Convert the replicated wire row into the shared cross-surface contract. */\nexport function conversationSummaryFromIndexEntry(\n\tentry: ConversationIndexEntry,\n): ConversationSummary {\n\treturn {\n\t\tthreadId: entry.thread_id,\n\t\ttitle: entry.title,\n\t\tupdatedAt: entry.updated_at,\n\t\tcreatedAt: null,\n\t\tstate: entry.state,\n\t\truntime: entry.runtime,\n\t\tsourceChannel: entry.start_channel,\n\t\tassetType: entry.asset_type,\n\t\tassetId: entry.asset_id ?? null,\n\t\tappId: entry.app_id ?? null,\n\t\ttriggerType: entry.trigger_type ?? null,\n\t\tpreview: entry.last_message_preview ?? null,\n\t\tmessageCount: entry.message_count ?? null,\n\t\tisUnread: entry.is_unread ?? false,\n\t\tsessionStatus: entry.session_status ?? null,\n\t\trunStatus: entry.run_status ?? null,\n\t};\n}\n\nexport function conversationHistorySource({\n\tindexEntries,\n\trestConversations,\n\tsupportsStatewirePaging,\n\thasSearch,\n}: {\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\trestConversations: readonly ConversationSummary[];\n\tsupportsStatewirePaging: boolean;\n\thasSearch: boolean;\n}): ConversationSummary[] {\n\t// Search is server-backed so it covers the user's entire authorized history,\n\t// including rows older than the Statewire live window. An empty query uses\n\t// Statewire as the render source; REST only supplements rolling old hosts.\n\tif (hasSearch) return [...restConversations];\n\tconst statewireItems = (indexEntries ?? []).map(\n\t\tconversationSummaryFromIndexEntry,\n\t);\n\tif (supportsStatewirePaging) return statewireItems;\n\tconst statewireIds = new Set(statewireItems.map((item) => item.threadId));\n\treturn [\n\t\t...statewireItems,\n\t\t...restConversations.filter(\n\t\t\t(conversation) => !statewireIds.has(conversation.threadId),\n\t\t),\n\t];\n}\n\nexport function shouldUseRestConversationHistory({\n\thasSearch,\n\tindexEntries,\n\tsupportsStatewirePaging,\n\tconnectionStatus,\n}: {\n\thasSearch: boolean;\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\tsupportsStatewirePaging: boolean;\n\tconnectionStatus: string;\n}): boolean {\n\tif (hasSearch) return true;\n\tif (supportsStatewirePaging) return false;\n\t// An old host is identifiable once its snapshot arrives. A transport that\n\t// fails or is parked before any snapshot also needs the independent REST\n\t// path; otherwise entries stays null and the history panel loads forever.\n\treturn (\n\t\tindexEntries !== null ||\n\t\tconnectionStatus === \"reconnecting\" ||\n\t\tconnectionStatus === \"gone\"\n\t);\n}\n\n/**\n * Inclusive satellite conversation history backed by the user's Pinned\n * Statewire instance. The replicated window is the render source; refreshes,\n * pagination, thread creation, lifecycle changes, and title changes arrive on\n * that same channel. A non-empty search deliberately uses the authorized REST\n * list endpoint so matches are not limited to the replicated newest window.\n */\nexport function useStatewireConversationHistory({\n\tbackendUrl,\n\tconversationIndexBaseUrl,\n\tworkspaceId,\n\tprincipalId,\n\tgetAuth,\n\theaders,\n\tsearch,\n\tenabled = true,\n\tsse = false,\n}: UseStatewireConversationHistoryOptions) {\n\tconst index = useConversationIndex({\n\t\tbaseUrl: conversationIndexBaseUrl,\n\t\tworkspaceId: workspaceId || \"pending-workspace\",\n\t\tuserId: principalId || \"pending-user\",\n\t\theaders,\n\t\tenabled: enabled && workspaceId.length > 0 && principalId.length > 0,\n\t\tsse,\n\t});\n\t// Rolling deploy compatibility: the pre-paging index snapshot has no\n\t// total_count. It still renders live rows immediately, while the old REST\n\t// pager remains available only until the upgraded host activates.\n\tconst supportsStatewirePaging = index.totalCount !== null;\n\tconst normalizedSearch = search?.trim().toLowerCase() ?? \"\";\n\tconst hasSearch = normalizedSearch.length > 0;\n\tconst usesRestHistory = shouldUseRestConversationHistory({\n\t\thasSearch,\n\t\tindexEntries: index.entries,\n\t\tsupportsStatewirePaging,\n\t\tconnectionStatus: index.connection.status,\n\t});\n\tconst legacyHistory = useRestConversationHistory({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\tsearch,\n\t\tenabled: enabled && principalId.length > 0 && usesRestHistory,\n\t});\n\tconst [readOverrides, setReadOverrides] = useState<Record<string, boolean>>(\n\t\t{},\n\t);\n\tconst [archivedThreadIds, setArchivedThreadIds] = useState<\n\t\tReadonlySet<string>\n\t>(() => new Set());\n\n\tuseEffect(() => {\n\t\tif (index.entries === null || archivedThreadIds.size === 0) return;\n\t\tconst visibleIds = new Set(index.entries.map((entry) => entry.thread_id));\n\t\tsetArchivedThreadIds((current) => {\n\t\t\tconst next = new Set(\n\t\t\t\t[...current].filter((threadId) => visibleIds.has(threadId)),\n\t\t\t);\n\t\t\treturn next.size === current.size ? current : next;\n\t\t});\n\t}, [archivedThreadIds.size, index.entries]);\n\n\tconst conversations = useMemo(() => {\n\t\treturn conversationHistorySource({\n\t\t\tindexEntries: index.entries,\n\t\t\trestConversations: legacyHistory.conversations,\n\t\t\tsupportsStatewirePaging,\n\t\t\thasSearch,\n\t\t})\n\t\t\t.filter((conversation) => !archivedThreadIds.has(conversation.threadId))\n\t\t\t.map((conversation) => ({\n\t\t\t\t...conversation,\n\t\t\t\tisUnread: readOverrides[conversation.threadId] ?? conversation.isUnread,\n\t\t\t}));\n\t}, [\n\t\tarchivedThreadIds,\n\t\tindex.entries,\n\t\tlegacyHistory.conversations,\n\t\thasSearch,\n\t\treadOverrides,\n\t\tsupportsStatewirePaging,\n\t]);\n\n\tconst refreshMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"refresh\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.refresh() : index.refresh(),\n\t});\n\tconst loadMoreMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"load-more\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.fetchNextPage() : index.loadMore(),\n\t});\n\tconst archive = useMutation({\n\t\tmutationKey: [\"conversation-history\", \"archive\", backendUrl, principalId],\n\t\tmutationFn: async (threadId: string) => {\n\t\t\tawait archiveThread(backendUrl, await getAuth(), threadId);\n\t\t\treturn threadId;\n\t\t},\n\t\tonMutate: (threadId) => {\n\t\t\tsetArchivedThreadIds((current) => new Set(current).add(threadId));\n\t\t},\n\t\tonError: (_error, threadId) => {\n\t\t\tsetArchivedThreadIds((current) => {\n\t\t\t\tconst next = new Set(current);\n\t\t\t\tnext.delete(threadId);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\trefreshMutation.mutate();\n\t\t},\n\t});\n\tconst readState = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-history\",\n\t\t\t\"read-state\",\n\t\t\tbackendUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: async ({\n\t\t\tthreadId,\n\t\t\tisUnread,\n\t\t}: {\n\t\t\tthreadId: string;\n\t\t\tisUnread: boolean;\n\t\t}) =>\n\t\t\tsetThreadReadState(backendUrl, await getAuth(), { threadId, isUnread }),\n\t\tonMutate: ({ threadId, isUnread }) => {\n\t\t\tconst previous = readOverrides[threadId];\n\t\t\tsetReadOverrides((current) => ({ ...current, [threadId]: isUnread }));\n\t\t\treturn { previous, threadId };\n\t\t},\n\t\tonError: (_error, _variables, context) => {\n\t\t\tif (!context) return;\n\t\t\tsetReadOverrides((current) => {\n\t\t\t\tconst next = { ...current };\n\t\t\t\tif (context.previous === undefined) delete next[context.threadId];\n\t\t\t\telse next[context.threadId] = context.previous;\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: (result) => {\n\t\t\tsetReadOverrides((current) => ({\n\t\t\t\t...current,\n\t\t\t\t[result.thread_id]: result.is_unread,\n\t\t\t}));\n\t\t\trefreshMutation.mutate(undefined, {\n\t\t\t\tonSettled: () => {\n\t\t\t\t\tsetReadOverrides((current) => {\n\t\t\t\t\t\tconst next = { ...current };\n\t\t\t\t\t\tdelete next[result.thread_id];\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst refresh = useCallback(\n\t\t() => refreshMutation.mutateAsync(),\n\t\t[refreshMutation.mutateAsync],\n\t);\n\tconst fetchNextPage = useCallback(\n\t\t() => loadMoreMutation.mutateAsync(),\n\t\t[loadMoreMutation.mutateAsync],\n\t);\n\n\treturn {\n\t\tconversations,\n\t\ttotalCount: usesRestHistory ? legacyHistory.totalCount : index.totalCount,\n\t\tisLoading:\n\t\t\tenabled &&\n\t\t\t(usesRestHistory\n\t\t\t\t? !legacyHistory.hasResolvedFirstPage\n\t\t\t\t: index.entries === null),\n\t\tisFetching:\n\t\t\trefreshMutation.isPending ||\n\t\t\tloadMoreMutation.isPending ||\n\t\t\tlegacyHistory.isFetching,\n\t\tisRefreshing: refreshMutation.isPending,\n\t\thasResolvedFirstPage: usesRestHistory\n\t\t\t? legacyHistory.hasResolvedFirstPage\n\t\t\t: index.entries !== null,\n\t\thasNextPage: usesRestHistory\n\t\t\t? legacyHistory.hasNextPage\n\t\t\t: index.hasNextPage,\n\t\tisFetchingNextPage: loadMoreMutation.isPending,\n\t\tfetchNextPage,\n\t\trefresh,\n\t\tarchiveConversation: archive.mutate,\n\t\tarchivePending: archive.isPending,\n\t\tsetConversationReadState: readState.mutate,\n\t\treadStatePending: readState.isPending,\n\t\tconnection: index.connection,\n\t};\n}\n"],"names":[],"mappings":"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"}
@@ -31,8 +31,6 @@ const Toolkits = {
31
31
  NOTEBOOK: "notebook_toolkit",
32
32
  /** Presentation slide editing. */
33
33
  PRESENTATION: "presentation_toolkit",
34
- /** Presentation slide editing (OnlyOffice, deprecated). */
35
- PRESENTATION_ONLYOFFICE: "presentation_onlyoffice_toolkit",
36
34
  /** PowerPoint presentation creation from templates. */
37
35
  POWERPOINT: "powerpoint_deck_toolkit",
38
36
  /** PowerPoint presentation creation from templates (pptx-studio). */
@@ -146,11 +144,6 @@ const TOOLKIT_DISPLAY_INFO = {
146
144
  description: "Edit presentation slides.",
147
145
  icon: "Presentation"
148
146
  },
149
- [Toolkits.PRESENTATION_ONLYOFFICE]: {
150
- name: "Presentation v0 (deprecated)",
151
- description: "Edit presentation slides (OnlyOffice, deprecated).",
152
- icon: "Presentation"
153
- },
154
147
  [Toolkits.POWERPOINT]: {
155
148
  name: "PowerPoint",
156
149
  description: "Create PowerPoint decks from templates.",
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/toolkits/index.ts"],"sourcesContent":["/**\n * Backend toolkit IDs.\n *\n * Pass these to the `tools` prop on `<AthenaProvider>` to enable backend toolkits.\n *\n * @example\n * import { Toolkits } from '@athenaintel/react';\n *\n * <AthenaProvider tools={[Toolkits.DOCUMENT, Toolkits.SPREADSHEET, Toolkits.WEB_SEARCH]}>\n */\nexport const Toolkits = {\n /** Web search and page browsing. */\n WEB_SEARCH: 'web_search_browse_toolkit',\n /** SQL query execution. */\n SQL: 'sql_toolkit',\n /** Azure Blob Storage catalog file operations. */\n AZURE_BLOB_STORAGE: 'azure_blob_storage_toolkit',\n /** Document comments and collaboration. */\n COMMENTS: 'comments_toolkit',\n /** Visual canvas creation. */\n CANVAS: 'canvas_toolkit',\n /** PostgreSQL database management. */\n DATABASE: 'database_toolkit',\n /** Asset collections management. */\n COLLECTIONS: 'collections_toolkit',\n /** Charts, dashboards, and figures. */\n VISUALIZATIONS: 'visualizations_toolkit',\n /** Custom UI creation. */\n USER_INTERFACE: 'user_interface_toolkit',\n /** Agent Operating Procedures. */\n AOP: 'aop_toolkit',\n /** Ephemeral compute environments. */\n COMPUTER_ASSET: 'computer_asset_toolkit',\n /** Web browser automation. */\n BROWSER: 'browser_toolkit',\n /** Virtual machine management. */\n VM: 'vm_toolkit',\n /** Jupyter notebook execution. */\n NOTEBOOK: 'notebook_toolkit',\n /** Presentation slide editing. */\n PRESENTATION: 'presentation_toolkit',\n /** Presentation slide editing (OnlyOffice, deprecated). */\n PRESENTATION_ONLYOFFICE: 'presentation_onlyoffice_toolkit',\n /** PowerPoint presentation creation from templates. */\n POWERPOINT: 'powerpoint_deck_toolkit',\n /** PowerPoint presentation creation from templates (pptx-studio). */\n PRESENTATION_PPTX_STUDIO: 'presentation_pptx_studio_toolkit',\n /** Workspace file management (Olympus Drive). */\n DRIVE: 'olympus_drive_toolkit',\n /** Python code execution. */\n PYTHON: 'python_toolkit',\n /** Multi-account email and calendar (Gmail + Outlook). */\n EMAIL: 'unified_email_toolkit',\n /** Legacy email and calendar operations. */\n EMAIL_CALENDAR: 'email_calendar_toolkit',\n /** Spreadsheet operations. */\n SPREADSHEET: 'spreadsheet_toolkit',\n /** Athena document editing. */\n DOCUMENT: 'document_toolkit',\n /** Word document backend operations. */\n WORD_DOCUMENT: 'word_document_be_toolkit',\n /** Go-To-Market management. */\n GTM: 'gtm_toolkit',\n /** Marketing campaign management. */\n MARKETING: 'marketing_toolkit',\n /** FDE implementations and workflows. */\n FDE: 'fde_toolkit',\n /** SharePoint / Google Drive / workspace file access. */\n EXTERNAL_DRIVE: 'external_drive_toolkit',\n /** Reusable playbooks and prompts. */\n PLAYBOOK: 'playbook_toolkit',\n /** Local Chrome browser control via tunnel. */\n DEVICE_TUNNEL: 'device_tunnel_toolkit',\n /** Project management. */\n PROJECTS: 'projects_toolkit',\n /** Task Studio script execution. */\n TASK_STUDIO: 'task_studio_toolkit',\n /** User memory and preferences. */\n PREFERENCES: 'preferences_toolkit',\n} as const;\n\n/** A toolkit ID string. */\nexport type ToolkitId = (typeof Toolkits)[keyof typeof Toolkits];\n\nexport interface ToolkitDisplayInfo {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nconst TOOLKIT_DISPLAY_INFO: Record<string, Omit<ToolkitDisplayInfo, 'id'>> = {\n [Toolkits.WEB_SEARCH]: {\n name: 'Web Search',\n description: 'Search the web and inspect pages.',\n icon: 'Globe',\n },\n [Toolkits.SQL]: {\n name: 'SQL',\n description: 'Run structured SQL queries.',\n icon: 'Database',\n },\n [Toolkits.AZURE_BLOB_STORAGE]: {\n name: 'Azure Blob Storage',\n description: 'List, read, and upload Azure Blob Storage catalog files.',\n icon: 'Cloud',\n },\n [Toolkits.COMMENTS]: {\n name: 'Comments',\n description: 'Work with document comments and reviews.',\n icon: 'MessageSquare',\n },\n [Toolkits.CANVAS]: {\n name: 'Canvas',\n description: 'Create and edit visual canvases.',\n icon: 'LayoutGrid',\n },\n [Toolkits.DATABASE]: {\n name: 'Database',\n description: 'Inspect and manage database assets.',\n icon: 'Database',\n },\n [Toolkits.COLLECTIONS]: {\n name: 'Collections',\n description: 'Manage asset collections.',\n icon: 'Boxes',\n },\n [Toolkits.VISUALIZATIONS]: {\n name: 'Visualizations',\n description: 'Create charts, dashboards, and figures.',\n icon: 'ChartBar',\n },\n [Toolkits.USER_INTERFACE]: {\n name: 'User Interface',\n description: 'Build custom user interfaces.',\n icon: 'PanelTop',\n },\n [Toolkits.AOP]: {\n name: 'AOP',\n description: 'Run Agent Operating Procedures.',\n icon: 'Workflow',\n },\n [Toolkits.COMPUTER_ASSET]: {\n name: 'Computer Asset',\n description: 'Provision and operate computer assets.',\n icon: 'Monitor',\n },\n [Toolkits.BROWSER]: {\n name: 'Browser',\n description: 'Control a web browser.',\n icon: 'Globe',\n },\n [Toolkits.VM]: {\n name: 'Virtual Machine',\n description: 'Manage virtual machine environments.',\n icon: 'Server',\n },\n [Toolkits.NOTEBOOK]: {\n name: 'Notebook',\n description: 'Run Jupyter notebook workflows.',\n icon: 'BookOpen',\n },\n [Toolkits.PRESENTATION]: {\n name: 'Presentation',\n description: 'Edit presentation slides.',\n icon: 'Presentation',\n },\n [Toolkits.PRESENTATION_ONLYOFFICE]: {\n name: 'Presentation v0 (deprecated)',\n description: 'Edit presentation slides (OnlyOffice, deprecated).',\n icon: 'Presentation',\n },\n [Toolkits.POWERPOINT]: {\n name: 'PowerPoint',\n description: 'Create PowerPoint decks from templates.',\n icon: 'Presentation',\n },\n [Toolkits.PRESENTATION_PPTX_STUDIO]: {\n name: 'Presentation',\n description: 'Create PowerPoint presentations from templates (pptx-studio).',\n icon: 'Presentation',\n },\n [Toolkits.DRIVE]: {\n name: 'Olympus Drive',\n description: 'Find and manage workspace files.',\n icon: 'Folder',\n },\n [Toolkits.PYTHON]: {\n name: 'Python',\n description: 'Run Python analysis and automation.',\n icon: 'Code2',\n },\n [Toolkits.EMAIL]: {\n name: 'Email',\n description: 'Work across connected email and calendar accounts.',\n icon: 'Mail',\n },\n [Toolkits.EMAIL_CALENDAR]: {\n name: 'Email & Calendar',\n description: 'Use email and calendar operations.',\n icon: 'Calendar',\n },\n [Toolkits.SPREADSHEET]: {\n name: 'Spreadsheet',\n description: 'Create and edit spreadsheets.',\n icon: 'Table2',\n },\n [Toolkits.DOCUMENT]: {\n name: 'Document',\n description: 'Create and edit Athena documents.',\n icon: 'FileText',\n },\n [Toolkits.WORD_DOCUMENT]: {\n name: 'Word Document',\n description: 'Create and edit Word documents.',\n icon: 'FileText',\n },\n [Toolkits.GTM]: {\n name: 'Go-To-Market',\n description: 'Manage go-to-market workflows.',\n icon: 'BriefcaseBusiness',\n },\n [Toolkits.MARKETING]: {\n name: 'Marketing',\n description: 'Manage marketing campaigns.',\n icon: 'Megaphone',\n },\n [Toolkits.FDE]: {\n name: 'FDE',\n description: 'Build FDE implementations and workflows.',\n icon: 'Workflow',\n },\n [Toolkits.EXTERNAL_DRIVE]: {\n name: 'External Drive',\n description: 'Access SharePoint, Google Drive, and other files.',\n icon: 'HardDrive',\n },\n [Toolkits.PLAYBOOK]: {\n name: 'Playbook',\n description: 'Use reusable playbooks and prompts.',\n icon: 'BookOpen',\n },\n [Toolkits.DEVICE_TUNNEL]: {\n name: 'Device Tunnel',\n description: 'Control a local browser through a tunnel.',\n icon: 'Cable',\n },\n [Toolkits.PROJECTS]: {\n name: 'Projects',\n description: 'Manage project work.',\n icon: 'FolderKanban',\n },\n [Toolkits.TASK_STUDIO]: {\n name: 'Task Studio',\n description: 'Run Task Studio scripts.',\n icon: 'Terminal',\n },\n [Toolkits.PREFERENCES]: {\n name: 'Preferences',\n description: 'Use memory and preference tools.',\n icon: 'Settings',\n },\n semantic_model_toolkit: {\n name: 'Semantic Model',\n description: 'Query semantic models and generate analytics.',\n icon: 'ChartBar',\n },\n semantic_model_dev_toolkit: {\n name: 'Semantic Model Development',\n description: 'Create, validate, and deploy semantic model YAML.',\n icon: 'Database',\n },\n};\n\nconst humanizeToolkitId = (id: string): string => {\n const trimmed = id.trim();\n if (!trimmed) {\n return 'Toolkit';\n }\n\n const withoutSuffix = trimmed.replace(/_toolkit$/, '');\n return withoutSuffix\n .split(/[_-]+/)\n .filter(Boolean)\n .map((word) => {\n if (word.length <= 3) {\n return word.toUpperCase();\n }\n return `${word.charAt(0).toUpperCase()}${word.slice(1)}`;\n })\n .join(' ');\n};\n\nexport const getToolkitDisplayInfo = (id: string): ToolkitDisplayInfo => {\n const info = TOOLKIT_DISPLAY_INFO[id];\n\n return {\n id,\n name: info?.name ?? humanizeToolkitId(id),\n description: info?.description,\n icon: info?.icon ?? 'Package',\n };\n};\n"],"names":[],"mappings":";;AAUO,MAAM,WAAW;AAAA;AAAA,EAEtB,YAAY;AAAA;AAAA,EAEZ,KAAK;AAAA;AAAA,EAEL,oBAAoB;AAAA;AAAA,EAEpB,UAAU;AAAA;AAAA,EAEV,QAAQ;AAAA;AAAA,EAER,UAAU;AAAA;AAAA,EAEV,aAAa;AAAA;AAAA,EAEb,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,KAAK;AAAA;AAAA,EAEL,gBAAgB;AAAA;AAAA,EAEhB,SAAS;AAAA;AAAA,EAET,IAAI;AAAA;AAAA,EAEJ,UAAU;AAAA;AAAA,EAEV,cAAc;AAAA;AAAA,EAEd,yBAAyB;AAAA;AAAA,EAEzB,YAAY;AAAA;AAAA,EAEZ,0BAA0B;AAAA;AAAA,EAE1B,OAAO;AAAA;AAAA,EAEP,QAAQ;AAAA;AAAA,EAER,OAAO;AAAA;AAAA,EAEP,gBAAgB;AAAA;AAAA,EAEhB,aAAa;AAAA;AAAA,EAEb,UAAU;AAAA;AAAA,EAEV,eAAe;AAAA;AAAA,EAEf,KAAK;AAAA;AAAA,EAEL,WAAW;AAAA;AAAA,EAEX,KAAK;AAAA;AAAA,EAEL,gBAAgB;AAAA;AAAA,EAEhB,UAAU;AAAA;AAAA,EAEV,eAAe;AAAA;AAAA,EAEf,UAAU;AAAA;AAAA,EAEV,aAAa;AAAA;AAAA,EAEb,aAAa;AACf;AAYA,MAAM,uBAAuE;AAAA,EAC3E,CAAC,SAAS,UAAU,GAAG;AAAA,IACrB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,GAAG,GAAG;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,kBAAkB,GAAG;AAAA,IAC7B,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,MAAM,GAAG;AAAA,IACjB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,WAAW,GAAG;AAAA,IACtB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,cAAc,GAAG;AAAA,IACzB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,cAAc,GAAG;AAAA,IACzB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,GAAG,GAAG;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,cAAc,GAAG;AAAA,IACzB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,OAAO,GAAG;AAAA,IAClB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,EAAE,GAAG;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,YAAY,GAAG;AAAA,IACvB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,uBAAuB,GAAG;AAAA,IAClC,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,UAAU,GAAG;AAAA,IACrB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,wBAAwB,GAAG;AAAA,IACnC,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,KAAK,GAAG;AAAA,IAChB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,MAAM,GAAG;AAAA,IACjB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,KAAK,GAAG;AAAA,IAChB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,cAAc,GAAG;AAAA,IACzB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,WAAW,GAAG;AAAA,IACtB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,aAAa,GAAG;AAAA,IACxB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,GAAG,GAAG;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,SAAS,GAAG;AAAA,IACpB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,GAAG,GAAG;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,cAAc,GAAG;AAAA,IACzB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,aAAa,GAAG;AAAA,IACxB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,WAAW,GAAG;AAAA,IACtB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,CAAC,SAAS,WAAW,GAAG;AAAA,IACtB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,wBAAwB;AAAA,IACtB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER,4BAA4B;AAAA,IAC1B,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAEV;AAEA,MAAM,oBAAoB,CAAC,OAAuB;AAChD,QAAM,UAAU,GAAG,KAAA;AACnB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,QAAQ,QAAQ,aAAa,EAAE;AACrD,SAAO,cACJ,MAAM,OAAO,EACb,OAAO,OAAO,EACd,IAAI,CAAC,SAAS;AACb,QAAI,KAAK,UAAU,GAAG;AACpB,aAAO,KAAK,YAAA;AAAA,IACd;AACA,WAAO,GAAG,KAAK,OAAO,CAAC,EAAE,YAAA,CAAa,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,EACxD,CAAC,EACA,KAAK,GAAG;AACb;AAEO,MAAM,wBAAwB,CAAC,OAAmC;AACvE,QAAM,OAAO,qBAAqB,EAAE;AAEpC,SAAO;AAAA,IACL;AAAA,IACA,OAAM,6BAAM,SAAQ,kBAAkB,EAAE;AAAA,IACxC,aAAa,6BAAM;AAAA,IACnB,OAAM,6BAAM,SAAQ;AAAA,EAAA;AAExB;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/toolkits/index.ts"],"sourcesContent":["/**\n * Backend toolkit IDs.\n *\n * Pass these to the `tools` prop on `<AthenaProvider>` to enable backend toolkits.\n *\n * @example\n * import { Toolkits } from '@athenaintel/react';\n *\n * <AthenaProvider tools={[Toolkits.DOCUMENT, Toolkits.SPREADSHEET, Toolkits.WEB_SEARCH]}>\n */\nexport const Toolkits = {\n /** Web search and page browsing. */\n WEB_SEARCH: 'web_search_browse_toolkit',\n /** SQL query execution. */\n SQL: 'sql_toolkit',\n /** Azure Blob Storage catalog file operations. */\n AZURE_BLOB_STORAGE: 'azure_blob_storage_toolkit',\n /** Document comments and collaboration. */\n COMMENTS: 'comments_toolkit',\n /** Visual canvas creation. */\n CANVAS: 'canvas_toolkit',\n /** PostgreSQL database management. */\n DATABASE: 'database_toolkit',\n /** Asset collections management. */\n COLLECTIONS: 'collections_toolkit',\n /** Charts, dashboards, and figures. */\n VISUALIZATIONS: 'visualizations_toolkit',\n /** Custom UI creation. */\n USER_INTERFACE: 'user_interface_toolkit',\n /** Agent Operating Procedures. */\n AOP: 'aop_toolkit',\n /** Ephemeral compute environments. */\n COMPUTER_ASSET: 'computer_asset_toolkit',\n /** Web browser automation. */\n BROWSER: 'browser_toolkit',\n /** Virtual machine management. */\n VM: 'vm_toolkit',\n /** Jupyter notebook execution. */\n NOTEBOOK: 'notebook_toolkit',\n /** Presentation slide editing. */\n PRESENTATION: 'presentation_toolkit',\n /** PowerPoint presentation creation from templates. */\n POWERPOINT: 'powerpoint_deck_toolkit',\n /** PowerPoint presentation creation from templates (pptx-studio). */\n PRESENTATION_PPTX_STUDIO: 'presentation_pptx_studio_toolkit',\n /** Workspace file management (Olympus Drive). */\n DRIVE: 'olympus_drive_toolkit',\n /** Python code execution. */\n PYTHON: 'python_toolkit',\n /** Multi-account email and calendar (Gmail + Outlook). */\n EMAIL: 'unified_email_toolkit',\n /** Legacy email and calendar operations. */\n EMAIL_CALENDAR: 'email_calendar_toolkit',\n /** Spreadsheet operations. */\n SPREADSHEET: 'spreadsheet_toolkit',\n /** Athena document editing. */\n DOCUMENT: 'document_toolkit',\n /** Word document backend operations. */\n WORD_DOCUMENT: 'word_document_be_toolkit',\n /** Go-To-Market management. */\n GTM: 'gtm_toolkit',\n /** Marketing campaign management. */\n MARKETING: 'marketing_toolkit',\n /** FDE implementations and workflows. */\n FDE: 'fde_toolkit',\n /** SharePoint / Google Drive / workspace file access. */\n EXTERNAL_DRIVE: 'external_drive_toolkit',\n /** Reusable playbooks and prompts. */\n PLAYBOOK: 'playbook_toolkit',\n /** Local Chrome browser control via tunnel. */\n DEVICE_TUNNEL: 'device_tunnel_toolkit',\n /** Project management. */\n PROJECTS: 'projects_toolkit',\n /** Task Studio script execution. */\n TASK_STUDIO: 'task_studio_toolkit',\n /** User memory and preferences. */\n PREFERENCES: 'preferences_toolkit',\n} as const;\n\n/** A toolkit ID string. */\nexport type ToolkitId = (typeof Toolkits)[keyof typeof Toolkits];\n\nexport interface ToolkitDisplayInfo {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nconst TOOLKIT_DISPLAY_INFO: Record<string, Omit<ToolkitDisplayInfo, 'id'>> = {\n [Toolkits.WEB_SEARCH]: {\n name: 'Web Search',\n description: 'Search the web and inspect pages.',\n icon: 'Globe',\n },\n [Toolkits.SQL]: {\n name: 'SQL',\n description: 'Run structured SQL queries.',\n icon: 'Database',\n },\n [Toolkits.AZURE_BLOB_STORAGE]: {\n name: 'Azure Blob Storage',\n description: 'List, read, and upload Azure Blob Storage catalog files.',\n icon: 'Cloud',\n },\n [Toolkits.COMMENTS]: {\n name: 'Comments',\n description: 'Work with document comments and reviews.',\n icon: 'MessageSquare',\n },\n [Toolkits.CANVAS]: {\n name: 'Canvas',\n description: 'Create and edit visual canvases.',\n icon: 'LayoutGrid',\n },\n [Toolkits.DATABASE]: {\n name: 'Database',\n description: 'Inspect and manage database assets.',\n icon: 'Database',\n },\n [Toolkits.COLLECTIONS]: {\n name: 'Collections',\n description: 'Manage asset collections.',\n icon: 'Boxes',\n },\n [Toolkits.VISUALIZATIONS]: {\n name: 'Visualizations',\n description: 'Create charts, dashboards, and figures.',\n icon: 'ChartBar',\n },\n [Toolkits.USER_INTERFACE]: {\n name: 'User Interface',\n description: 'Build custom user interfaces.',\n icon: 'PanelTop',\n },\n [Toolkits.AOP]: {\n name: 'AOP',\n description: 'Run Agent Operating Procedures.',\n icon: 'Workflow',\n },\n [Toolkits.COMPUTER_ASSET]: {\n name: 'Computer Asset',\n description: 'Provision and operate computer assets.',\n icon: 'Monitor',\n },\n [Toolkits.BROWSER]: {\n name: 'Browser',\n description: 'Control a web browser.',\n icon: 'Globe',\n },\n [Toolkits.VM]: {\n name: 'Virtual Machine',\n description: 'Manage virtual machine environments.',\n icon: 'Server',\n },\n [Toolkits.NOTEBOOK]: {\n name: 'Notebook',\n description: 'Run Jupyter notebook workflows.',\n icon: 'BookOpen',\n },\n [Toolkits.PRESENTATION]: {\n name: 'Presentation',\n description: 'Edit presentation slides.',\n icon: 'Presentation',\n },\n [Toolkits.POWERPOINT]: {\n name: 'PowerPoint',\n description: 'Create PowerPoint decks from templates.',\n icon: 'Presentation',\n },\n [Toolkits.PRESENTATION_PPTX_STUDIO]: {\n name: 'Presentation',\n description: 'Create PowerPoint presentations from templates (pptx-studio).',\n icon: 'Presentation',\n },\n [Toolkits.DRIVE]: {\n name: 'Olympus Drive',\n description: 'Find and manage workspace files.',\n icon: 'Folder',\n },\n [Toolkits.PYTHON]: {\n name: 'Python',\n description: 'Run Python analysis and automation.',\n icon: 'Code2',\n },\n [Toolkits.EMAIL]: {\n name: 'Email',\n description: 'Work across connected email and calendar accounts.',\n icon: 'Mail',\n },\n [Toolkits.EMAIL_CALENDAR]: {\n name: 'Email & Calendar',\n description: 'Use email and calendar operations.',\n icon: 'Calendar',\n },\n [Toolkits.SPREADSHEET]: {\n name: 'Spreadsheet',\n description: 'Create and edit spreadsheets.',\n icon: 'Table2',\n },\n [Toolkits.DOCUMENT]: {\n name: 'Document',\n description: 'Create and edit Athena documents.',\n icon: 'FileText',\n },\n [Toolkits.WORD_DOCUMENT]: {\n name: 'Word Document',\n description: 'Create and edit Word documents.',\n icon: 'FileText',\n },\n [Toolkits.GTM]: {\n name: 'Go-To-Market',\n description: 'Manage go-to-market workflows.',\n icon: 'BriefcaseBusiness',\n },\n [Toolkits.MARKETING]: {\n name: 'Marketing',\n description: 'Manage marketing campaigns.',\n icon: 'Megaphone',\n },\n [Toolkits.FDE]: {\n name: 'FDE',\n description: 'Build FDE implementations and workflows.',\n icon: 'Workflow',\n },\n [Toolkits.EXTERNAL_DRIVE]: {\n name: 'External Drive',\n description: 'Access SharePoint, Google Drive, and other files.',\n icon: 'HardDrive',\n },\n [Toolkits.PLAYBOOK]: {\n name: 'Playbook',\n description: 'Use reusable playbooks and prompts.',\n icon: 'BookOpen',\n },\n [Toolkits.DEVICE_TUNNEL]: {\n name: 'Device Tunnel',\n description: 'Control a local browser through a tunnel.',\n icon: 'Cable',\n },\n [Toolkits.PROJECTS]: {\n name: 'Projects',\n description: 'Manage project work.',\n icon: 'FolderKanban',\n },\n [Toolkits.TASK_STUDIO]: {\n name: 'Task Studio',\n description: 'Run Task Studio scripts.',\n icon: 'Terminal',\n },\n [Toolkits.PREFERENCES]: {\n name: 'Preferences',\n description: 'Use memory and preference tools.',\n icon: 'Settings',\n },\n semantic_model_toolkit: {\n name: 'Semantic Model',\n description: 'Query semantic models and generate analytics.',\n icon: 'ChartBar',\n },\n semantic_model_dev_toolkit: {\n name: 'Semantic Model Development',\n description: 'Create, validate, and deploy semantic model YAML.',\n icon: 'Database',\n },\n};\n\nconst humanizeToolkitId = (id: string): string => {\n const trimmed = id.trim();\n if (!trimmed) {\n return 'Toolkit';\n }\n\n const withoutSuffix = trimmed.replace(/_toolkit$/, '');\n return withoutSuffix\n .split(/[_-]+/)\n .filter(Boolean)\n .map((word) => {\n if (word.length <= 3) {\n return word.toUpperCase();\n }\n return `${word.charAt(0).toUpperCase()}${word.slice(1)}`;\n })\n .join(' ');\n};\n\nexport const getToolkitDisplayInfo = (id: string): ToolkitDisplayInfo => {\n const info = TOOLKIT_DISPLAY_INFO[id];\n\n return {\n id,\n name: info?.name ?? humanizeToolkitId(id),\n description: info?.description,\n icon: info?.icon ?? 'Package',\n };\n};\n"],"names":[],"mappings":"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"}
@@ -39,8 +39,6 @@ export declare const Toolkits: {
39
39
  readonly NOTEBOOK: 'notebook_toolkit';
40
40
  /** Presentation slide editing. */
41
41
  readonly PRESENTATION: 'presentation_toolkit';
42
- /** Presentation slide editing (OnlyOffice, deprecated). */
43
- readonly PRESENTATION_ONLYOFFICE: 'presentation_onlyoffice_toolkit';
44
42
  /** PowerPoint presentation creation from templates. */
45
43
  readonly POWERPOINT: 'powerpoint_deck_toolkit';
46
44
  /** PowerPoint presentation creation from templates (pptx-studio). */