@arbidocs/react 0.5.111 → 0.5.112

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 (983) hide show
  1. package/dist/account/client.js +96 -0
  2. package/dist/account/client.js.map +7 -0
  3. package/dist/account/delete.js +70 -0
  4. package/dist/account/delete.js.map +7 -0
  5. package/dist/account/didit.js +34 -0
  6. package/dist/account/didit.js.map +7 -0
  7. package/dist/account/dismissed-tips.js +33 -0
  8. package/dist/account/dismissed-tips.js.map +7 -0
  9. package/dist/account/email.js +84 -0
  10. package/dist/account/email.js.map +7 -0
  11. package/dist/account/entitlements.js +47 -0
  12. package/dist/account/entitlements.js.map +7 -0
  13. package/dist/account/identity.js +270 -0
  14. package/dist/account/identity.js.map +7 -0
  15. package/dist/account/index.js +93 -0
  16. package/dist/account/index.js.map +7 -0
  17. package/dist/account/notifications.js +59 -0
  18. package/dist/account/notifications.js.map +7 -0
  19. package/dist/account/password.js +103 -0
  20. package/dist/account/password.js.map +7 -0
  21. package/dist/account/profile.js +116 -0
  22. package/dist/account/profile.js.map +7 -0
  23. package/dist/account/recovery.js +13 -0
  24. package/dist/account/recovery.js.map +7 -0
  25. package/dist/account/relevance.js +82 -0
  26. package/dist/account/relevance.js.map +7 -0
  27. package/dist/account/sessions.js +37 -0
  28. package/dist/account/sessions.js.map +7 -0
  29. package/dist/account/settings.js +39 -0
  30. package/dist/account/settings.js.map +7 -0
  31. package/dist/account/table-views.js +16 -0
  32. package/dist/account/table-views.js.map +7 -0
  33. package/dist/ai/AiAnswer.js +83 -0
  34. package/dist/ai/AiAnswer.js.map +7 -0
  35. package/dist/ai/AiMarkdown.js +40 -0
  36. package/dist/ai/AiMarkdown.js.map +7 -0
  37. package/dist/ai/ArtifactCanvas.js +193 -0
  38. package/dist/ai/ArtifactCanvas.js.map +7 -0
  39. package/dist/ai/CitationRenderer.js +413 -0
  40. package/dist/ai/CitationRenderer.js.map +7 -0
  41. package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
  42. package/dist/ai/MarkdownRenderer.js.map +7 -0
  43. package/dist/ai/MessageArtifactCard.js +75 -0
  44. package/dist/ai/MessageArtifactCard.js.map +7 -0
  45. package/dist/ai/PassageCard.js +79 -0
  46. package/dist/ai/PassageCard.js.map +7 -0
  47. package/dist/ai/engine.js +110 -0
  48. package/dist/ai/engine.js.map +7 -0
  49. package/dist/ai/index.js +63 -0
  50. package/dist/ai/index.js.map +7 -0
  51. package/dist/ai/markdown-base-components.js +37 -0
  52. package/dist/ai/markdown-base-components.js.map +7 -0
  53. package/dist/ai/markdown-streaming-context.js +6 -0
  54. package/dist/ai/markdown-streaming-context.js.map +7 -0
  55. package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
  56. package/dist/ai/normalize-citations.js.map +7 -0
  57. package/dist/ai/redline.js +41 -0
  58. package/dist/ai/redline.js.map +7 -0
  59. package/dist/ai/split-markdown-blocks.js +40 -0
  60. package/dist/ai/split-markdown-blocks.js.map +7 -0
  61. package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
  62. package/dist/ai/stored-markdown.js.map +7 -0
  63. package/dist/annotations/AnnotationPageOverlay.js +807 -0
  64. package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
  65. package/dist/annotations/AnnotationToolbar.js +398 -0
  66. package/dist/annotations/AnnotationToolbar.js.map +7 -0
  67. package/dist/annotations/FreezeDialog.js +170 -0
  68. package/dist/annotations/FreezeDialog.js.map +7 -0
  69. package/dist/annotations/ProductionDialog.js +354 -0
  70. package/dist/annotations/ProductionDialog.js.map +7 -0
  71. package/dist/annotations/controller.js +49 -0
  72. package/dist/annotations/controller.js.map +7 -0
  73. package/dist/annotations/freeze/browser.js +21 -0
  74. package/dist/annotations/freeze/browser.js.map +7 -0
  75. package/dist/annotations/freeze/bundle.js +201 -0
  76. package/dist/annotations/freeze/bundle.js.map +7 -0
  77. package/dist/annotations/freeze/coords.js +37 -0
  78. package/dist/annotations/freeze/coords.js.map +7 -0
  79. package/dist/annotations/freeze/freeze.js +261 -0
  80. package/dist/annotations/freeze/freeze.js.map +7 -0
  81. package/dist/annotations/freeze/hash.js +28 -0
  82. package/dist/annotations/freeze/hash.js.map +7 -0
  83. package/dist/annotations/freeze/index-page.js +78 -0
  84. package/dist/annotations/freeze/index-page.js.map +7 -0
  85. package/dist/annotations/freeze/index.js +28 -22
  86. package/dist/annotations/freeze/index.js.map +7 -1
  87. package/dist/annotations/freeze/raster.js +208 -0
  88. package/dist/annotations/freeze/raster.js.map +7 -0
  89. package/dist/annotations/freeze/stamp.js +117 -0
  90. package/dist/annotations/freeze/stamp.js.map +7 -0
  91. package/dist/annotations/freeze/types.js +14 -0
  92. package/dist/annotations/freeze/types.js.map +7 -0
  93. package/dist/annotations/freeze/vector.js +283 -0
  94. package/dist/annotations/freeze/vector.js.map +7 -0
  95. package/dist/annotations/geometry.js +81 -0
  96. package/dist/annotations/geometry.js.map +7 -0
  97. package/dist/annotations/index.js +125 -6
  98. package/dist/annotations/index.js.map +7 -1
  99. package/dist/annotations/merge.js +53 -0
  100. package/dist/annotations/merge.js.map +7 -0
  101. package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
  102. package/dist/annotations/model.js.map +7 -0
  103. package/dist/annotations/overlay-geometry.js +41 -0
  104. package/dist/annotations/overlay-geometry.js.map +7 -0
  105. package/dist/annotations/redaction-log.js +33 -0
  106. package/dist/annotations/redaction-log.js.map +7 -0
  107. package/dist/annotations/selection-marks.js +122 -0
  108. package/dist/annotations/selection-marks.js.map +7 -0
  109. package/dist/annotations/state.js +140 -0
  110. package/dist/annotations/state.js.map +7 -0
  111. package/dist/annotations/store.js +49 -0
  112. package/dist/annotations/store.js.map +7 -0
  113. package/dist/annotations/useAnnotationLayer.js +306 -0
  114. package/dist/annotations/useAnnotationLayer.js.map +7 -0
  115. package/dist/annotations/useAnnotationShortcuts.js +31 -0
  116. package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
  117. package/dist/annotations/useTextSelectionMarks.js +100 -0
  118. package/dist/annotations/useTextSelectionMarks.js.map +7 -0
  119. package/dist/artifacts/artifact-kind.js +19 -0
  120. package/dist/artifacts/artifact-kind.js.map +7 -0
  121. package/dist/artifacts/index.js +89 -571
  122. package/dist/artifacts/index.js.map +7 -1
  123. package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
  124. package/dist/artifacts/normalize-markdown.js.map +7 -0
  125. package/dist/artifacts/redline-core.js +12 -3
  126. package/dist/artifacts/redline-core.js.map +7 -1
  127. package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
  128. package/dist/artifacts/redline-diff.js.map +7 -0
  129. package/dist/artifacts/redline-engine.js +14 -0
  130. package/dist/artifacts/redline-engine.js.map +7 -0
  131. package/dist/artifacts/renderArtifactMarkdown.js +9 -0
  132. package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
  133. package/dist/artifacts/useArtifactEditSession.js +183 -0
  134. package/dist/artifacts/useArtifactEditSession.js.map +7 -0
  135. package/dist/artifacts/useArtifactSession.js +173 -0
  136. package/dist/artifacts/useArtifactSession.js.map +7 -0
  137. package/dist/artifacts/useArtifactSource.js +16 -0
  138. package/dist/artifacts/useArtifactSource.js.map +7 -0
  139. package/dist/artifacts/useArtifactText.js +78 -0
  140. package/dist/artifacts/useArtifactText.js.map +7 -0
  141. package/dist/artifacts/useRedline.js +65 -0
  142. package/dist/artifacts/useRedline.js.map +7 -0
  143. package/dist/artifacts/useStreamedArtifact.js +74 -0
  144. package/dist/artifacts/useStreamedArtifact.js.map +7 -0
  145. package/dist/artifacts/versions.js +68 -0
  146. package/dist/artifacts/versions.js.map +7 -0
  147. package/dist/billing.js +200 -0
  148. package/dist/billing.js.map +7 -0
  149. package/dist/boot-timeout.js +19 -0
  150. package/dist/boot-timeout.js.map +7 -0
  151. package/dist/calendar/accounts.js +213 -0
  152. package/dist/calendar/accounts.js.map +7 -0
  153. package/dist/calendar/hooks.js +409 -0
  154. package/dist/calendar/hooks.js.map +7 -0
  155. package/dist/calendar/index.js +31 -0
  156. package/dist/calendar/index.js.map +7 -0
  157. package/dist/calendar/keys.js +5 -0
  158. package/dist/calendar/keys.js.map +7 -0
  159. package/dist/calendar/offline/outbox.js +231 -0
  160. package/dist/calendar/offline/outbox.js.map +7 -0
  161. package/dist/calendar/offline/runtime.js +109 -0
  162. package/dist/calendar/offline/runtime.js.map +7 -0
  163. package/dist/calendar/offline/support.js +41 -0
  164. package/dist/calendar/offline/support.js.map +7 -0
  165. package/dist/calendar/support.js +34 -0
  166. package/dist/calendar/support.js.map +7 -0
  167. package/dist/calls/actions.js +226 -0
  168. package/dist/calls/actions.js.map +7 -0
  169. package/dist/calls/events.js +138 -0
  170. package/dist/calls/events.js.map +7 -0
  171. package/dist/calls/gate.js +19 -0
  172. package/dist/calls/gate.js.map +7 -0
  173. package/dist/calls/hooks.js +115 -0
  174. package/dist/calls/hooks.js.map +7 -0
  175. package/dist/calls/in-call-chat.js +132 -0
  176. package/dist/calls/in-call-chat.js.map +7 -0
  177. package/dist/calls/index.js +24 -0
  178. package/dist/calls/index.js.map +7 -0
  179. package/dist/calls/keys.js +17 -0
  180. package/dist/calls/keys.js.map +7 -0
  181. package/dist/calls/livekit/index.js +6 -958
  182. package/dist/calls/livekit/index.js.map +7 -1
  183. package/dist/calls/livekit/room.js +98 -0
  184. package/dist/calls/livekit/room.js.map +7 -0
  185. package/dist/calls/livekit/useCallRecorder.js +219 -0
  186. package/dist/calls/livekit/useCallRecorder.js.map +7 -0
  187. package/dist/calls/livekit/useCallTranscriber.js +309 -0
  188. package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
  189. package/dist/calls/livekit/useHostMuteNotice.js +29 -0
  190. package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
  191. package/dist/calls/livekit/useInCallChat.js +161 -0
  192. package/dist/calls/livekit/useInCallChat.js.map +7 -0
  193. package/dist/calls/livekit/useWebinar.js +239 -0
  194. package/dist/calls/livekit/useWebinar.js.map +7 -0
  195. package/dist/calls/meeting-chat.js +149 -0
  196. package/dist/calls/meeting-chat.js.map +7 -0
  197. package/dist/calls/moderation.js +50 -0
  198. package/dist/calls/moderation.js.map +7 -0
  199. package/dist/calls/open-meeting-chat.js +29 -0
  200. package/dist/calls/open-meeting-chat.js.map +7 -0
  201. package/dist/calls/read-only.js +24 -0
  202. package/dist/calls/read-only.js.map +7 -0
  203. package/dist/calls/recording-media.js +218 -0
  204. package/dist/calls/recording-media.js.map +7 -0
  205. package/dist/calls/recording-playback.js +260 -0
  206. package/dist/calls/recording-playback.js.map +7 -0
  207. package/dist/calls/recording.js +268 -0
  208. package/dist/calls/recording.js.map +7 -0
  209. package/dist/calls/save-to-thread.js +80 -0
  210. package/dist/calls/save-to-thread.js.map +7 -0
  211. package/dist/calls/session.js +134 -0
  212. package/dist/calls/session.js.map +7 -0
  213. package/dist/calls/transcript-format.js +147 -0
  214. package/dist/calls/transcript-format.js.map +7 -0
  215. package/dist/calls/transcription.js +101 -0
  216. package/dist/calls/transcription.js.map +7 -0
  217. package/dist/calls/webinar.js +71 -0
  218. package/dist/calls/webinar.js.map +7 -0
  219. package/dist/charge-watch.js +71 -0
  220. package/dist/charge-watch.js.map +7 -0
  221. package/dist/chat/ChatBubble.js +146 -0
  222. package/dist/chat/ChatBubble.js.map +7 -0
  223. package/dist/chat/ConversationScope.js +30 -0
  224. package/dist/chat/ConversationScope.js.map +7 -0
  225. package/dist/chat/active-config.js +20 -0
  226. package/dist/chat/active-config.js.map +7 -0
  227. package/dist/chat/agent-chat-owner.js +25 -0
  228. package/dist/chat/agent-chat-owner.js.map +7 -0
  229. package/dist/chat/chat-artifacts.js +64 -0
  230. package/dist/chat/chat-artifacts.js.map +7 -0
  231. package/dist/chat/citations.js +32 -0
  232. package/dist/chat/citations.js.map +7 -0
  233. package/dist/chat/config-model.js +10 -0
  234. package/dist/chat/config-model.js.map +7 -0
  235. package/dist/chat/conversation-cache.js +676 -0
  236. package/dist/chat/conversation-cache.js.map +7 -0
  237. package/dist/chat/conversation-events.js +57 -0
  238. package/dist/chat/conversation-events.js.map +7 -0
  239. package/dist/chat/conversation-mentions.js +58 -0
  240. package/dist/chat/conversation-mentions.js.map +7 -0
  241. package/dist/chat/conversation-workspace.js +58 -0
  242. package/dist/chat/conversation-workspace.js.map +7 -0
  243. package/dist/chat/mentions.js +116 -0
  244. package/dist/chat/mentions.js.map +7 -0
  245. package/dist/chat/open-document.js +106 -0
  246. package/dist/chat/open-document.js.map +7 -0
  247. package/dist/chat/orphaned.js +44 -0
  248. package/dist/chat/orphaned.js.map +7 -0
  249. package/dist/chat/pendingFirstTurn.js +30 -0
  250. package/dist/chat/pendingFirstTurn.js.map +7 -0
  251. package/dist/chat/reply-target.js +12 -0
  252. package/dist/chat/reply-target.js.map +7 -0
  253. package/dist/chat/run-finished.js +28 -0
  254. package/dist/chat/run-finished.js.map +7 -0
  255. package/dist/chat/run-state.js +91 -0
  256. package/dist/chat/run-state.js.map +7 -0
  257. package/dist/chat/stream-handlers.js +419 -0
  258. package/dist/chat/stream-handlers.js.map +7 -0
  259. package/dist/chat/thread-binding.js +76 -0
  260. package/dist/chat/thread-binding.js.map +7 -0
  261. package/dist/chat/thread-document.js +53 -0
  262. package/dist/chat/thread-document.js.map +7 -0
  263. package/dist/chat/turn-control.js +79 -0
  264. package/dist/chat/turn-control.js.map +7 -0
  265. package/dist/chat/useAgentRunControl.js +36 -0
  266. package/dist/chat/useAgentRunControl.js.map +7 -0
  267. package/dist/chat/useAnswerAgentQuestion.js +19 -0
  268. package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
  269. package/dist/chat/useAskAgain.js +32 -0
  270. package/dist/chat/useAskAgain.js.map +7 -0
  271. package/dist/chat/useAutoSendDraft.js +17 -0
  272. package/dist/chat/useAutoSendDraft.js.map +7 -0
  273. package/dist/chat/useBranchNavigation.js +97 -0
  274. package/dist/chat/useBranchNavigation.js.map +7 -0
  275. package/dist/chat/useConnectRunStream.js +169 -0
  276. package/dist/chat/useConnectRunStream.js.map +7 -0
  277. package/dist/chat/useConversation.js +431 -0
  278. package/dist/chat/useConversation.js.map +7 -0
  279. package/dist/chat/useConversationActions.js +662 -0
  280. package/dist/chat/useConversationActions.js.map +7 -0
  281. package/dist/chat/useConversationData.js +143 -0
  282. package/dist/chat/useConversationData.js.map +7 -0
  283. package/dist/chat/useConversationDocuments.js +41 -0
  284. package/dist/chat/useConversationDocuments.js.map +7 -0
  285. package/dist/chat/useConversationSettings.js +78 -0
  286. package/dist/chat/useConversationSettings.js.map +7 -0
  287. package/dist/chat/useConversationTurn.js +31 -0
  288. package/dist/chat/useConversationTurn.js.map +7 -0
  289. package/dist/chat/useConversationWorkspace.js +12 -0
  290. package/dist/chat/useConversationWorkspace.js.map +7 -0
  291. package/dist/chat/useDeleteMessage.js +15 -0
  292. package/dist/chat/useDeleteMessage.js.map +7 -0
  293. package/dist/chat/useDocumentAutoAdd.js +73 -0
  294. package/dist/chat/useDocumentAutoAdd.js.map +7 -0
  295. package/dist/chat/useMessageTimer.js +39 -0
  296. package/dist/chat/useMessageTimer.js.map +7 -0
  297. package/dist/chat/useThinkingContent.js +67 -0
  298. package/dist/chat/useThinkingContent.js.map +7 -0
  299. package/dist/chat/useThreadDocument.js +61 -0
  300. package/dist/chat/useThreadDocument.js.map +7 -0
  301. package/dist/chat/workflow-run-titles.js +50 -0
  302. package/dist/chat/workflow-run-titles.js.map +7 -0
  303. package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
  304. package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
  305. package/dist/{chunk-LBAG7KL7.cjs → chunk-FQVNZCTD.cjs} +3 -3
  306. package/dist/{chunk-LBAG7KL7.cjs.map → chunk-FQVNZCTD.cjs.map} +1 -1
  307. package/dist/{chunk-DI5KSVKY.cjs → chunk-UDDJIUHJ.cjs} +3 -3
  308. package/dist/{chunk-DI5KSVKY.cjs.map → chunk-UDDJIUHJ.cjs.map} +1 -1
  309. package/dist/config/config-hooks.js +209 -0
  310. package/dist/config/config-hooks.js.map +7 -0
  311. package/dist/connectivity.js +72 -0
  312. package/dist/connectivity.js.map +7 -0
  313. package/dist/connectors/hooks.js +263 -0
  314. package/dist/connectors/hooks.js.map +7 -0
  315. package/dist/connectors/index.js +28 -0
  316. package/dist/connectors/index.js.map +7 -0
  317. package/dist/contacts.js +100 -0
  318. package/dist/contacts.js.map +7 -0
  319. package/dist/conversation-list.js +65 -0
  320. package/dist/conversation-list.js.map +7 -0
  321. package/dist/databases.js +195 -0
  322. package/dist/databases.js.map +7 -0
  323. package/dist/datasets/aggregate.js +281 -0
  324. package/dist/datasets/aggregate.js.map +7 -0
  325. package/dist/datasets/index.js +122 -0
  326. package/dist/datasets/index.js.map +7 -0
  327. package/dist/datasets/members.js +27 -0
  328. package/dist/datasets/members.js.map +7 -0
  329. package/dist/datasets/panel.js +44 -0
  330. package/dist/datasets/panel.js.map +7 -0
  331. package/dist/datasets/registry.js +47 -0
  332. package/dist/datasets/registry.js.map +7 -0
  333. package/dist/datasets/rows-source.js +44 -0
  334. package/dist/datasets/rows-source.js.map +7 -0
  335. package/dist/datasets/sources/activity.js +83 -0
  336. package/dist/datasets/sources/activity.js.map +7 -0
  337. package/dist/datasets/sources/conversations.js +74 -0
  338. package/dist/datasets/sources/conversations.js.map +7 -0
  339. package/dist/datasets/sources/database.js +209 -0
  340. package/dist/datasets/sources/database.js.map +7 -0
  341. package/dist/datasets/sources/documents.js +93 -0
  342. package/dist/datasets/sources/documents.js.map +7 -0
  343. package/dist/datasets/sources/facts.js +56 -0
  344. package/dist/datasets/sources/facts.js.map +7 -0
  345. package/dist/datasets/sources/projects.js +117 -0
  346. package/dist/datasets/sources/projects.js.map +7 -0
  347. package/dist/datasets/sources/tags.js +67 -0
  348. package/dist/datasets/sources/tags.js.map +7 -0
  349. package/dist/datasets/sources/usage.js +268 -0
  350. package/dist/datasets/sources/usage.js.map +7 -0
  351. package/dist/datasets/sources/workflows.js +91 -0
  352. package/dist/datasets/sources/workflows.js.map +7 -0
  353. package/dist/datasets/sources/workspaces.js +67 -0
  354. package/dist/datasets/sources/workspaces.js.map +7 -0
  355. package/dist/datasets/store.js +194 -0
  356. package/dist/datasets/store.js.map +7 -0
  357. package/dist/datasets/types.js +14 -0
  358. package/dist/datasets/types.js.map +7 -0
  359. package/dist/directmessages/ConversationList.js +148 -0
  360. package/dist/directmessages/ConversationList.js.map +7 -0
  361. package/dist/directmessages/DateSeparator.js +8 -0
  362. package/dist/directmessages/DateSeparator.js.map +7 -0
  363. package/dist/directmessages/DmAvatar.js +29 -0
  364. package/dist/directmessages/DmAvatar.js.map +7 -0
  365. package/dist/directmessages/DmComposer.js +201 -0
  366. package/dist/directmessages/DmComposer.js.map +7 -0
  367. package/dist/directmessages/arrivals.js +29 -0
  368. package/dist/directmessages/arrivals.js.map +7 -0
  369. package/dist/directmessages/chat-cache.js +192 -0
  370. package/dist/directmessages/chat-cache.js.map +7 -0
  371. package/dist/directmessages/grouping.js +26 -0
  372. package/dist/directmessages/grouping.js.map +7 -0
  373. package/dist/directmessages/index.js +81 -0
  374. package/dist/directmessages/index.js.map +7 -0
  375. package/dist/directmessages/useChats.js +266 -0
  376. package/dist/directmessages/useChats.js.map +7 -0
  377. package/dist/directmessages/utils.js +23 -0
  378. package/dist/directmessages/utils.js.map +7 -0
  379. package/dist/document-tools/can-annotate.js +7 -0
  380. package/dist/document-tools/can-annotate.js.map +7 -0
  381. package/dist/document-tools/core.cjs +80 -80
  382. package/dist/document-tools/core.js +218 -12
  383. package/dist/document-tools/core.js.map +7 -1
  384. package/dist/document-tools/document-pdf.js +76 -0
  385. package/dist/document-tools/document-pdf.js.map +7 -0
  386. package/dist/document-tools/environment.js +136 -0
  387. package/dist/document-tools/environment.js.map +7 -0
  388. package/dist/document-tools/file-shares.js +112 -0
  389. package/dist/document-tools/file-shares.js.map +7 -0
  390. package/dist/document-tools/frozen-copy.js +27 -0
  391. package/dist/document-tools/frozen-copy.js.map +7 -0
  392. package/dist/document-tools/index.cjs +80 -80
  393. package/dist/document-tools/index.js +26 -148
  394. package/dist/document-tools/index.js.map +7 -1
  395. package/dist/document-tools/markup-download.js +51 -0
  396. package/dist/document-tools/markup-download.js.map +7 -0
  397. package/dist/document-tools/markup-store.js +138 -0
  398. package/dist/document-tools/markup-store.js.map +7 -0
  399. package/dist/document-tools/markup-transfer.js +88 -0
  400. package/dist/document-tools/markup-transfer.js.map +7 -0
  401. package/dist/document-tools/production.js +147 -0
  402. package/dist/document-tools/production.js.map +7 -0
  403. package/dist/document-tools/saved-signature.js +90 -0
  404. package/dist/document-tools/saved-signature.js.map +7 -0
  405. package/dist/document-tools/signature-requests.js +310 -0
  406. package/dist/document-tools/signature-requests.js.map +7 -0
  407. package/dist/document-tools/signing.js +127 -0
  408. package/dist/document-tools/signing.js.map +7 -0
  409. package/dist/document-tools/useDocumentBytes.js +38 -0
  410. package/dist/document-tools/useDocumentBytes.js.map +7 -0
  411. package/dist/document-tools/useDocumentMarkup.js +154 -0
  412. package/dist/document-tools/useDocumentMarkup.js.map +7 -0
  413. package/dist/document-tools/useIsOnline.js +13 -0
  414. package/dist/document-tools/useIsOnline.js.map +7 -0
  415. package/dist/document-tools/verification.js +60 -0
  416. package/dist/document-tools/verification.js.map +7 -0
  417. package/dist/documents/DocumentReview.js +220 -0
  418. package/dist/documents/DocumentReview.js.map +7 -0
  419. package/dist/documents/DraftTitleControls.js +41 -0
  420. package/dist/documents/DraftTitleControls.js.map +7 -0
  421. package/dist/documents/InlineMicButton.js +90 -0
  422. package/dist/documents/InlineMicButton.js.map +7 -0
  423. package/dist/documents/MicRecordingOverlay.js +29 -0
  424. package/dist/documents/MicRecordingOverlay.js.map +7 -0
  425. package/dist/documents/MicWaveformIndicator.js +68 -0
  426. package/dist/documents/MicWaveformIndicator.js.map +7 -0
  427. package/dist/documents/PhotoCapture.js +120 -0
  428. package/dist/documents/PhotoCapture.js.map +7 -0
  429. package/dist/documents/VideoCapture.js +129 -0
  430. package/dist/documents/VideoCapture.js.map +7 -0
  431. package/dist/documents/VoiceNoteRecorder.js +166 -0
  432. package/dist/documents/VoiceNoteRecorder.js.map +7 -0
  433. package/dist/documents/audio-segmenter.js +63 -0
  434. package/dist/documents/audio-segmenter.js.map +7 -0
  435. package/dist/documents/capture-frame.js +21 -0
  436. package/dist/documents/capture-frame.js.map +7 -0
  437. package/dist/documents/chunked-recorder.js +190 -0
  438. package/dist/documents/chunked-recorder.js.map +7 -0
  439. package/dist/documents/document-download.js +53 -0
  440. package/dist/documents/document-download.js.map +7 -0
  441. package/dist/documents/document-fields.js +109 -0
  442. package/dist/documents/document-fields.js.map +7 -0
  443. package/dist/documents/documents-cache.js +110 -0
  444. package/dist/documents/documents-cache.js.map +7 -0
  445. package/dist/documents/documents-data.js +128 -0
  446. package/dist/documents/documents-data.js.map +7 -0
  447. package/dist/documents/documents-loader.js +113 -0
  448. package/dist/documents/documents-loader.js.map +7 -0
  449. package/dist/documents/documents-writes.js +448 -0
  450. package/dist/documents/documents-writes.js.map +7 -0
  451. package/dist/documents/format-elapsed.js +10 -0
  452. package/dist/documents/format-elapsed.js.map +7 -0
  453. package/dist/documents/has-video-track.js +26 -0
  454. package/dist/documents/has-video-track.js.map +7 -0
  455. package/dist/documents/index.js +266 -0
  456. package/dist/documents/index.js.map +7 -0
  457. package/dist/documents/media-error.js +18 -0
  458. package/dist/documents/media-error.js.map +7 -0
  459. package/dist/documents/offline-documents.js +160 -0
  460. package/dist/documents/offline-documents.js.map +7 -0
  461. package/dist/documents/pending-sync.js +210 -0
  462. package/dist/documents/pending-sync.js.map +7 -0
  463. package/dist/documents/processing-live.js +122 -0
  464. package/dist/documents/processing-live.js.map +7 -0
  465. package/dist/documents/processing-order.js +59 -0
  466. package/dist/documents/processing-order.js.map +7 -0
  467. package/dist/documents/processing-settle.js +21 -0
  468. package/dist/documents/processing-settle.js.map +7 -0
  469. package/dist/documents/related-documents.js +133 -0
  470. package/dist/documents/related-documents.js.map +7 -0
  471. package/dist/documents/support.js +29 -0
  472. package/dist/documents/support.js.map +7 -0
  473. package/dist/documents/upload-files.js +169 -0
  474. package/dist/documents/upload-files.js.map +7 -0
  475. package/dist/documents/useAudioRecorder.js +315 -0
  476. package/dist/documents/useAudioRecorder.js.map +7 -0
  477. package/dist/documents/useCameraStream.js +35 -0
  478. package/dist/documents/useCameraStream.js.map +7 -0
  479. package/dist/documents/useDocumentThumbnails.js +71 -0
  480. package/dist/documents/useDocumentThumbnails.js.map +7 -0
  481. package/dist/documents/useDownloadDocuments.js +90 -0
  482. package/dist/documents/useDownloadDocuments.js.map +7 -0
  483. package/dist/documents/usePassageQuotes.js +37 -0
  484. package/dist/documents/usePassageQuotes.js.map +7 -0
  485. package/dist/documents/useUploadFiles.js +165 -0
  486. package/dist/documents/useUploadFiles.js.map +7 -0
  487. package/dist/documents/useUploadFromUrls.js +63 -0
  488. package/dist/documents/useUploadFromUrls.js.map +7 -0
  489. package/dist/documents/useVideoRecorder.js +62 -0
  490. package/dist/documents/useVideoRecorder.js.map +7 -0
  491. package/dist/entities/AgentMarkers.js +61 -0
  492. package/dist/entities/AgentMarkers.js.map +7 -0
  493. package/dist/entities/DocumentEntity.js +125 -0
  494. package/dist/entities/DocumentEntity.js.map +7 -0
  495. package/dist/entities/EntityPill.js +250 -0
  496. package/dist/entities/EntityPill.js.map +7 -0
  497. package/dist/entities/ProjectEntity.js +61 -0
  498. package/dist/entities/ProjectEntity.js.map +7 -0
  499. package/dist/entities/ShieldIcon.js +49 -0
  500. package/dist/entities/ShieldIcon.js.map +7 -0
  501. package/dist/entities/TagEntity.js +79 -0
  502. package/dist/entities/TagEntity.js.map +7 -0
  503. package/dist/entities/ThreadVisibilityIcon.js +15 -0
  504. package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
  505. package/dist/entities/UserEntity.js +211 -0
  506. package/dist/entities/UserEntity.js.map +7 -0
  507. package/dist/entities/VerifiedBadge.js +19 -0
  508. package/dist/entities/VerifiedBadge.js.map +7 -0
  509. package/dist/entities/agent-avatar-colors.js +26 -0
  510. package/dist/entities/agent-avatar-colors.js.map +7 -0
  511. package/dist/entities/colors.js +64 -0
  512. package/dist/entities/colors.js.map +7 -0
  513. package/dist/entities/file-type.js +151 -0
  514. package/dist/entities/file-type.js.map +7 -0
  515. package/dist/entities/index.js +100 -0
  516. package/dist/entities/index.js.map +7 -0
  517. package/dist/entities/media-type.js +61 -0
  518. package/dist/entities/media-type.js.map +7 -0
  519. package/dist/entities/registry.js +385 -0
  520. package/dist/entities/registry.js.map +7 -0
  521. package/dist/entities/status.js +43 -0
  522. package/dist/entities/status.js.map +7 -0
  523. package/dist/entities/tag-kinds.js +23 -0
  524. package/dist/entities/tag-kinds.js.map +7 -0
  525. package/dist/entities/tag-types.js +44 -0
  526. package/dist/entities/tag-types.js.map +7 -0
  527. package/dist/entities/vocabulary.js +12 -0
  528. package/dist/entities/vocabulary.js.map +7 -0
  529. package/dist/entity-extraction.js +25 -0
  530. package/dist/entity-extraction.js.map +7 -0
  531. package/dist/facts-search.js +57 -0
  532. package/dist/facts-search.js.map +7 -0
  533. package/dist/facts.js +69 -0
  534. package/dist/facts.js.map +7 -0
  535. package/dist/hooks.js +320 -0
  536. package/dist/hooks.js.map +7 -0
  537. package/dist/host/ArbiHost.js +24 -0
  538. package/dist/host/ArbiHost.js.map +7 -0
  539. package/dist/host/assistant-copy.js +54 -0
  540. package/dist/host/assistant-copy.js.map +7 -0
  541. package/dist/host/config.js +9 -0
  542. package/dist/host/config.js.map +7 -0
  543. package/dist/host/context.js +10 -0
  544. package/dist/host/context.js.map +7 -0
  545. package/dist/host/features.js +144 -0
  546. package/dist/host/features.js.map +7 -0
  547. package/dist/host/index.js +12 -0
  548. package/dist/host/index.js.map +7 -0
  549. package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
  550. package/dist/host/merge.js.map +7 -0
  551. package/dist/house-template.js +40 -0
  552. package/dist/house-template.js.map +7 -0
  553. package/dist/icons/AppleIcon.js +25 -0
  554. package/dist/icons/AppleIcon.js.map +7 -0
  555. package/dist/icons/ArbiBotHeadIcon.js +46 -0
  556. package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
  557. package/dist/icons/ArbiIcon.js +24 -0
  558. package/dist/icons/ArbiIcon.js.map +7 -0
  559. package/dist/icons/AudIcon.js +56 -0
  560. package/dist/icons/AudIcon.js.map +7 -0
  561. package/dist/icons/ClaudeIcon.js +28 -0
  562. package/dist/icons/ClaudeIcon.js.map +7 -0
  563. package/dist/icons/DocIcon.js +56 -0
  564. package/dist/icons/DocIcon.js.map +7 -0
  565. package/dist/icons/EmlIcon.js +57 -0
  566. package/dist/icons/EmlIcon.js.map +7 -0
  567. package/dist/icons/FireworksIcon.js +47 -0
  568. package/dist/icons/FireworksIcon.js.map +7 -0
  569. package/dist/icons/GeminiIcon.js +37 -0
  570. package/dist/icons/GeminiIcon.js.map +7 -0
  571. package/dist/icons/GitHubIcon.js +32 -0
  572. package/dist/icons/GitHubIcon.js.map +7 -0
  573. package/dist/icons/GoogleIcon.js +53 -0
  574. package/dist/icons/GoogleIcon.js.map +7 -0
  575. package/dist/icons/HtmlIcon.js +56 -0
  576. package/dist/icons/HtmlIcon.js.map +7 -0
  577. package/dist/icons/ImgIcon.js +56 -0
  578. package/dist/icons/ImgIcon.js.map +7 -0
  579. package/dist/icons/LinkedInIcon.js +25 -0
  580. package/dist/icons/LinkedInIcon.js.map +7 -0
  581. package/dist/icons/OpenAIIcon.js +28 -0
  582. package/dist/icons/OpenAIIcon.js.map +7 -0
  583. package/dist/icons/PdfIcon.js +56 -0
  584. package/dist/icons/PdfIcon.js.map +7 -0
  585. package/dist/icons/ProviderIcon.js +42 -0
  586. package/dist/icons/ProviderIcon.js.map +7 -0
  587. package/dist/icons/TxtIcon.js +56 -0
  588. package/dist/icons/TxtIcon.js.map +7 -0
  589. package/dist/icons/VidIcon.js +56 -0
  590. package/dist/icons/VidIcon.js.map +7 -0
  591. package/dist/icons/XlsIcon.js +56 -0
  592. package/dist/icons/XlsIcon.js.map +7 -0
  593. package/dist/icons/arbi-mark.js +5 -0
  594. package/dist/icons/arbi-mark.js.map +7 -0
  595. package/dist/icons/colors.js +31 -0
  596. package/dist/icons/colors.js.map +7 -0
  597. package/dist/icons/file-type.js +105 -0
  598. package/dist/icons/file-type.js.map +7 -0
  599. package/dist/icons/index.js +55 -0
  600. package/dist/icons/index.js.map +7 -0
  601. package/dist/imagecrop/ImageCropModal.js +56 -0
  602. package/dist/imagecrop/ImageCropModal.js.map +7 -0
  603. package/dist/imagecrop/ImageCropper.js +100 -0
  604. package/dist/imagecrop/ImageCropper.js.map +7 -0
  605. package/dist/imagecrop/cropImage.js +43 -0
  606. package/dist/imagecrop/cropImage.js.map +7 -0
  607. package/dist/imagecrop/index.js +13 -0
  608. package/dist/imagecrop/index.js.map +7 -0
  609. package/dist/index.cjs +282 -282
  610. package/dist/index.js +702 -17116
  611. package/dist/index.js.map +7 -1
  612. package/dist/{chunk-SSXFVWCT.js → lazy-chunk.js} +8 -8
  613. package/dist/lazy-chunk.js.map +7 -0
  614. package/dist/lib/collision-padding.js +13 -0
  615. package/dist/lib/collision-padding.js.map +7 -0
  616. package/dist/lib/format-friendly-date.js +55 -0
  617. package/dist/lib/format-friendly-date.js.map +7 -0
  618. package/dist/lib/format-relative-time.js +52 -0
  619. package/dist/lib/format-relative-time.js.map +7 -0
  620. package/dist/lib/markdown-to-text.js +35 -0
  621. package/dist/lib/markdown-to-text.js.map +7 -0
  622. package/dist/lib/toast-interaction.js +9 -0
  623. package/dist/lib/toast-interaction.js.map +7 -0
  624. package/dist/lib/utils.js +9 -0
  625. package/dist/lib/utils.js.map +7 -0
  626. package/dist/mail/client.js +103 -0
  627. package/dist/mail/client.js.map +7 -0
  628. package/dist/mail/document-attachment.js +38 -0
  629. package/dist/mail/document-attachment.js.map +7 -0
  630. package/dist/mail/filing.js +132 -0
  631. package/dist/mail/filing.js.map +7 -0
  632. package/dist/mail/hooks.js +393 -0
  633. package/dist/mail/hooks.js.map +7 -0
  634. package/dist/mail/index.js +120 -0
  635. package/dist/mail/index.js.map +7 -0
  636. package/dist/mail/offline/changes.js +258 -0
  637. package/dist/mail/offline/changes.js.map +7 -0
  638. package/dist/mail/offline/confirm-sign-out.js +37 -0
  639. package/dist/mail/offline/confirm-sign-out.js.map +7 -0
  640. package/dist/mail/offline/crypto.js +26 -0
  641. package/dist/mail/offline/crypto.js.map +7 -0
  642. package/dist/mail/offline/drafts.js +69 -0
  643. package/dist/mail/offline/drafts.js.map +7 -0
  644. package/dist/mail/offline/hooks.js +104 -0
  645. package/dist/mail/offline/hooks.js.map +7 -0
  646. package/dist/mail/offline/index.js +48 -0
  647. package/dist/mail/offline/index.js.map +7 -0
  648. package/dist/mail/offline/live.js +233 -0
  649. package/dist/mail/offline/live.js.map +7 -0
  650. package/dist/mail/offline/mailbox.js +191 -0
  651. package/dist/mail/offline/mailbox.js.map +7 -0
  652. package/dist/mail/offline/outbox.js +167 -0
  653. package/dist/mail/offline/outbox.js.map +7 -0
  654. package/dist/mail/offline/reads.js +159 -0
  655. package/dist/mail/offline/reads.js.map +7 -0
  656. package/dist/mail/offline/runtime.js +100 -0
  657. package/dist/mail/offline/runtime.js.map +7 -0
  658. package/dist/mail/offline/settings.js +84 -0
  659. package/dist/mail/offline/settings.js.map +7 -0
  660. package/dist/mail/offline/store.js +29 -0
  661. package/dist/mail/offline/store.js.map +7 -0
  662. package/dist/mail/offline/sync.js +251 -0
  663. package/dist/mail/offline/sync.js.map +7 -0
  664. package/dist/mail/offline/wipe.js +19 -0
  665. package/dist/mail/offline/wipe.js.map +7 -0
  666. package/dist/mail/thread-keys.js +53 -0
  667. package/dist/mail/thread-keys.js.map +7 -0
  668. package/dist/mail/threads.js +71 -0
  669. package/dist/mail/threads.js.map +7 -0
  670. package/dist/mail/useMailClient.js +42 -0
  671. package/dist/mail/useMailClient.js.map +7 -0
  672. package/dist/model-connections.js +58 -0
  673. package/dist/model-connections.js.map +7 -0
  674. package/dist/notifications/ActivityFeed.js +70 -0
  675. package/dist/notifications/ActivityFeed.js.map +7 -0
  676. package/dist/notifications/NotificationBell.js +200 -0
  677. package/dist/notifications/NotificationBell.js.map +7 -0
  678. package/dist/notifications/Toaster.js +24 -0
  679. package/dist/notifications/Toaster.js.map +7 -0
  680. package/dist/notifications/activity-types.js +65 -0
  681. package/dist/notifications/activity-types.js.map +7 -0
  682. package/dist/notifications/bell.js +24 -0
  683. package/dist/notifications/bell.js.map +7 -0
  684. package/dist/notifications/calendar-notifications.js +79 -0
  685. package/dist/notifications/calendar-notifications.js.map +7 -0
  686. package/dist/notifications/index.js +108 -0
  687. package/dist/notifications/index.js.map +7 -0
  688. package/dist/notifications/live.js +28 -0
  689. package/dist/notifications/live.js.map +7 -0
  690. package/dist/notifications/notification-types.js +127 -0
  691. package/dist/notifications/notification-types.js.map +7 -0
  692. package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
  693. package/dist/notifications/notify-store.js.map +7 -0
  694. package/dist/notifications/server-notifications.js +452 -0
  695. package/dist/notifications/server-notifications.js.map +7 -0
  696. package/dist/notifications/useNotifications.js +34 -0
  697. package/dist/notifications/useNotifications.js.map +7 -0
  698. package/dist/offline-store/network.js +11 -0
  699. package/dist/offline-store/network.js.map +7 -0
  700. package/dist/offline-store/store.js +136 -0
  701. package/dist/offline-store/store.js.map +7 -0
  702. package/dist/offline-store/wipe.js +8 -0
  703. package/dist/offline-store/wipe.js.map +7 -0
  704. package/dist/offline.js +58 -0
  705. package/dist/offline.js.map +7 -0
  706. package/dist/people.js +122 -0
  707. package/dist/people.js.map +7 -0
  708. package/dist/projects.js +30 -0
  709. package/dist/projects.js.map +7 -0
  710. package/dist/query-client.js +63 -0
  711. package/dist/query-client.js.map +7 -0
  712. package/dist/{chunk-ZM6N7YZH.js → query-keys.js} +18 -31
  713. package/dist/query-keys.js.map +7 -0
  714. package/dist/query-persist.js +66 -0
  715. package/dist/query-persist.js.map +7 -0
  716. package/dist/queued-writes.js +59 -0
  717. package/dist/queued-writes.js.map +7 -0
  718. package/dist/remote-control.js +67 -0
  719. package/dist/remote-control.js.map +7 -0
  720. package/dist/search/index.js +23 -0
  721. package/dist/search/index.js.map +7 -0
  722. package/dist/search/session.js +58 -0
  723. package/dist/search/session.js.map +7 -0
  724. package/dist/search/useSemanticSearch.js +82 -0
  725. package/dist/search/useSemanticSearch.js.map +7 -0
  726. package/dist/session/chat.js +512 -0
  727. package/dist/session/chat.js.map +7 -0
  728. package/dist/session/documents.js +196 -0
  729. package/dist/session/documents.js.map +7 -0
  730. package/dist/session/drafts.js +103 -0
  731. package/dist/session/drafts.js.map +7 -0
  732. package/dist/session/index.js +123 -0
  733. package/dist/session/index.js.map +7 -0
  734. package/dist/session/layout.js +339 -0
  735. package/dist/session/layout.js.map +7 -0
  736. package/dist/session/persist.js +106 -0
  737. package/dist/session/persist.js.map +7 -0
  738. package/dist/session/session-hooks.js +53 -0
  739. package/dist/session/session-hooks.js.map +7 -0
  740. package/dist/session/signed-in.js +36 -0
  741. package/dist/session/signed-in.js.map +7 -0
  742. package/dist/session/store.js +166 -0
  743. package/dist/session/store.js.map +7 -0
  744. package/dist/session/thread-tabs.js +121 -0
  745. package/dist/session/thread-tabs.js.map +7 -0
  746. package/dist/session/ui-state-storage.js +76 -0
  747. package/dist/session/ui-state-storage.js.map +7 -0
  748. package/dist/session/workspace.js +77 -0
  749. package/dist/session/workspace.js.map +7 -0
  750. package/dist/shell/index.cjs +37 -37
  751. package/dist/shell/index.js +43 -10
  752. package/dist/shell/index.js.map +7 -1
  753. package/dist/skill-pack.js +111 -0
  754. package/dist/skill-pack.js.map +7 -0
  755. package/dist/storage.js +186 -0
  756. package/dist/storage.js.map +7 -0
  757. package/dist/support/index.js +35 -0
  758. package/dist/support/index.js.map +7 -0
  759. package/dist/tags.js +204 -0
  760. package/dist/tags.js.map +7 -0
  761. package/dist/ui/DebouncedInput.js +109 -0
  762. package/dist/ui/DebouncedInput.js.map +7 -0
  763. package/dist/ui/DictateContext.js +8 -0
  764. package/dist/ui/DictateContext.js.map +7 -0
  765. package/dist/ui/IconToggle.js +79 -0
  766. package/dist/ui/IconToggle.js.map +7 -0
  767. package/dist/ui/VerifiedToggle.js +38 -0
  768. package/dist/ui/VerifiedToggle.js.map +7 -0
  769. package/dist/ui/VisibilityToggle.js +103 -0
  770. package/dist/ui/VisibilityToggle.js.map +7 -0
  771. package/dist/ui/avatar.js +40 -0
  772. package/dist/ui/avatar.js.map +7 -0
  773. package/dist/ui/badge.js +28 -0
  774. package/dist/ui/badge.js.map +7 -0
  775. package/dist/ui/button.js +48 -0
  776. package/dist/ui/button.js.map +7 -0
  777. package/dist/ui/card.js +90 -0
  778. package/dist/ui/card.js.map +7 -0
  779. package/dist/ui/checkbox.js +22 -0
  780. package/dist/ui/checkbox.js.map +7 -0
  781. package/dist/ui/collapsible.js +10 -0
  782. package/dist/ui/collapsible.js.map +7 -0
  783. package/dist/ui/command.js +103 -0
  784. package/dist/ui/command.js.map +7 -0
  785. package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
  786. package/dist/ui/dialog.js.map +7 -0
  787. package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
  788. package/dist/ui/dropdown-menu.js.map +7 -0
  789. package/dist/ui/hover-card.js +36 -0
  790. package/dist/ui/hover-card.js.map +7 -0
  791. package/dist/ui/index.cjs +154 -154
  792. package/dist/ui/index.js +290 -10
  793. package/dist/ui/index.js.map +7 -1
  794. package/dist/ui/input.js +65 -0
  795. package/dist/ui/input.js.map +7 -0
  796. package/dist/ui/label.js +16 -0
  797. package/dist/ui/label.js.map +7 -0
  798. package/dist/ui/mark-menu.js +300 -0
  799. package/dist/ui/mark-menu.js.map +7 -0
  800. package/dist/ui/popover.js +40 -0
  801. package/dist/ui/popover.js.map +7 -0
  802. package/dist/ui/portal-container.js +17 -0
  803. package/dist/ui/portal-container.js.map +7 -0
  804. package/dist/ui/progress.js +24 -0
  805. package/dist/ui/progress.js.map +7 -0
  806. package/dist/ui/radio-group.js +29 -0
  807. package/dist/ui/radio-group.js.map +7 -0
  808. package/dist/ui/scroll-area.js +39 -0
  809. package/dist/ui/scroll-area.js.map +7 -0
  810. package/dist/ui/select.js +130 -0
  811. package/dist/ui/select.js.map +7 -0
  812. package/dist/ui/separator.js +23 -0
  813. package/dist/ui/separator.js.map +7 -0
  814. package/dist/ui/slider.js +23 -0
  815. package/dist/ui/slider.js.map +7 -0
  816. package/dist/ui/switch.js +28 -0
  817. package/dist/ui/switch.js.map +7 -0
  818. package/dist/ui/table.js +75 -0
  819. package/dist/ui/table.js.map +7 -0
  820. package/dist/ui/tabs.js +48 -0
  821. package/dist/ui/tabs.js.map +7 -0
  822. package/dist/ui/textarea.js +63 -0
  823. package/dist/ui/textarea.js.map +7 -0
  824. package/dist/ui/toggle-group.js +43 -0
  825. package/dist/ui/toggle-group.js.map +7 -0
  826. package/dist/ui/toggle.js +40 -0
  827. package/dist/ui/toggle.js.map +7 -0
  828. package/dist/ui/tooltip.js +215 -0
  829. package/dist/ui/tooltip.js.map +7 -0
  830. package/dist/usage-metered.js +8 -0
  831. package/dist/usage-metered.js.map +7 -0
  832. package/dist/useArbi.js +16 -0
  833. package/dist/useArbi.js.map +7 -0
  834. package/dist/useInstallSkillPack.js +81 -0
  835. package/dist/useInstallSkillPack.js.map +7 -0
  836. package/dist/usermenu/UserMenu.js +188 -0
  837. package/dist/usermenu/UserMenu.js.map +7 -0
  838. package/dist/usermenu/index.js +5 -0
  839. package/dist/usermenu/index.js.map +7 -0
  840. package/dist/users/index.js +15 -0
  841. package/dist/users/index.js.map +7 -0
  842. package/dist/users/user-display.js +60 -0
  843. package/dist/users/user-display.js.map +7 -0
  844. package/dist/viewers/AudioViewer.js +23 -0
  845. package/dist/viewers/AudioViewer.js.map +7 -0
  846. package/dist/viewers/DocxViewer.js +81 -0
  847. package/dist/viewers/DocxViewer.js.map +7 -0
  848. package/dist/viewers/ImageViewer.js +31 -0
  849. package/dist/viewers/ImageViewer.js.map +7 -0
  850. package/dist/viewers/PdfViewer.js +19 -3
  851. package/dist/viewers/PdfViewer.js.map +7 -1
  852. package/dist/{PdfViewerImpl-TEBYF2QI.js → viewers/PdfViewerImpl.js} +25 -19
  853. package/dist/viewers/PdfViewerImpl.js.map +7 -0
  854. package/dist/viewers/VideoViewer.js +31 -0
  855. package/dist/viewers/VideoViewer.js.map +7 -0
  856. package/dist/viewers/XlsxViewer.js +102 -0
  857. package/dist/viewers/XlsxViewer.js.map +7 -0
  858. package/dist/viewers/index.js +61 -271
  859. package/dist/viewers/index.js.map +7 -1
  860. package/dist/viewers/page-scroll.js +59 -0
  861. package/dist/viewers/page-scroll.js.map +7 -0
  862. package/dist/viewers/pdf-viewer-constants.js +9 -0
  863. package/dist/viewers/pdf-viewer-constants.js.map +7 -0
  864. package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
  865. package/dist/viewers/pdfjs-polyfills.js.map +7 -0
  866. package/dist/viewers/selection-runs.js +38 -0
  867. package/dist/viewers/selection-runs.js.map +7 -0
  868. package/dist/viewers/usePageIntersectionObserver.js +68 -0
  869. package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
  870. package/dist/viewers/useProcessedChunks.js +58 -0
  871. package/dist/viewers/useProcessedChunks.js.map +7 -0
  872. package/dist/viewers/viewer-zoom.js +163 -0
  873. package/dist/viewers/viewer-zoom.js.map +7 -0
  874. package/dist/websocket/ArbiWebSocketProvider.js +207 -0
  875. package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
  876. package/dist/websocket/context.js +14 -0
  877. package/dist/websocket/context.js.map +7 -0
  878. package/dist/websocket/hooks.js +30 -0
  879. package/dist/websocket/hooks.js.map +7 -0
  880. package/dist/websocket/index.js +22 -0
  881. package/dist/websocket/index.js.map +7 -0
  882. package/dist/websocket/live-updates.js +38 -0
  883. package/dist/websocket/live-updates.js.map +7 -0
  884. package/dist/websocket/reconnect.js +13 -0
  885. package/dist/websocket/reconnect.js.map +7 -0
  886. package/dist/websocket/store.js +58 -0
  887. package/dist/websocket/store.js.map +7 -0
  888. package/dist/workforce.js +607 -0
  889. package/dist/workforce.js.map +7 -0
  890. package/dist/workspaces/access-request.js +35 -0
  891. package/dist/workspaces/access-request.js.map +7 -0
  892. package/dist/workspaces/archive.js +59 -0
  893. package/dist/workspaces/archive.js.map +7 -0
  894. package/dist/workspaces/current.js +20 -0
  895. package/dist/workspaces/current.js.map +7 -0
  896. package/dist/workspaces/delete-workspaces.js +15 -0
  897. package/dist/workspaces/delete-workspaces.js.map +7 -0
  898. package/dist/workspaces/export-archive.js +40 -0
  899. package/dist/workspaces/export-archive.js.map +7 -0
  900. package/dist/workspaces/index.js +99 -0
  901. package/dist/workspaces/index.js.map +7 -0
  902. package/dist/workspaces/settings.js +45 -0
  903. package/dist/workspaces/settings.js.map +7 -0
  904. package/dist/workspaces/shell-workspaces.js +49 -0
  905. package/dist/workspaces/shell-workspaces.js.map +7 -0
  906. package/dist/workspaces/switch.js +234 -0
  907. package/dist/workspaces/switch.js.map +7 -0
  908. package/dist/workspaces/transfer.js +170 -0
  909. package/dist/workspaces/transfer.js.map +7 -0
  910. package/dist/workspaces/useShellWorkspaces.js +86 -0
  911. package/dist/workspaces/useShellWorkspaces.js.map +7 -0
  912. package/dist/workspaces/workspace-users.js +65 -0
  913. package/dist/workspaces/workspace-users.js.map +7 -0
  914. package/package.json +4 -4
  915. package/dist/PdfViewerImpl-TEBYF2QI.js.map +0 -1
  916. package/dist/PdfViewerImpl.d-B28hLEuj.d.cts +0 -62
  917. package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
  918. package/dist/annotations/freeze/index.d.cts +0 -205
  919. package/dist/annotations/index.d.cts +0 -360
  920. package/dist/artifacts/index.d.cts +0 -476
  921. package/dist/artifacts/redline-core.d.cts +0 -39
  922. package/dist/bundle-YNOX7VIL.js +0 -5
  923. package/dist/bundle-YNOX7VIL.js.map +0 -1
  924. package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
  925. package/dist/calls/livekit/index.d.cts +0 -280
  926. package/dist/chunk-47CCGUWR.js.map +0 -1
  927. package/dist/chunk-4FL3X3LA.js +0 -2057
  928. package/dist/chunk-4FL3X3LA.js.map +0 -1
  929. package/dist/chunk-6QNBSXCE.js +0 -271
  930. package/dist/chunk-6QNBSXCE.js.map +0 -1
  931. package/dist/chunk-74N436VK.js.map +0 -1
  932. package/dist/chunk-APZZQZ6P.js +0 -147
  933. package/dist/chunk-APZZQZ6P.js.map +0 -1
  934. package/dist/chunk-BF5KW5ZI.js.map +0 -1
  935. package/dist/chunk-DPYBZDJB.js.map +0 -1
  936. package/dist/chunk-DZKRL5H3.js +0 -2766
  937. package/dist/chunk-DZKRL5H3.js.map +0 -1
  938. package/dist/chunk-HDCRPPBW.js +0 -75
  939. package/dist/chunk-HDCRPPBW.js.map +0 -1
  940. package/dist/chunk-L2IPPTVC.js +0 -20
  941. package/dist/chunk-L2IPPTVC.js.map +0 -1
  942. package/dist/chunk-LSU4UPS5.js +0 -1011
  943. package/dist/chunk-LSU4UPS5.js.map +0 -1
  944. package/dist/chunk-NIKPG4PW.js +0 -1128
  945. package/dist/chunk-NIKPG4PW.js.map +0 -1
  946. package/dist/chunk-NNAJLY6B.js +0 -4974
  947. package/dist/chunk-NNAJLY6B.js.map +0 -1
  948. package/dist/chunk-OYPKKHXY.js +0 -559
  949. package/dist/chunk-OYPKKHXY.js.map +0 -1
  950. package/dist/chunk-PTOP7OHG.js.map +0 -1
  951. package/dist/chunk-QMY2JKBI.js +0 -246
  952. package/dist/chunk-QMY2JKBI.js.map +0 -1
  953. package/dist/chunk-SN5YV6FF.js +0 -11
  954. package/dist/chunk-SN5YV6FF.js.map +0 -1
  955. package/dist/chunk-SSXFVWCT.js.map +0 -1
  956. package/dist/chunk-T3USOSVN.js.map +0 -1
  957. package/dist/chunk-T4CLW3DN.js +0 -2560
  958. package/dist/chunk-T4CLW3DN.js.map +0 -1
  959. package/dist/chunk-UW2SGTI5.js.map +0 -1
  960. package/dist/chunk-VSCU7K4V.js.map +0 -1
  961. package/dist/chunk-WL2Y2T47.js.map +0 -1
  962. package/dist/chunk-WUTL62MC.js.map +0 -1
  963. package/dist/chunk-XWPLOFDN.js +0 -644
  964. package/dist/chunk-XWPLOFDN.js.map +0 -1
  965. package/dist/chunk-Y3MTRA7D.js +0 -97
  966. package/dist/chunk-Y3MTRA7D.js.map +0 -1
  967. package/dist/chunk-YNNAJJ5Z.js.map +0 -1
  968. package/dist/chunk-ZM6N7YZH.js.map +0 -1
  969. package/dist/document-tools/core.d.cts +0 -883
  970. package/dist/document-tools/index.d.cts +0 -90
  971. package/dist/index.d-LArLnpI8.d.cts +0 -2036
  972. package/dist/index.d-oR5FKZpJ.d.cts +0 -579
  973. package/dist/index.d.cts +0 -15923
  974. package/dist/lazy-chunk.d-B6YDLMKI.d.cts +0 -31
  975. package/dist/model.d-CNtRWKVK.d.cts +0 -110
  976. package/dist/query-keys.d-B1Am9tIF.d.cts +0 -337
  977. package/dist/shell/index.d.cts +0 -6
  978. package/dist/store.d-GADDvC7w.d.cts +0 -35
  979. package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
  980. package/dist/ui/index.d.cts +0 -26
  981. package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
  982. package/dist/viewers/PdfViewer.d.cts +0 -9
  983. package/dist/viewers/index.d.cts +0 -262
@@ -0,0 +1,419 @@
1
+ import { useCallback } from "react";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ import {
4
+ quotaFromStreamError
5
+ } from "@arbidocs/sdk/browser";
6
+ import { arbiQueryKeys } from "../hooks.js";
7
+ import { useArbi } from "../useArbi.js";
8
+ import { useArbiHost } from "../host/config.js";
9
+ import { refreshDocuments } from "../documents/index.js";
10
+ import { useArbiSessionStore } from "../session/index.js";
11
+ import { invalidateConversationLists, patchConversationList } from "../conversation-list.js";
12
+ import { MIN_QUEUED_MESSAGE_VISIBILITY_MS, queuedMessages } from "./run-state.js";
13
+ import {
14
+ addAssistantMessageToCache,
15
+ addUserMessageToCache,
16
+ appendTokenToMessage,
17
+ applyFinalContextToMessage,
18
+ applyOutputItemToMessage,
19
+ commitFinalMessage,
20
+ completeQueuedUserMessageByContent,
21
+ ensureAssistantMessageLoading,
22
+ flushStreamingTokens,
23
+ getInterjectionText,
24
+ getThreadsQueryKey,
25
+ isMessageRunning,
26
+ markMessageAsFailed,
27
+ markNarrationSettled,
28
+ removeSettledNarration,
29
+ setUserInputRequest,
30
+ threadEndingAtContains,
31
+ updateUserMessageInCache,
32
+ updateUserMessageStateInCache
33
+ } from "./conversation-cache.js";
34
+ import { adoptNewChatDocument } from "./thread-binding.js";
35
+ import { recordChatArtifact } from "./chat-artifacts.js";
36
+ const MIN_NARRATION_DWELL_MS = 4e3;
37
+ const FIRST_TOKEN_MEASURE = "arbi:send-message:first-token";
38
+ function createStreamHandlers(ctx, params) {
39
+ const { queryClient, session, host } = ctx;
40
+ const { streamState, parentMessageId, parentId } = params;
41
+ let turnUserMessageId = null;
42
+ let queuedEntryRetired = false;
43
+ const isViewingConversation = () => session.getState().conversationId === streamState.conversationId;
44
+ const retireQueuedEntry = () => {
45
+ const clientId = streamState.queuedClientId;
46
+ if (!clientId || queuedEntryRetired) return;
47
+ queuedEntryRetired = true;
48
+ const entry = queuedMessages.find(session.getState().queuedMessages, clientId);
49
+ if (!entry) return;
50
+ const remainingVisibility = Math.max(
51
+ 0,
52
+ MIN_QUEUED_MESSAGE_VISIBILITY_MS - (Date.now() - entry.createdAt)
53
+ );
54
+ if (remainingVisibility === 0) {
55
+ session.removeQueuedMessage(clientId);
56
+ } else {
57
+ setTimeout(() => session.removeQueuedMessage(clientId), remainingVisibility);
58
+ }
59
+ };
60
+ const handleUserMessage = (userMessage) => {
61
+ console.debug("[SSE] user_message:", userMessage.external_id, userMessage.status);
62
+ const serverConversationId = userMessage.conversation_ext_id;
63
+ if (serverConversationId && streamState.conversationId === "new") {
64
+ streamState.conversationId = serverConversationId;
65
+ session.moveConversation("new", serverConversationId);
66
+ const userExtId = ctx.userId();
67
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
68
+ patchConversationList(
69
+ queryClient,
70
+ streamState.workspaceId ?? session.getState().workspaceId,
71
+ (old) => old.some((c) => c.external_id === serverConversationId) ? old : [
72
+ {
73
+ external_id: serverConversationId,
74
+ title: null,
75
+ created_by_ext_id: userExtId,
76
+ updated_by_ext_id: null,
77
+ created_at: nowIso,
78
+ updated_at: nowIso,
79
+ is_shared: false,
80
+ message_count: 1,
81
+ last_message_status: "in_progress"
82
+ },
83
+ ...old
84
+ ]
85
+ );
86
+ adoptNewChatDocument(
87
+ session,
88
+ queryClient,
89
+ serverConversationId,
90
+ streamState.threadDocumentId ?? null
91
+ );
92
+ }
93
+ const { type: _type, ...messageData } = userMessage;
94
+ const userMsg = { ...messageData, isLoading: true };
95
+ if (userMessage.status === "queued") {
96
+ streamState.queuedUserMessageId = userMessage.external_id;
97
+ }
98
+ const updated = updateUserMessageInCache(queryClient, streamState.conversationId, userMsg);
99
+ if (!updated) {
100
+ addUserMessageToCache(queryClient, streamState.conversationId, userMsg, {
101
+ parentId,
102
+ parentMessageId,
103
+ currentParentMessageId: session.getState().cursor
104
+ });
105
+ }
106
+ turnUserMessageId = userMessage.external_id;
107
+ streamState.userMessageId = userMessage.external_id;
108
+ if (streamState.queuedContinuation) {
109
+ retireQueuedEntry();
110
+ const viewedLeaf = session.getState().cursor;
111
+ if (isViewingConversation() && viewedLeaf && threadEndingAtContains(
112
+ queryClient,
113
+ streamState.conversationId,
114
+ userMessage.external_id,
115
+ viewedLeaf
116
+ )) {
117
+ session.setCursor(userMessage.external_id);
118
+ }
119
+ }
120
+ };
121
+ const handleMessageQueued = (data) => {
122
+ if (!streamState.queuedContinuation && data.response_id && !streamState.assistantId) {
123
+ streamState.assistantId = data.response_id;
124
+ session.setStreamingAssistantId(streamState.conversationId, data.response_id);
125
+ }
126
+ streamState.queuedUserMessageId = data.user_message?.external_id ?? data.user_message_id ?? streamState.queuedUserMessageId;
127
+ if (streamState.queuedClientId) {
128
+ session.acknowledgeQueuedMessage(streamState.queuedClientId, streamState.queuedUserMessageId);
129
+ }
130
+ };
131
+ const handleStreamStart = (streamStart) => {
132
+ console.debug("[SSE] stream_start:", streamStart.assistant_message_ext_id);
133
+ streamState.hasStreamStarted = true;
134
+ if (streamState.queuedUserMessageId) {
135
+ updateUserMessageStateInCache(
136
+ queryClient,
137
+ streamState.conversationId,
138
+ streamState.queuedUserMessageId,
139
+ "completed",
140
+ false
141
+ );
142
+ }
143
+ if (streamState.queuedContinuation) {
144
+ retireQueuedEntry();
145
+ if (streamState.queueOwnerAssistantId) {
146
+ session.moveQueuedMessages(
147
+ streamState.queueOwnerAssistantId,
148
+ streamStart.assistant_message_ext_id
149
+ );
150
+ }
151
+ }
152
+ if (streamState.queuedContinuation) {
153
+ session.setConversationGenerating(
154
+ streamState.conversationId,
155
+ true,
156
+ streamState.abortController
157
+ );
158
+ }
159
+ streamState.assistantId = streamStart.assistant_message_ext_id;
160
+ session.setStreamingAssistantId(
161
+ streamState.conversationId,
162
+ streamStart.assistant_message_ext_id
163
+ );
164
+ const assistantMsg = {
165
+ role: "assistant",
166
+ content: "",
167
+ external_id: streamState.assistantId,
168
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
169
+ config_ext_id: null,
170
+ created_by_ext_id: "",
171
+ conversation_ext_id: streamState.conversationId,
172
+ tokens: 0,
173
+ status: "in_progress",
174
+ isLoading: true
175
+ };
176
+ const placed = addAssistantMessageToCache(
177
+ queryClient,
178
+ streamState.conversationId,
179
+ assistantMsg,
180
+ turnUserMessageId ?? streamState.queuedUserMessageId
181
+ );
182
+ if (!placed) {
183
+ const conversationId = streamState.conversationId;
184
+ const answerId = streamStart.assistant_message_ext_id;
185
+ void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) }).then(() => {
186
+ if (streamState.assistantId === answerId && !streamState.isStopped() && isMessageRunning(queryClient, conversationId, answerId))
187
+ ensureAssistantMessageLoading(queryClient, conversationId, answerId);
188
+ });
189
+ }
190
+ void invalidateConversationLists(queryClient);
191
+ session.setCursor(streamState.assistantId);
192
+ };
193
+ let firstTokenSeen = false;
194
+ const markFirstToken = () => {
195
+ if (firstTokenSeen) return;
196
+ firstTokenSeen = true;
197
+ try {
198
+ performance.mark("arbi:send-message:first-token");
199
+ if (performance.getEntriesByName("arbi:send-message:start", "mark").length > 0)
200
+ performance.measure(
201
+ "arbi:send-message:first-token",
202
+ "arbi:send-message:start",
203
+ "arbi:send-message:first-token"
204
+ );
205
+ } catch {
206
+ }
207
+ };
208
+ const handleToken = (tokenContent) => {
209
+ if (!streamState.assistantId) return;
210
+ markFirstToken();
211
+ appendTokenToMessage(
212
+ queryClient,
213
+ streamState.conversationId,
214
+ streamState.assistantId,
215
+ tokenContent
216
+ );
217
+ };
218
+ const handleOutputTextDelta = (data) => {
219
+ if (!streamState.assistantId) return;
220
+ markFirstToken();
221
+ if (streamState.pivotedSinceProse) {
222
+ streamState.pivotedSinceProse = false;
223
+ markNarrationSettled(queryClient, streamState.conversationId, streamState.assistantId);
224
+ }
225
+ appendTokenToMessage(
226
+ queryClient,
227
+ streamState.conversationId,
228
+ streamState.assistantId,
229
+ data.delta
230
+ );
231
+ };
232
+ const resolveNotBefore = () => streamState.lastNarrationSettledAt === 0 ? 0 : streamState.lastNarrationSettledAt + MIN_NARRATION_DWELL_MS;
233
+ const handleMetadata = (metadata) => {
234
+ console.debug("[SSE] message_metadata:", metadata.external_id);
235
+ const serverAssistantId = metadata.external_id;
236
+ const viewedLeaf = session.getState().cursor;
237
+ const viewingNewerLeaf = !!viewedLeaf && threadEndingAtContains(queryClient, streamState.conversationId, viewedLeaf, serverAssistantId);
238
+ if (isViewingConversation() && !viewingNewerLeaf) {
239
+ session.setCursor(serverAssistantId);
240
+ }
241
+ if (metadata.suggested_query) {
242
+ session.setSuggestedQuery({
243
+ conversationExtId: streamState.conversationId,
244
+ text: metadata.suggested_query
245
+ });
246
+ }
247
+ if (streamState.assistantId) {
248
+ const { type: _type, ...messageData } = metadata;
249
+ commitFinalMessage(
250
+ queryClient,
251
+ streamState.conversationId,
252
+ streamState.assistantId,
253
+ messageData,
254
+ resolveNotBefore()
255
+ );
256
+ }
257
+ };
258
+ const handleOutputItemDone = (ev) => {
259
+ if (!streamState.assistantId) return;
260
+ const item = ev.item;
261
+ const interjection = getInterjectionText(item);
262
+ if (interjection) {
263
+ completeQueuedUserMessageByContent(queryClient, streamState.conversationId, interjection);
264
+ session.consumeQueuedMessage(streamState.assistantId, interjection);
265
+ }
266
+ const isAnswerMessage = item.arbi?.step === "answering" || item.arbi?.label === "Answered";
267
+ if (item.type === "message" && !isAnswerMessage && item.arbi?.label === "Narration") {
268
+ removeSettledNarration(
269
+ queryClient,
270
+ streamState.conversationId,
271
+ streamState.assistantId,
272
+ item.content
273
+ );
274
+ } else if (item.type === "message" && !isAnswerMessage) {
275
+ streamState.lastNarrationSettledAt = Date.now();
276
+ }
277
+ if (item.type === "function_call") {
278
+ streamState.pivotedSinceProse = true;
279
+ const tool = item.name || item.arbi?.detail?.[0]?.tool || "";
280
+ if (tool === "create_fact" || tool === "label_facts") {
281
+ streamState.factsTouched = true;
282
+ }
283
+ }
284
+ applyOutputItemToMessage(queryClient, streamState.conversationId, streamState.assistantId, ev);
285
+ };
286
+ const handleUserInputRequest = (request) => {
287
+ if (!streamState.assistantId) return;
288
+ setUserInputRequest(queryClient, streamState.conversationId, streamState.assistantId, request);
289
+ };
290
+ const handleProbeAnswer = (probe) => {
291
+ if (!streamState.assistantId) return;
292
+ session.setAgentProbeAnswer(streamState.assistantId, probe);
293
+ };
294
+ const handleDeferredInterjection = (data) => {
295
+ if (!data.message) return;
296
+ streamState.deferredInterjections.push(data.message);
297
+ };
298
+ const handleAgentControlState = (event) => {
299
+ if (!streamState.assistantId) return;
300
+ session.setAgentControlState(streamState.assistantId, event.state);
301
+ };
302
+ const handleMailDraft = (draft) => host.onMailDraft?.(draft);
303
+ const handleArtifact = (artifact) => {
304
+ console.info("[SSE] Received artifact event:", {
305
+ doc_ext_id: artifact.doc_ext_id,
306
+ title: artifact.title,
307
+ is_complete: artifact.is_complete
308
+ });
309
+ recordChatArtifact(artifact, streamState.conversationId);
310
+ host.onArtifact?.(artifact, streamState.conversationId);
311
+ if (artifact.is_complete) {
312
+ const documents = session.getState().conversationDocuments[streamState.conversationId] ?? [];
313
+ if (!documents.some((d) => d.docId === artifact.doc_ext_id))
314
+ session.setConversationDocuments(streamState.conversationId, [
315
+ ...documents,
316
+ { docId: artifact.doc_ext_id, isPinned: false }
317
+ ]);
318
+ if (artifact.mode === "html" || artifact.mode === "react")
319
+ session.setPinnedDocumentId(artifact.doc_ext_id);
320
+ ctx.refreshDocuments([artifact.doc_ext_id]).catch(() => {
321
+ });
322
+ }
323
+ };
324
+ const handleElapsedTime = (t) => {
325
+ session.setBackendElapsed(streamState.conversationId, t);
326
+ };
327
+ const handleContextUpdate = (context) => {
328
+ if (!streamState.assistantId) return;
329
+ applyFinalContextToMessage(
330
+ queryClient,
331
+ streamState.conversationId,
332
+ streamState.assistantId,
333
+ context
334
+ );
335
+ };
336
+ const handleError = (error) => {
337
+ if (streamState.isStopped()) return;
338
+ console.error("Stream error:", error);
339
+ if (streamState.queuedContinuation && !streamState.hasStreamStarted) {
340
+ streamState.queuedFailed = true;
341
+ }
342
+ const quota = quotaFromStreamError(error);
343
+ if (quota) host.onQuotaExceeded?.(quota);
344
+ if (error instanceof Error) return;
345
+ streamState.serverError = String(error);
346
+ if (streamState.assistantId) {
347
+ markMessageAsFailed(queryClient, streamState.conversationId, streamState.assistantId);
348
+ }
349
+ };
350
+ const handleComplete = () => {
351
+ console.debug("[SSE] Stream complete");
352
+ const generation = session.getState().generating[streamState.conversationId];
353
+ if (streamState.isStopped() || generation?.isGenerating === false) {
354
+ void queryClient.invalidateQueries({
355
+ queryKey: getThreadsQueryKey(streamState.conversationId)
356
+ });
357
+ }
358
+ flushStreamingTokens(queryClient);
359
+ if (streamState.assistantId) {
360
+ session.clearAgentControl(streamState.assistantId);
361
+ }
362
+ if (streamState.factsTouched) {
363
+ streamState.factsTouched = false;
364
+ queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allFacts(), refetchType: "all" });
365
+ queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allTags(), refetchType: "all" });
366
+ }
367
+ };
368
+ return {
369
+ onMessageQueued: handleMessageQueued,
370
+ onUserMessage: handleUserMessage,
371
+ onStreamStart: handleStreamStart,
372
+ onToken: handleToken,
373
+ onMetadata: handleMetadata,
374
+ onOutputItemDone: handleOutputItemDone,
375
+ onOutputTextDelta: handleOutputTextDelta,
376
+ onUserInputRequest: handleUserInputRequest,
377
+ onProbeAnswer: handleProbeAnswer,
378
+ onDeferredInterjection: handleDeferredInterjection,
379
+ onAgentControlState: handleAgentControlState,
380
+ onArtifact: handleArtifact,
381
+ onMailDraft: handleMailDraft,
382
+ onElapsedTime: handleElapsedTime,
383
+ onContextUpdate: handleContextUpdate,
384
+ onError: handleError,
385
+ onComplete: handleComplete
386
+ };
387
+ }
388
+ function useStreamHandlers() {
389
+ const queryClient = useQueryClient();
390
+ const session = useArbiSessionStore();
391
+ const config = useArbiHost();
392
+ const arbi = useArbi();
393
+ return useCallback(
394
+ (params) => createStreamHandlers(
395
+ {
396
+ queryClient,
397
+ session,
398
+ host: config.chat ?? {},
399
+ userId: () => {
400
+ try {
401
+ return arbi.user.identity()?.externalId ?? "";
402
+ } catch {
403
+ return "";
404
+ }
405
+ },
406
+ refreshDocuments: (ids) => refreshDocuments(queryClient, arbi, ids)
407
+ },
408
+ params
409
+ ),
410
+ [queryClient, session, config, arbi]
411
+ );
412
+ }
413
+ export {
414
+ FIRST_TOKEN_MEASURE,
415
+ MIN_NARRATION_DWELL_MS,
416
+ createStreamHandlers,
417
+ useStreamHandlers
418
+ };
419
+ //# sourceMappingURL=stream-handlers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/chat/stream-handlers.ts"],
4
+ "sourcesContent": ["/**\n * The chat engine's stream handlers: what each frame of an assistant turn does to the conversation\n * cache (`conversation-cache`), the session (`ArbiSessionState`: generation, cursor, queued\n * follow-ups, run control) and the host (`ArbiHostConfig.chat`: documents shown, mail drafts, used-up\n * quota). `createStreamHandlers` builds one set per stream, sharing that stream's mutable state\n * (its conversation id moves from `new` to the server's, its answer id arrives with\n * `response.created`).\n */\n\nimport { useCallback } from 'react'\nimport { useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport {\n quotaFromStreamError,\n type AgentControlStateEvent,\n type ArtifactEvent,\n type ChatMessage as Message,\n type ConversationResponse as Conversation,\n type DeferredInterjectionEvent,\n type MailDraftSSEEvent,\n type MessageMetadataPayload,\n type MessageQueuedEvent,\n type OutputItemDone,\n type ProbeAnswerEvent,\n type SSEStreamStartData,\n type TokenBudgetContext,\n type UserInputRequestEvent,\n type UserMessageEvent,\n} from '@arbidocs/sdk/browser'\nimport { arbiQueryKeys } from '../hooks'\nimport { useArbi } from '../useArbi'\nimport { useArbiHost } from '../host/config'\nimport { refreshDocuments } from '../documents'\nimport { useArbiSessionStore } from '../session'\nimport type { ArbiSessionStore } from '../session/store'\nimport { invalidateConversationLists, patchConversationList } from '../conversation-list'\nimport type { ArbiChatHost } from './host'\nimport { MIN_QUEUED_MESSAGE_VISIBILITY_MS, queuedMessages } from './run-state'\nimport {\n addAssistantMessageToCache,\n addUserMessageToCache,\n appendTokenToMessage,\n applyFinalContextToMessage,\n applyOutputItemToMessage,\n commitFinalMessage,\n completeQueuedUserMessageByContent,\n ensureAssistantMessageLoading,\n flushStreamingTokens,\n getInterjectionText,\n getThreadsQueryKey,\n isMessageRunning,\n markMessageAsFailed,\n markNarrationSettled,\n removeSettledNarration,\n setUserInputRequest,\n threadEndingAtContains,\n updateUserMessageInCache,\n updateUserMessageStateInCache,\n} from './conversation-cache'\nimport { adoptNewChatDocument } from './thread-binding'\nimport { recordChatArtifact } from './chat-artifacts'\n\n/**\n * How long freshly-arrived narration must stay readable on screen before the\n * turn's one resolving commit is allowed to remove it.\n *\n * The whole point is that the user can READ what the agent narrated. If a\n * narration line settles a few hundred ms before the answer completes, resolving\n * immediately would flash that line away \u2014 the original complaint, in a new\n * costume. So the commit that hands the window to the answer waits until the\n * newest narration has had this long on screen.\n *\n * 4000 ms, set from measurement rather than taste. A live turn (see\n * answer-resolves.visual.spec) narrated \"Now I'll open and read the most relevant\n * document \u2014 test-case.pdf (PDF)\" \u2014 13 words, ~3.9 s of reading at a normal\n * 200-250 wpm \u2014 and the answer began almost immediately after it. At a 2500 ms\n * dwell that sentence measured 2446 ms on screen: not comfortably readable.\n *\n * Being generous is close to free: the answer streams in BELOW the narration\n * while it dwells, so nothing is hidden or delayed \u2014 and in the common case the\n * answer takes longer than this to stream, so the wait is already over when\n * `response.completed` lands and the delay is exactly zero.\n *\n * (Formerly MIN_PREAMBLE_DWELL_MS. Same 4 s, same purpose; renamed because there\n * is no \"preamble\" any more \u2014 nothing is folded out of the window mid-turn.)\n */\nexport const MIN_NARRATION_DWELL_MS = 4000\n\n/** The measure of the time to an answer's first token (from the send's `arbi:send-message:start`). */\nexport const FIRST_TOKEN_MEASURE = 'arbi:send-message:first-token'\n\nexport interface StreamHandlers {\n onMessageQueued: (data: MessageQueuedEvent) => void\n onUserMessage: (msg: UserMessageEvent) => void\n onStreamStart: (msg: SSEStreamStartData) => void\n onToken: (content: string) => void\n onMetadata: (msg: MessageMetadataPayload) => void\n onOutputItemDone: (ev: OutputItemDone) => void\n onOutputTextDelta: (data: { item_id: string; delta: string }) => void\n onUserInputRequest: (request: UserInputRequestEvent) => void\n onProbeAnswer: (probe: ProbeAnswerEvent) => void\n onDeferredInterjection: (data: DeferredInterjectionEvent) => void\n onAgentControlState: (event: AgentControlStateEvent) => void\n onArtifact: (artifact: ArtifactEvent) => void\n onMailDraft: (draft: MailDraftSSEEvent) => void\n onElapsedTime: (t: number) => void\n onContextUpdate: (context: TokenBudgetContext) => void\n onError: (error: unknown) => void\n onComplete: () => void\n}\n\n/** The mutable state of one stream, shared by its handlers and the send that started it. */\nexport interface StreamState {\n conversationId: string\n /**\n * The workspace the turn is in (captured when it started; the server's if it moved the turn to\n * its thread's). A new conversation joins this workspace's list, whatever the session is on now.\n */\n workspaceId?: string | null\n assistantId: string | null\n /**\n * Epoch ms when the newest narration block settled \u2014 the dwell clock's start. 0 while the turn\n * has narrated nothing, which is the honest answer to \"how long must this stay readable\": no time\n * at all.\n */\n lastNarrationSettledAt: number\n /**\n * The model has pivoted to a tool call and not yet resumed prose. The next prose therefore opens\n * a new narration and closes the previous one \u2014 the only reliable paragraph boundary, since one\n * sentence can span several message items.\n */\n pivotedSinceProse: boolean\n /**\n * Steering messages the backend deferred because they landed after the agent had committed to\n * its answer. Collected during the stream and resubmitted as a new turn once it completes.\n */\n deferredInterjections: string[]\n queuedContinuation: boolean\n queuedUserMessageId: string | null\n hasStreamStarted: boolean\n /** The backend refused a queued follow-up before its turn started. */\n queuedFailed: boolean\n abortController: AbortController\n /**\n * The person pressed Stop on this turn. Stop cancels the run on the server first, and that can\n * drop this connection before the local abort lands: a stopped turn must not then be recorded as\n * a failed one.\n */\n isStopped: () => boolean\n queueOwnerAssistantId: string | null\n queuedClientId: string | null\n /**\n * A memory tool (`create_fact` / `label_facts`) ran this turn, so the Facts table and the\n * workspace label vocabulary may have changed on the server. The tags query never auto-refetches\n * (staleTime: Infinity), so both are refreshed when the turn completes rather than making the\n * person reload the page to see a label the model just created.\n */\n factsTouched: boolean\n /**\n * The document the turn's thread is bound to, sent with it: a new chat's binding becomes the\n * conversation's once the server names it.\n */\n threadDocumentId?: string | null\n /** The server confirmed this turn's user message: it is stored, so the turn exists there. */\n userMessageId?: string | null\n /**\n * The server's own failure report (`response.failed` / `arbi.error` / an HTTP error), as opposed\n * to a dropped connection, which does not end the run on the server.\n */\n serverError?: string | null\n}\n\n/** What the handlers write to besides the cache. */\nexport interface StreamHandlerContext {\n queryClient: QueryClient\n session: ArbiSessionStore\n host: ArbiChatHost\n /** The signed-in user (the owner of a conversation this stream creates). */\n userId: () => string\n /** Re-read documents a turn wrote, into every documents cache. */\n refreshDocuments: (docIds: string[]) => Promise<unknown>\n}\n\nexport interface StreamHandlerParams {\n streamState: StreamState\n /** The message the send continued from (the cursor when it was sent). */\n parentMessageId: string | null\n /** The message the turn replies to. */\n parentId?: string | null\n}\n\n/** One stream's handlers. */\nexport function createStreamHandlers(\n ctx: StreamHandlerContext,\n params: StreamHandlerParams\n): StreamHandlers {\n const { queryClient, session, host } = ctx\n const { streamState, parentMessageId, parentId } = params\n\n // The user message this turn answers, as the server placed it.\n let turnUserMessageId: string | null = null\n let queuedEntryRetired = false\n\n const isViewingConversation = () =>\n session.getState().conversationId === streamState.conversationId\n\n /**\n * Take this follow-up out of the agent bar's queue box: the server has confirmed it\n * as a message of its own. The bubble in the thread shows it from here on. A follow-up\n * the server answers this fast still stays readable for a moment.\n */\n const retireQueuedEntry = () => {\n const clientId = streamState.queuedClientId\n if (!clientId || queuedEntryRetired) return\n queuedEntryRetired = true\n const entry = queuedMessages.find(session.getState().queuedMessages, clientId)\n if (!entry) return\n const remainingVisibility = Math.max(\n 0,\n MIN_QUEUED_MESSAGE_VISIBILITY_MS - (Date.now() - entry.createdAt)\n )\n if (remainingVisibility === 0) {\n session.removeQueuedMessage(clientId)\n } else {\n setTimeout(() => session.removeQueuedMessage(clientId), remainingVisibility)\n }\n }\n\n const handleUserMessage = (userMessage: UserMessageEvent) => {\n console.debug('[SSE] user_message:', userMessage.external_id, userMessage.status)\n\n const serverConversationId = userMessage.conversation_ext_id\n\n // Handle conversation ID transition from 'new' to real conversation\n if (serverConversationId && streamState.conversationId === 'new') {\n streamState.conversationId = serverConversationId\n\n // Its generation, documents, facts and tab move to the server id, and it stays open.\n session.moveConversation('new', serverConversationId)\n\n // Append a synthetic row to the conversations list so the sidebar /\n // ConversationList shows it immediately. We initialize every field\n // we know of so column readers (message count cell, last-message\n // status cell, owner cell) don't render `undefined`. Fields the\n // server may add later (generated title, message_count once the\n // first assistant message lands) get corrected when the user opens\n // the conversation (which fetches its detail) or by subsequent\n // events that touch the same conversation.\n const userExtId = ctx.userId()\n const nowIso = new Date().toISOString()\n patchConversationList(\n queryClient,\n streamState.workspaceId ?? session.getState().workspaceId,\n (old) =>\n old.some((c) => c.external_id === serverConversationId)\n ? old\n : [\n {\n external_id: serverConversationId,\n title: null,\n created_by_ext_id: userExtId,\n updated_by_ext_id: null,\n created_at: nowIso,\n updated_at: nowIso,\n is_shared: false,\n message_count: 1,\n last_message_status: 'in_progress',\n } as Conversation,\n ...old,\n ]\n )\n // The server bound it with this turn (a chat about a document): the row says so at once.\n adoptNewChatDocument(\n session,\n queryClient,\n serverConversationId,\n streamState.threadDocumentId ?? null\n )\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type: _type, ...messageData } = userMessage\n // Mark the freshly-arrived user message as in-flight (isLoading=true)\n // so getOrphanedLastMessage suppresses the red \"Response Incomplete\"\n // banner during the brief gap between this event and the assistant's\n // stream_start. clearLoadingState (called when streams end / fail)\n // clears it back. Backend-loaded historical messages don't get this\n // flag, so genuine orphans from prior sessions still surface.\n const userMsg: Message = { ...messageData, isLoading: true }\n\n if (userMessage.status === 'queued') {\n streamState.queuedUserMessageId = userMessage.external_id\n }\n\n // If the message was already added from arbi.message_queued (with status=queued),\n // update it in-place (e.g., status \u2192 completed) instead of duplicating.\n const updated = updateUserMessageInCache(queryClient, streamState.conversationId, userMsg)\n if (!updated) {\n // Placed under the server's parent (userMessage.parent_message_ext_id) when the\n // cache has it, so queued follow-ups line up one after another.\n addUserMessageToCache(queryClient, streamState.conversationId, userMsg, {\n parentId,\n parentMessageId,\n currentParentMessageId: session.getState().cursor,\n })\n }\n turnUserMessageId = userMessage.external_id\n streamState.userMessageId = userMessage.external_id\n\n if (streamState.queuedContinuation) {\n retireQueuedEntry()\n // Follow the thread to its newest turn: when the follow-up extends the line being\n // viewed, view the line that now ends at it, not the sibling it would otherwise be.\n const viewedLeaf = session.getState().cursor\n if (\n isViewingConversation() &&\n viewedLeaf &&\n threadEndingAtContains(\n queryClient,\n streamState.conversationId,\n userMessage.external_id,\n viewedLeaf\n )\n ) {\n session.setCursor(userMessage.external_id)\n }\n }\n }\n\n const handleMessageQueued = (data: MessageQueuedEvent) => {\n // The queued acknowledgement precedes response.created but already has\n // the canonical assistant response ID. Seed the generation state now so\n // the docked agent bar appears with the user message instead of popping\n // in later. A queued continuation belongs to the existing parent bar, so\n // never replace its ID with the acknowledgement's throwaway response ID.\n if (!streamState.queuedContinuation && data.response_id && !streamState.assistantId) {\n streamState.assistantId = data.response_id\n session.setStreamingAssistantId(streamState.conversationId, data.response_id)\n }\n streamState.queuedUserMessageId =\n data.user_message?.external_id ?? data.user_message_id ?? streamState.queuedUserMessageId\n if (streamState.queuedClientId) {\n session.acknowledgeQueuedMessage(streamState.queuedClientId, streamState.queuedUserMessageId)\n }\n }\n\n const handleStreamStart = (streamStart: SSEStreamStartData) => {\n console.debug('[SSE] stream_start:', streamStart.assistant_message_ext_id)\n\n streamState.hasStreamStarted = true\n if (streamState.queuedUserMessageId) {\n updateUserMessageStateInCache(\n queryClient,\n streamState.conversationId,\n streamState.queuedUserMessageId,\n 'completed',\n false\n )\n }\n if (streamState.queuedContinuation) {\n retireQueuedEntry()\n // Follow-ups still waiting were queued on the turn that just finished; they now\n // wait on this one, so show them in its bar.\n if (streamState.queueOwnerAssistantId) {\n session.moveQueuedMessages(\n streamState.queueOwnerAssistantId,\n streamStart.assistant_message_ext_id\n )\n }\n }\n\n if (streamState.queuedContinuation) {\n session.setConversationGenerating(\n streamState.conversationId,\n true,\n streamState.abortController\n )\n }\n\n streamState.assistantId = streamStart.assistant_message_ext_id\n\n // The session holds the answer's id, so interjections and Stop can name it.\n session.setStreamingAssistantId(\n streamState.conversationId,\n streamStart.assistant_message_ext_id\n )\n\n const assistantMsg: Message = {\n role: 'assistant',\n content: '',\n external_id: streamState.assistantId,\n created_at: new Date().toISOString(),\n config_ext_id: null,\n created_by_ext_id: '',\n conversation_ext_id: streamState.conversationId,\n tokens: 0,\n status: 'in_progress',\n isLoading: true,\n }\n\n const placed = addAssistantMessageToCache(\n queryClient,\n streamState.conversationId,\n assistantMsg,\n turnUserMessageId ?? streamState.queuedUserMessageId\n )\n if (!placed) {\n // The answer's user message is not in the cache, so the answer could not be placed\n // after it. Re-read the thread for the server's order, then mark the row as streaming\n // again (the refetched row has no local loading flag).\n const conversationId = streamState.conversationId\n const answerId = streamStart.assistant_message_ext_id\n void queryClient\n .invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n .then(() => {\n if (\n streamState.assistantId === answerId &&\n !streamState.isStopped() &&\n isMessageRunning(queryClient, conversationId, answerId)\n )\n ensureAssistantMessageLoading(queryClient, conversationId, answerId)\n })\n }\n\n // The turn's user and assistant messages are stored now, so the list's Messages count\n // must include them while the answer generates (it is re-read again on completion).\n void invalidateConversationLists(queryClient)\n\n // The backend persists the assistant message at response.created,\n // so this ID is permanent and safe to use for chaining.\n session.setCursor(streamState.assistantId)\n }\n\n let firstTokenSeen = false\n const markFirstToken = () => {\n if (firstTokenSeen) return\n firstTokenSeen = true\n // Time to first token, from the send's own mark (the host reports the measure).\n try {\n performance.mark('arbi:send-message:first-token')\n if (performance.getEntriesByName('arbi:send-message:start', 'mark').length > 0)\n performance.measure(\n 'arbi:send-message:first-token',\n 'arbi:send-message:start',\n 'arbi:send-message:first-token'\n )\n } catch {\n // No performance timeline here: nothing to measure.\n }\n }\n\n // Raw tokens (non-agent LLM / fallback) \u2014 no item id. Stream straight through.\n const handleToken = (tokenContent: string) => {\n if (!streamState.assistantId) return\n markFirstToken()\n appendTokenToMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n tokenContent\n )\n }\n\n // A message output_item streaming its text (#2075). Every delta is APPENDED,\n // rendered provisionally (faded \u2014 see Message.tsx), until `response.completed`\n // says which of it was the answer. The one removal mid-turn is an item the\n // server settles as Narration (see handleOutputItemDone).\n //\n // There is deliberately no attempt to spot the answer mid-stream. The\n // previous design guessed (\"a new text block, once a tool call has settled,\n // is the answer\") and was wrong by construction: a turn may make any number\n // of tool calls, so every intermediate block after the first tool call was\n // mis-called. It survived only because the correcting event usually landed\n // inside the dwell \u2014 a race, not correctness.\n //\n // Deltas are appended VERBATIM, with no separator injected at item\n // boundaries. An item boundary is not an utterance boundary: the backend\n // settles the open narration item whenever it needs to emit a tool event,\n // which routinely splits one sentence across several items. A real captured\n // run shows the three items \"I've\" / \" started two background research tasks\n // \u2026for both Apple and\" / \" Microsoft. Let me collect those results now.\\n\\n\" \u2014\n // one sentence in three parts. Injecting a blank line per item would break\n // that into three mangled paragraphs. The model supplies its own line breaks\n // (note the trailing \"\\n\\n\" ending the utterance above), so plain appending\n // reproduces exactly the layout it intended: one line per utterance.\n const handleOutputTextDelta = (data: { item_id: string; delta: string }) => {\n if (!streamState.assistantId) return\n markFirstToken()\n // Prose resuming after a tool call is a NEW narration, not a continuation\n // of the one before it. Close the previous one here rather than when it\n // settled: only now is it known that the model went away and came back,\n // which is what makes this a paragraph boundary and what makes the prose\n // above it superseded.\n if (streamState.pivotedSinceProse) {\n streamState.pivotedSinceProse = false\n markNarrationSettled(queryClient, streamState.conversationId, streamState.assistantId)\n }\n appendTokenToMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n data.delta\n )\n }\n\n /**\n * The earliest moment the turn may resolve: a full dwell after the newest\n * narration settled. Zero when the turn narrated nothing \u2014 there is no prose\n * to protect, so a one-shot answer resolves the instant it completes.\n */\n const resolveNotBefore = () =>\n streamState.lastNarrationSettledAt === 0\n ? 0\n : streamState.lastNarrationSettledAt + MIN_NARRATION_DWELL_MS\n\n const handleMetadata = (metadata: MessageMetadataPayload) => {\n console.debug('[SSE] message_metadata:', metadata.external_id)\n\n const serverAssistantId = metadata.external_id\n\n // Update parentMessageId with the server-confirmed ID, but only if the user\n // is still viewing this conversation. Without this guard, metadata arriving from\n // a background stream would overwrite the active tab's parentMessageId.\n // A follow-up queued behind this turn may already extend the thread past it: keep\n // viewing that newer leaf rather than stepping back to this answer.\n const viewedLeaf = session.getState().cursor\n const viewingNewerLeaf =\n !!viewedLeaf &&\n threadEndingAtContains(queryClient, streamState.conversationId, viewedLeaf, serverAssistantId)\n if (isViewingConversation() && !viewingNewerLeaf) {\n session.setCursor(serverAssistantId)\n }\n\n // Backend-suggested follow-up (SUGGESTED_QUERIES config) \u2014 stashed\n // keyed to its conversation; the composer offers it as a chip.\n if (metadata.suggested_query) {\n session.setSuggestedQuery({\n conversationExtId: streamState.conversationId,\n text: metadata.suggested_query,\n })\n }\n\n if (streamState.assistantId) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type: _type, ...messageData } = metadata\n\n // `response.completed` is the ONLY place the main window resolves, and it\n // resolves in ONE commit: metadata.content is the authoritative answer\n // (the backend's _answer_final persists the answer alone, no narration),\n // it carries the citation offsets computed against that exact string, and\n // it clears `isLoading` so the body stops rendering provisionally.\n //\n // Doing all three together is the fix for the jitter: the answer used to\n // re-render un-faded with its footnotes, and the narration used to leave\n // the body on a separate timer, so the window reflowed twice in quick\n // succession. One commit, one reflow.\n commitFinalMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n messageData,\n resolveNotBefore()\n )\n }\n }\n\n // A settled output_item (#2075). Every item folds into the trace via the\n // reducer \u2014 including narration, which is why the body can drop narration's\n // text without losing it. Narration is the only text that leaves the body\n // before `response.completed`.\n const handleOutputItemDone = (ev: OutputItemDone) => {\n if (!streamState.assistantId) return\n const item = ev.item as {\n type?: string\n name?: string\n arbi?: { label?: string; step?: string; detail?: Array<{ tool?: string }> }\n summary?: unknown\n content?: unknown\n }\n // An interjection reasoning item settles the queued prompts it steered in.\n const interjection = getInterjectionText(item)\n if (interjection) {\n completeQueuedUserMessageByContent(queryClient, streamState.conversationId, interjection)\n session.consumeQueuedMessage(streamState.assistantId, interjection)\n }\n // A narration message settles the instant the model pivots to a tool call \u2014\n // which is the moment its prose is complete on screen, and so the moment its\n // reading window starts. The answer's own item is excluded: the answer is\n // what stays, so it needs no protection from being removed.\n //\n // Timing off the settled ITEM (not off deltas) is what keeps a normal turn\n // free of any added delay. Deltas cannot distinguish narration from the\n // answer, so a delta clock would restart on the answer's own last token and\n // make every single turn wait out the full dwell.\n const isAnswerMessage = item.arbi?.step === 'answering' || item.arbi?.label === 'Answered'\n // An item the server settles as Narration (a working note, or a first draft the\n // grounding guard re-rolled into a tool call) is not the answer: it leaves the body now\n // and lives on in Show steps. Left in place it read as the finished answer. Having left,\n // it needs no reading window, so it does not hold the resolution either.\n if (item.type === 'message' && !isAnswerMessage && item.arbi?.label === 'Narration') {\n removeSettledNarration(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n item.content\n )\n } else if (item.type === 'message' && !isAnswerMessage) {\n streamState.lastNarrationSettledAt = Date.now()\n }\n // A message item ending is NOT a paragraph ending. The backend splits one\n // sentence across several items \u2014 \"I've\" / \" started two background\n // research tasks\u2026\" / \" Microsoft. Let me collect those results now.\" \u2014\n // so breaking at every settle would shred prose mid-sentence.\n //\n // What genuinely ends a narration is the model PIVOTING to a tool call\n // and coming back. Record the pivot; the next prose acts on it.\n if (item.type === 'function_call') {\n streamState.pivotedSinceProse = true\n // A memory tool changed facts / labels server-side. Note it now and\n // refresh those views at completion, by when the tool has executed and\n // committed (invalidating on the call itself would race the DB write).\n // The tool name rides on `item.name`; fall back to the display detail.\n const tool = item.name || item.arbi?.detail?.[0]?.tool || ''\n if (tool === 'create_fact' || tool === 'label_facts') {\n streamState.factsTouched = true\n }\n }\n\n applyOutputItemToMessage(queryClient, streamState.conversationId, streamState.assistantId, ev)\n }\n\n const handleUserInputRequest = (request: UserInputRequestEvent) => {\n if (!streamState.assistantId) return\n setUserInputRequest(queryClient, streamState.conversationId, streamState.assistantId, request)\n }\n\n const handleProbeAnswer = (probe: ProbeAnswerEvent) => {\n if (!streamState.assistantId) return\n // Out-of-band status answer \u2014 a transient note on the streaming turn.\n session.setAgentProbeAnswer(streamState.assistantId, probe)\n }\n\n const handleDeferredInterjection = (data: DeferredInterjectionEvent) => {\n // Steering that reached the agent after it had committed to its answer.\n // Too late to fold into this turn \u2014 collect it and let the send\n // resubmit it as a new turn once the current turn finishes (submitting\n // now would race the in-flight stream).\n if (!data.message) return\n streamState.deferredInterjections.push(data.message)\n }\n\n const handleAgentControlState = (event: AgentControlStateEvent) => {\n if (!streamState.assistantId) return\n // Server-confirmed pause/resume state overrides the optimistic client state.\n session.setAgentControlState(streamState.assistantId, event.state)\n }\n\n // ARBI saved an email draft (a reply it was asked for): the host opens it beside this chat.\n const handleMailDraft = (draft: MailDraftSSEEvent) => host.onMailDraft?.(draft)\n\n const handleArtifact = (artifact: ArtifactEvent) => {\n console.info('[SSE] Received artifact event:', {\n doc_ext_id: artifact.doc_ext_id,\n title: artifact.title,\n is_complete: artifact.is_complete,\n })\n\n // Kept for every surface that shows the document as it is written; the host shows it.\n recordChatArtifact(artifact, streamState.conversationId)\n host.onArtifact?.(artifact, streamState.conversationId)\n\n // Auto-pin a freshly created artifact as this conversation's full-context\n // document once it's done streaming \u2014 \"make it bigger\", \"change the\n // color\" means the thing just shown, not whatever was pinned before.\n // Deliberately scoped to artifact CREATION, not general document\n // viewing: opening an unrelated doc to check something must not\n // silently redirect full-context to it (that's exactly the footgun the\n // existing manual-pin-only design avoids). The pin button\n // (the context chip's PinnedDocChip) remains the cancel/override \u2014 same\n // setPinnedDocumentId it already uses, so unpinning or pinning\n // something else works exactly as it does today. the conversation's documents\n // are required too: selectFullContextDocument only honours a pin that's\n // also in the conversation's document list (`selectFullContextDocument`),\n // and a just-generated artifact was never added there.\n if (artifact.is_complete) {\n const documents = session.getState().conversationDocuments[streamState.conversationId] ?? []\n if (!documents.some((d) => d.docId === artifact.doc_ext_id))\n session.setConversationDocuments(streamState.conversationId, [\n ...documents,\n { docId: artifact.doc_ext_id, isPinned: false },\n ])\n // A document draft is a Word document (stored as DOCX): the assistant drafts in it through\n // the open document (read on demand, tracked changes), so it is never pinned \u2014 a pin\n // would resend the whole document every turn. Only html/react artifacts, whose source\n // the assistant edits directly, are pinned.\n if (artifact.mode === 'html' || artifact.mode === 'react')\n session.setPinnedDocumentId(artifact.doc_ext_id)\n // The pin only WORKS once the doc is in the workspace-documents\n // cache: the composer's pill lookup and selectFullContextDocument\n // both intersect against it, and a just-generated artifact isn't\n // there until some later refetch. Without this, the auto-pin was\n // set but invisible AND dropped from the next send \u2014 same append\n // the upload path does.\n ctx.refreshDocuments([artifact.doc_ext_id]).catch(() => {})\n }\n }\n\n const handleElapsedTime = (t: number) => {\n session.setBackendElapsed(streamState.conversationId, t)\n }\n\n const handleContextUpdate = (context: TokenBudgetContext) => {\n if (!streamState.assistantId) return\n applyFinalContextToMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n context\n )\n }\n\n const handleError = (error: unknown) => {\n // A stop ends the stream as well; the stop itself settles the turn.\n if (streamState.isStopped()) return\n console.error('Stream error:', error)\n if (streamState.queuedContinuation && !streamState.hasStreamStarted) {\n streamState.queuedFailed = true\n }\n // If the stream error carries LiteLLM's ExceededBudget payload, open\n // the upgrade modal proactively. The \"Response Failed\" inline alert\n // still appears (driven by message status), but the user gets the\n // popup explaining why and offering to upgrade.\n const quota = quotaFromStreamError(error)\n if (quota) host.onQuotaExceeded?.(quota)\n // A thrown error is the connection, not the run: the run goes on on the server, and the\n // send re-reads the thread to attach to it or show how it ended (see useMessageActions).\n // Marking it failed here offered Retry, which deleted the question under a live answer.\n if (error instanceof Error) return\n streamState.serverError = String(error)\n // The server failed the answer: mark it failed so the UI shows the error state\n if (streamState.assistantId) {\n markMessageAsFailed(queryClient, streamState.conversationId, streamState.assistantId)\n }\n }\n\n const handleComplete = () => {\n console.debug('[SSE] Stream complete')\n // A Stop can end the run with a completed frame that carries only the partial answer,\n // either before its abort lands or with no local stream to abort. That frame's status\n // is not the run's: re-read the thread so the message shows how the server ended it.\n const generation = session.getState().generating[streamState.conversationId]\n if (streamState.isStopped() || generation?.isGenerating === false) {\n void queryClient.invalidateQueries({\n queryKey: getThreadsQueryKey(streamState.conversationId),\n })\n }\n // Ensure any rAF-buffered tokens are committed before the consumer\n // considers the stream finished. Without this, final deltas that\n // arrived in the same frame as the complete event would be dropped.\n flushStreamingTokens(queryClient)\n // Turn is over \u2014 drop its transient control state (pause/probe).\n if (streamState.assistantId) {\n session.clearAgentControl(streamState.assistantId)\n }\n // The model added a fact or a new label this turn: refresh the Facts\n // list and the workspace label vocabulary so they appear without a page\n // reload. `refetchType: 'all'` updates the cache even when the Facts view\n // is not currently mounted (the tags query has staleTime: Infinity and\n // would otherwise never pick the new label up on its own).\n if (streamState.factsTouched) {\n streamState.factsTouched = false\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allFacts(), refetchType: 'all' })\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allTags(), refetchType: 'all' })\n }\n }\n\n return {\n onMessageQueued: handleMessageQueued,\n onUserMessage: handleUserMessage,\n onStreamStart: handleStreamStart,\n onToken: handleToken,\n onMetadata: handleMetadata,\n onOutputItemDone: handleOutputItemDone,\n onOutputTextDelta: handleOutputTextDelta,\n onUserInputRequest: handleUserInputRequest,\n onProbeAnswer: handleProbeAnswer,\n onDeferredInterjection: handleDeferredInterjection,\n onAgentControlState: handleAgentControlState,\n onArtifact: handleArtifact,\n onMailDraft: handleMailDraft,\n onElapsedTime: handleElapsedTime,\n onContextUpdate: handleContextUpdate,\n onError: handleError,\n onComplete: handleComplete,\n }\n}\n\n/** The stream handlers of this host's chat (its cache, session and chat host). */\nexport function useStreamHandlers(): (params: StreamHandlerParams) => StreamHandlers {\n const queryClient = useQueryClient()\n const session = useArbiSessionStore()\n const config = useArbiHost()\n const arbi = useArbi()\n return useCallback(\n (params: StreamHandlerParams) =>\n createStreamHandlers(\n {\n queryClient,\n session,\n host: config.chat ?? {},\n userId: () => {\n try {\n return arbi.user.identity()?.externalId ?? ''\n } catch {\n return ''\n }\n },\n refreshDocuments: (ids) => refreshDocuments(queryClient, arbi, ids),\n },\n params\n ),\n [queryClient, session, config, arbi]\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,76 @@
1
+ import { findConversation, patchConversation } from "../conversation-list.js";
2
+ import { getThreadsQueryKey } from "./conversation-cache.js";
3
+ import {
4
+ UNBOUND,
5
+ bindingOfRow,
6
+ forgetLegacyThreadDocuments,
7
+ readLegacyThreadDocuments
8
+ } from "./thread-document.js";
9
+ function threadBinding(queryClient, conversationId) {
10
+ if (!conversationId) return UNBOUND;
11
+ const row = findConversation(queryClient, conversationId);
12
+ if (row) return bindingOfRow(row);
13
+ const threads = queryClient.getQueryData(getThreadsQueryKey(conversationId));
14
+ return bindingOfRow(threads ? { external_id: conversationId, ...threads } : null);
15
+ }
16
+ function boundDocumentOf(queryClient, state) {
17
+ return state.conversationId ? threadBinding(queryClient, state.conversationId).documentId : state.newChatDocumentId;
18
+ }
19
+ function cacheThreadBinding(queryClient, conversationId, binding) {
20
+ const fields = {
21
+ bound_document_ext_id: binding.documentId,
22
+ bound_document_unavailable: binding.unavailable
23
+ };
24
+ patchConversation(queryClient, conversationId, fields);
25
+ queryClient.setQueryData(
26
+ getThreadsQueryKey(conversationId),
27
+ (old) => old ? { ...old, ...fields } : old
28
+ );
29
+ }
30
+ async function bindThreadDocument(arbi, queryClient, conversationId, documentId) {
31
+ const before = threadBinding(queryClient, conversationId);
32
+ if (before.documentId === documentId && !before.unavailable) return;
33
+ cacheThreadBinding(queryClient, conversationId, { documentId, unavailable: false });
34
+ try {
35
+ const saved = await arbi.conversations.update(conversationId, {
36
+ bound_document_ext_id: documentId
37
+ });
38
+ patchConversation(queryClient, conversationId, saved);
39
+ cacheThreadBinding(queryClient, conversationId, bindingOfRow(saved));
40
+ } catch (error) {
41
+ cacheThreadBinding(queryClient, conversationId, before);
42
+ throw error;
43
+ }
44
+ }
45
+ function adoptNewChatDocument(session, queryClient, conversationId, documentId = session.getState().newChatDocumentId) {
46
+ if (!documentId) return;
47
+ cacheThreadBinding(queryClient, conversationId, { documentId, unavailable: false });
48
+ if (session.getState().newChatDocumentId === documentId) session.setNewChatDocumentId(null);
49
+ }
50
+ async function migrateLegacyThreadDocuments(arbi, queryClient, conversations) {
51
+ const legacy = readLegacyThreadDocuments();
52
+ const listed = conversations.filter(
53
+ (c) => c.external_id in legacy && "bound_document_unavailable" in c
54
+ );
55
+ if (listed.length === 0) return;
56
+ await Promise.all(
57
+ listed.map(async (row) => {
58
+ const server = bindingOfRow(row);
59
+ if (server.documentId || server.unavailable) return;
60
+ try {
61
+ await bindThreadDocument(arbi, queryClient, row.external_id, legacy[row.external_id]);
62
+ } catch {
63
+ }
64
+ })
65
+ );
66
+ forgetLegacyThreadDocuments(listed.map((c) => c.external_id));
67
+ }
68
+ export {
69
+ adoptNewChatDocument,
70
+ bindThreadDocument,
71
+ boundDocumentOf,
72
+ cacheThreadBinding,
73
+ migrateLegacyThreadDocuments,
74
+ threadBinding
75
+ };
76
+ //# sourceMappingURL=thread-binding.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/chat/thread-binding.ts"],
4
+ "sourcesContent": ["/**\n * A conversation's bound document in the query cache, and the writes that change it on the server.\n *\n * The server holds the binding (`./thread-document`); the cache is its mirror: the conversation's\n * row in the workspace's list (`bound_document_ext_id`, `bound_document_unavailable`), else its\n * threads response (a thread opened from a link, not listed yet). An attach or unbind shows at once\n * and is written with `PATCH /v1/conversation/{id}`; a failure puts the cache back. Another\n * member's or device's change arrives as `conversation.document_binding_changed`\n * (`./conversation-events`), which re-reads the conversation under this reader's access.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi, ConversationResponse, ThreadsResponse } from '@arbidocs/sdk/browser'\nimport { findConversation, patchConversation } from '../conversation-list'\nimport { getThreadsQueryKey } from './conversation-cache'\nimport {\n UNBOUND,\n bindingOfRow,\n forgetLegacyThreadDocuments,\n readLegacyThreadDocuments,\n type ThreadBinding,\n} from './thread-document'\n\n/** What this module needs of the session store (structural, like the rest of the chat engine). */\ninterface NewChatSession {\n getState(): { conversationId: string | null; newChatDocumentId: string | null }\n setNewChatDocumentId(documentId: string | null): void\n}\n\n/** A saved conversation's binding, from the cache (its list row, else its threads). */\nexport function threadBinding(\n queryClient: QueryClient,\n conversationId: string | null | undefined\n): ThreadBinding {\n if (!conversationId) return UNBOUND\n const row = findConversation(queryClient, conversationId)\n if (row) return bindingOfRow(row)\n const threads = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n return bindingOfRow(threads ? { external_id: conversationId, ...threads } : null)\n}\n\n/** The document the open conversation is bound to: its saved binding, or the new chat's. */\nexport function boundDocumentOf(\n queryClient: QueryClient,\n state: ReturnType<NewChatSession['getState']>\n): string | null {\n return state.conversationId\n ? threadBinding(queryClient, state.conversationId).documentId\n : state.newChatDocumentId\n}\n\n/** Put a binding in the cache (the list rows and the threads response that hold the conversation). */\nexport function cacheThreadBinding(\n queryClient: QueryClient,\n conversationId: string,\n binding: ThreadBinding\n): void {\n const fields = {\n bound_document_ext_id: binding.documentId,\n bound_document_unavailable: binding.unavailable,\n }\n patchConversation(queryClient, conversationId, fields)\n queryClient.setQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId), (old) =>\n old ? { ...old, ...fields } : old\n )\n}\n\n/**\n * Bind a saved conversation to a document, or (null) unbind it: shown at once, written to the\n * server. Rejects (with the cache put back) when the server refuses: a document of another\n * workspace, or one the caller cannot read.\n */\nexport async function bindThreadDocument(\n arbi: Pick<Arbi, 'conversations'>,\n queryClient: QueryClient,\n conversationId: string,\n documentId: string | null\n): Promise<void> {\n const before = threadBinding(queryClient, conversationId)\n if (before.documentId === documentId && !before.unavailable) return\n cacheThreadBinding(queryClient, conversationId, { documentId, unavailable: false })\n try {\n const saved: ConversationResponse = await arbi.conversations.update(conversationId, {\n bound_document_ext_id: documentId,\n })\n patchConversation(queryClient, conversationId, saved)\n cacheThreadBinding(queryClient, conversationId, bindingOfRow(saved))\n } catch (error) {\n cacheThreadBinding(queryClient, conversationId, before)\n throw error\n }\n}\n\n/**\n * A new chat got its server id: the document its first turn was sent with is now the\n * conversation's (the server bound it with that turn). Call it once the conversation's row is in\n * the list; `documentId` defaults to the session's new-chat binding.\n */\nexport function adoptNewChatDocument(\n session: NewChatSession,\n queryClient: QueryClient,\n conversationId: string,\n documentId: string | null = session.getState().newChatDocumentId\n): void {\n if (!documentId) return\n cacheThreadBinding(queryClient, conversationId, { documentId, unavailable: false })\n if (session.getState().newChatDocumentId === documentId) session.setNewChatDocumentId(null)\n}\n\n/**\n * Move the bindings this browser kept locally (before the server held them) to the server, for\n * the conversations of a workspace's list, then forget them here. A conversation the server\n * already binds keeps its server binding. Runs once per list it is given; the key is removed when\n * the last kept binding is moved.\n */\nexport async function migrateLegacyThreadDocuments(\n arbi: Pick<Arbi, 'conversations'>,\n queryClient: QueryClient,\n conversations: readonly ConversationResponse[]\n): Promise<void> {\n const legacy = readLegacyThreadDocuments()\n // Only rows from a server that holds bindings (they carry the field): never lose a kept one.\n const listed = conversations.filter(\n (c) => c.external_id in legacy && 'bound_document_unavailable' in c\n )\n if (listed.length === 0) return\n await Promise.all(\n listed.map(async (row) => {\n const server = bindingOfRow(row)\n if (server.documentId || server.unavailable) return\n try {\n await bindThreadDocument(arbi, queryClient, row.external_id, legacy[row.external_id])\n } catch {\n // The document is gone or not readable any more: nothing to keep.\n }\n })\n )\n forgetLegacyThreadDocuments(listed.map((c) => c.external_id))\n}\n"],
5
+ "mappings": "AAaA,SAAS,kBAAkB,yBAAyB;AACpD,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AASA,SAAS,cACd,aACA,gBACe;AACf,MAAI,CAAC,eAAgB,QAAO;AAC5B,QAAM,MAAM,iBAAiB,aAAa,cAAc;AACxD,MAAI,IAAK,QAAO,aAAa,GAAG;AAChC,QAAM,UAAU,YAAY,aAA8B,mBAAmB,cAAc,CAAC;AAC5F,SAAO,aAAa,UAAU,EAAE,aAAa,gBAAgB,GAAG,QAAQ,IAAI,IAAI;AAClF;AAGO,SAAS,gBACd,aACA,OACe;AACf,SAAO,MAAM,iBACT,cAAc,aAAa,MAAM,cAAc,EAAE,aACjD,MAAM;AACZ;AAGO,SAAS,mBACd,aACA,gBACA,SACM;AACN,QAAM,SAAS;AAAA,IACb,uBAAuB,QAAQ;AAAA,IAC/B,4BAA4B,QAAQ;AAAA,EACtC;AACA,oBAAkB,aAAa,gBAAgB,MAAM;AACrD,cAAY;AAAA,IAA8B,mBAAmB,cAAc;AAAA,IAAG,CAAC,QAC7E,MAAM,EAAE,GAAG,KAAK,GAAG,OAAO,IAAI;AAAA,EAChC;AACF;AAOA,eAAsB,mBACpB,MACA,aACA,gBACA,YACe;AACf,QAAM,SAAS,cAAc,aAAa,cAAc;AACxD,MAAI,OAAO,eAAe,cAAc,CAAC,OAAO,YAAa;AAC7D,qBAAmB,aAAa,gBAAgB,EAAE,YAAY,aAAa,MAAM,CAAC;AAClF,MAAI;AACF,UAAM,QAA8B,MAAM,KAAK,cAAc,OAAO,gBAAgB;AAAA,MAClF,uBAAuB;AAAA,IACzB,CAAC;AACD,sBAAkB,aAAa,gBAAgB,KAAK;AACpD,uBAAmB,aAAa,gBAAgB,aAAa,KAAK,CAAC;AAAA,EACrE,SAAS,OAAO;AACd,uBAAmB,aAAa,gBAAgB,MAAM;AACtD,UAAM;AAAA,EACR;AACF;AAOO,SAAS,qBACd,SACA,aACA,gBACA,aAA4B,QAAQ,SAAS,EAAE,mBACzC;AACN,MAAI,CAAC,WAAY;AACjB,qBAAmB,aAAa,gBAAgB,EAAE,YAAY,aAAa,MAAM,CAAC;AAClF,MAAI,QAAQ,SAAS,EAAE,sBAAsB,WAAY,SAAQ,qBAAqB,IAAI;AAC5F;AAQA,eAAsB,6BACpB,MACA,aACA,eACe;AACf,QAAM,SAAS,0BAA0B;AAEzC,QAAM,SAAS,cAAc;AAAA,IAC3B,CAAC,MAAM,EAAE,eAAe,UAAU,gCAAgC;AAAA,EACpE;AACA,MAAI,OAAO,WAAW,EAAG;AACzB,QAAM,QAAQ;AAAA,IACZ,OAAO,IAAI,OAAO,QAAQ;AACxB,YAAM,SAAS,aAAa,GAAG;AAC/B,UAAI,OAAO,cAAc,OAAO,YAAa;AAC7C,UAAI;AACF,cAAM,mBAAmB,MAAM,aAAa,IAAI,aAAa,OAAO,IAAI,WAAW,CAAC;AAAA,MACtF,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAAA,EACH;AACA,8BAA4B,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AAC9D;",
6
+ "names": []
7
+ }