@opengeni/react 6.5.2-canary.41607687019001 → 6.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1154) hide show
  1. package/dist/app/app-state.d.ts +4 -0
  2. package/dist/app/app-state.js +19 -14
  3. package/dist/app/components/Composer.js +25 -23
  4. package/dist/app/components/agent/agent-capability-picker.js +10 -8
  5. package/dist/app/components/artifacts/artifact-browse-controls.js +4 -4
  6. package/dist/app/components/artifacts/artifact-library.js +21 -19
  7. package/dist/app/components/artifacts/artifact-page-chrome.js +3 -3
  8. package/dist/app/components/artifacts/artifact-viewer.js +23 -22
  9. package/dist/app/components/artifacts/artifact-viewer.js.map +1 -1
  10. package/dist/app/components/artifacts/chat-interactive-block.js +12 -12
  11. package/dist/app/components/artifacts/copy-artifact-link.js +7 -5
  12. package/dist/app/components/artifacts/file-reach-dialog.js +11 -9
  13. package/dist/app/components/artifacts/inline-chat-image.js +18 -18
  14. package/dist/app/components/artifacts/retained-file-preview.js +24 -23
  15. package/dist/app/components/artifacts/retained-text-preview.js +3 -3
  16. package/dist/app/components/artifacts/site-audience.js +6 -5
  17. package/dist/app/components/artifacts/site-conversations.js +16 -14
  18. package/dist/app/components/artifacts/site-data.js +18 -16
  19. package/dist/app/components/artifacts/site-public-link.js +3 -2
  20. package/dist/app/components/artifacts/site-publishing-page.js +39 -37
  21. package/dist/app/components/artifacts/site-publishing.js +34 -32
  22. package/dist/app/components/artifacts/site-settings.js +38 -36
  23. package/dist/app/components/artifacts/site-version-menu.js +8 -7
  24. package/dist/app/components/billing-class-mark.js +3 -3
  25. package/dist/app/components/bots/bot-launch-strip.js +17 -17
  26. package/dist/app/components/bots/bot-template-dialog.js +30 -28
  27. package/dist/app/components/bots/bot-template-shortcuts.js +19 -19
  28. package/dist/app/components/bots/bot-templates-page.js +38 -36
  29. package/dist/app/components/bots/bot-templates-page.js.map +1 -1
  30. package/dist/app/components/capabilities/capability-detail-sheet.js +13 -11
  31. package/dist/app/components/capabilities/capability-logo-source.js +13 -13
  32. package/dist/app/components/capabilities/capability-logo.js +4 -3
  33. package/dist/app/components/capabilities/connector-tool-permissions.js +8 -6
  34. package/dist/app/components/capabilities/native-connect-setup.js +14 -14
  35. package/dist/app/components/capabilities/own-logins-shared-heads-up.js +7 -6
  36. package/dist/app/components/capabilities/perform-capability-action.js +7 -6
  37. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +17 -17
  38. package/dist/app/components/capabilities/session-capability-card.js +72 -70
  39. package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
  40. package/dist/app/components/capabilities/session-chrome-card.js +28 -26
  41. package/dist/app/components/capabilities/session-connection-accounts.js +4 -3
  42. package/dist/app/components/capabilities/session-custom-mcp-card.js +20 -19
  43. package/dist/app/components/capabilities/session-github-card.js +22 -20
  44. package/dist/app/components/capabilities/session-machine-card.js +27 -25
  45. package/dist/app/components/capabilities/session-personal-github-card.js +16 -16
  46. package/dist/app/components/capabilities/session-plugin-card.js +10 -9
  47. package/dist/app/components/capabilities/use-capabilities-catalog.js +4 -3
  48. package/dist/app/components/capabilities/use-connection-accounts.js +5 -4
  49. package/dist/app/components/command-menu/chat-status.js +15 -13
  50. package/dist/app/components/command-menu/chat-switcher.js +35 -33
  51. package/dist/app/components/command-menu/chat-switcher.js.map +1 -1
  52. package/dist/app/components/command-menu/command-menu.js +53 -50
  53. package/dist/app/components/command-menu/command-menu.js.map +1 -1
  54. package/dist/app/components/command-menu/shortcut-sheet.js +18 -16
  55. package/dist/app/components/command-menu/shortcut-sheet.js.map +1 -1
  56. package/dist/app/components/common.js +4 -3
  57. package/dist/app/components/composer-capabilities-menu-body.js +4 -4
  58. package/dist/app/components/composer-mobile-plus-panel.js +8 -8
  59. package/dist/app/components/composer-mobile-plus.js +1 -1
  60. package/dist/app/components/credit-required-gate.js +3 -3
  61. package/dist/app/components/credit-required-prompt.js +10 -8
  62. package/dist/app/components/credit-required-prompt.js.map +1 -1
  63. package/dist/app/components/credits/checkout-credits-celebration.js +3 -2
  64. package/dist/app/components/credits/checkout-return.js +3 -2
  65. package/dist/app/components/credits/checkout-return.js.map +1 -1
  66. package/dist/app/components/credits/coupon-redeem.js +5 -4
  67. package/dist/app/components/credits/credit-refusal-notice.js +7 -5
  68. package/dist/app/components/cross-slot-deep-link-recovery.js +5 -4
  69. package/dist/app/components/desktop/app-shots.js +13 -11
  70. package/dist/app/components/desktop/computer-use.js +6 -4
  71. package/dist/app/components/desktop/this-computer.js +9 -7
  72. package/dist/app/components/feedback.js +5 -4
  73. package/dist/app/components/follow-up-repository-menu-body.js +8 -6
  74. package/dist/app/components/follow-up-repository-menu-body.js.map +1 -1
  75. package/dist/app/components/follow-up-repository-picker.js +1 -1
  76. package/dist/app/components/github-app-connect-launcher.js +5 -4
  77. package/dist/app/components/in-app-help-link.js +3 -3
  78. package/dist/app/components/knowledge/agent-learning-settings.js +3 -2
  79. package/dist/app/components/knowledge/agent-learning-settings.js.map +1 -1
  80. package/dist/app/components/machines/connect-machine-dialog.js +18 -16
  81. package/dist/app/components/manual-repository-editor.js +3 -2
  82. package/dist/app/components/markdown.js +6 -6
  83. package/dist/app/components/models/models-ui.js +12 -10
  84. package/dist/app/components/my-things.js +12 -10
  85. package/dist/app/components/my-things.js.map +1 -1
  86. package/dist/app/components/new-session-starters.js +3 -3
  87. package/dist/app/components/own-where-it-works.js +9 -7
  88. package/dist/app/components/personal-resource-attachment-surface.js +4 -4
  89. package/dist/app/components/pickers.js +5 -5
  90. package/dist/app/components/rail/channel-create-dialog.js +7 -5
  91. package/dist/app/components/rail/project-glyph.js +17 -17
  92. package/dist/app/components/rail/project-profile.js +31 -29
  93. package/dist/app/components/rail/rail-context.js +3 -3
  94. package/dist/app/components/rail/rail-sections.js +68 -66
  95. package/dist/app/components/rail/session-header.js +59 -57
  96. package/dist/app/components/rail/session-list.js +66 -64
  97. package/dist/app/components/rail/session-row-content.js +4 -4
  98. package/dist/app/components/rail/session-row-hover-details.js +14 -12
  99. package/dist/app/components/rail/session-shell.js +90 -88
  100. package/dist/app/components/rail/site-session-group-heading.js +8 -8
  101. package/dist/app/components/repository-picker.js +8 -6
  102. package/dist/app/components/secrets/session-secrets-panel.js +4 -3
  103. package/dist/app/components/secrets/vault-model.js +3 -2
  104. package/dist/app/components/session/agent-configuration-panel.js +25 -23
  105. package/dist/app/components/session/agent-configuration-panel.js.map +1 -1
  106. package/dist/app/components/session/artifact-link-boundary.js +3 -3
  107. package/dist/app/components/session/artifact-session-page.js +11 -9
  108. package/dist/app/components/session/banners.js +8 -8
  109. package/dist/app/components/session/codex-usage-notice.js +5 -3
  110. package/dist/app/components/session/console-new-conversation.js +42 -40
  111. package/dist/app/components/session/context-text-reader.js +3 -2
  112. package/dist/app/components/session/descendant-requests.js +39 -37
  113. package/dist/app/components/session/descendant-requests.js.map +1 -1
  114. package/dist/app/components/session/editable-artifacts-workspace.js +36 -34
  115. package/dist/app/components/session/editable-artifacts-workspace.js.map +1 -1
  116. package/dist/app/components/session/failed-session-banner.js +13 -11
  117. package/dist/app/components/session/failed-session-banner.js.map +1 -1
  118. package/dist/app/components/session/failure-recovery-boundary.js +3 -3
  119. package/dist/app/components/session/human-input-delegation-record.js +2 -2
  120. package/dist/app/components/session/human-input.js +33 -31
  121. package/dist/app/components/session/inspector.js +57 -55
  122. package/dist/app/components/session/inspector.js.map +1 -1
  123. package/dist/app/components/session/message-actions.js +5 -4
  124. package/dist/app/components/session/message-actions.js.map +1 -1
  125. package/dist/app/components/session/message-resource-attachments.js +12 -11
  126. package/dist/app/components/session/message-resource-attachments.js.map +1 -1
  127. package/dist/app/components/session/model-context-inspector.js +6 -4
  128. package/dist/app/components/session/model-recovery-notice.js +3 -3
  129. package/dist/app/components/session/new-session-settings-menu.js +11 -9
  130. package/dist/app/components/session/new-session-setup-strip.js +18 -18
  131. package/dist/app/components/session/sandbox-recovery-actions.js +3 -3
  132. package/dist/app/components/session/sandbox-switcher.js +10 -9
  133. package/dist/app/components/session/sandbox-workspace.js +47 -46
  134. package/dist/app/components/session/search-markdown-highlight.js +7 -7
  135. package/dist/app/components/session/search-results-view.js +8 -8
  136. package/dist/app/components/session/session-admin-access.js +13 -11
  137. package/dist/app/components/session/session-admission-notice.js +7 -5
  138. package/dist/app/components/session/session-avatar-picker.js +22 -20
  139. package/dist/app/components/session/session-avatar.js +16 -16
  140. package/dist/app/components/session/session-machine-access-notice.js +7 -5
  141. package/dist/app/components/session/session-profile-dialog.js +29 -27
  142. package/dist/app/components/session/session-profile-editor.js +30 -28
  143. package/dist/app/components/session/session-retention.js +10 -8
  144. package/dist/app/components/session/session-search-dialog.js +10 -10
  145. package/dist/app/components/session/session-skill-reviews.js +2 -1
  146. package/dist/app/components/session/session-skill-reviews.js.map +1 -1
  147. package/dist/app/components/session/session-tenancy-control.js +13 -11
  148. package/dist/app/components/session/session-tenancy-control.js.map +1 -1
  149. package/dist/app/components/session/session-unattended-setting.js +7 -5
  150. package/dist/app/components/session/session-usage-limit-section.js +11 -9
  151. package/dist/app/components/session/share-chat-dialog.js +9 -7
  152. package/dist/app/components/session/site-origin-link.js +3 -3
  153. package/dist/app/components/session/subagents.js +8 -8
  154. package/dist/app/components/session/subscription-account-indicator.js +6 -6
  155. package/dist/app/components/session-connectors-menu-body.js +4 -3
  156. package/dist/app/components/session-connectors-menu-body.js.map +1 -1
  157. package/dist/app/components/settings/row-select.js +7 -5
  158. package/dist/app/components/toaster.js +3 -2
  159. package/dist/app/components/transcription-settings.js +11 -9
  160. package/dist/app/components/ui/destructive-confirm.js +11 -9
  161. package/dist/app/components/usage/usage-entry.js +5 -5
  162. package/dist/app/components/window-bar.js +16 -14
  163. package/dist/app/components/workspace-composer-plus.js +22 -21
  164. package/dist/app/components/workspace-reach.js +6 -4
  165. package/dist/app/components/workspace-tenant-boundary.js +5 -4
  166. package/dist/app/embed/memory-navigation.js +3 -3
  167. package/dist/app/embed/session-app.js +211 -209
  168. package/dist/app/lib/actions/actions-provider.js +15 -13
  169. package/dist/app/lib/agent-capabilities.js +3 -3
  170. package/dist/app/lib/app-surfaces.js +7 -6
  171. package/dist/app/lib/archive-session.d.ts +9 -4
  172. package/dist/app/lib/archive-session.js +4 -2
  173. package/dist/app/lib/bot-templates.js +3 -2
  174. package/dist/app/lib/capabilities.js +3 -2
  175. package/dist/app/lib/codex-usage-query.js +2 -2
  176. package/dist/app/lib/composer-connectors.js +17 -16
  177. package/dist/app/lib/console-site.js +2 -2
  178. package/dist/app/lib/console-text.js +2 -2
  179. package/dist/app/lib/events.js +9 -9
  180. package/dist/app/lib/failed-session-copy.js +3 -3
  181. package/dist/app/lib/inbox.js +4 -2
  182. package/dist/app/lib/model-access-onboarding.js +3 -3
  183. package/dist/app/lib/move-chat-to-machine.js +3 -3
  184. package/dist/app/lib/navigation.js +2 -2
  185. package/dist/app/lib/session-branch-cache.js +6 -6
  186. package/dist/app/lib/session-create.js +4 -4
  187. package/dist/app/lib/session-group-pagination.js +6 -6
  188. package/dist/app/lib/session-hover-facts.js +13 -11
  189. package/dist/app/lib/session-model.js +2 -2
  190. package/dist/app/lib/session-rail.js +3 -3
  191. package/dist/app/lib/session-rename.js +3 -3
  192. package/dist/app/lib/session-restart-operation-controller.js +4 -3
  193. package/dist/app/lib/session-tenancy.js +3 -2
  194. package/dist/app/lib/session-usage-limit.js +3 -2
  195. package/dist/app/lib/sessions-group.js +5 -5
  196. package/dist/app/lib/site-publishing.js +3 -2
  197. package/dist/app/lib/site-tool-consent-dialog.js +9 -7
  198. package/dist/app/lib/site-tool-consent-dialog.js.map +1 -1
  199. package/dist/app/lib/site-tool-consent.js +1 -1
  200. package/dist/app/lib/subscription-plans.js +3 -2
  201. package/dist/app/lib/toast.js +2 -1
  202. package/dist/app/lib/turn-failure-analytics.js +4 -4
  203. package/dist/app/lib/use-duplicate-site.js +6 -5
  204. package/dist/app/lib/use-follow-up-repositories.js +6 -5
  205. package/dist/app/lib/use-workspace-integrations.js +4 -3
  206. package/dist/app/lib/use-workspace-machines.js +4 -4
  207. package/dist/app/lib/use-workspace-model-catalog.js +5 -4
  208. package/dist/app/lib/use-workspace-rigs.js +2 -2
  209. package/dist/app/lib/workspace-navigation-preference.js +4 -4
  210. package/dist/app/lib/workspace-scope-context.js +3 -3
  211. package/dist/app/routes/artifacts.js +67 -66
  212. package/dist/app/routes/artifacts.js.map +1 -1
  213. package/dist/app/routes/retained-artifact.js +42 -40
  214. package/dist/app/routes/retained-artifact.js.map +1 -1
  215. package/dist/app/routes/session-unavailable.js +8 -7
  216. package/dist/app/routes/session.js +119 -117
  217. package/dist/app/routes/sessions-index-hydration.js +5 -5
  218. package/dist/app/routes/sessions-index.js +104 -102
  219. package/dist/app/routes/site-view.js +67 -65
  220. package/dist/app/routes/site-view.js.map +1 -1
  221. package/dist/artifacts-document.js +4 -4
  222. package/dist/artifacts-presentation.js +4 -4
  223. package/dist/artifacts-spreadsheet.js +4 -4
  224. package/dist/artifacts.js +10 -10
  225. package/dist/automations.js +17 -15
  226. package/dist/automations.js.map +1 -1
  227. package/dist/browser-viewer-TC27OCIP.js +23 -0
  228. package/dist/chat-interactive-block-RWPQBHVS.js +18 -0
  229. package/dist/chunk-2BDT3UZQ.js +229 -0
  230. package/dist/chunk-2CLNIEK4.js +373 -0
  231. package/dist/chunk-2FSBSCZJ.js +451 -0
  232. package/dist/chunk-2I7HDP53.js +199 -0
  233. package/dist/chunk-2INLDVK3.js +15 -0
  234. package/dist/chunk-2KALVELR.js +126 -0
  235. package/dist/chunk-2M3J7ZWQ.js +418 -0
  236. package/dist/chunk-2OP6WLGV.js +708 -0
  237. package/dist/chunk-2RG7NIAS.js +2936 -0
  238. package/dist/chunk-2STUPWEL.js +135 -0
  239. package/dist/chunk-2YUOVM3G.js +271 -0
  240. package/dist/chunk-2Z3NQNTM.js +3670 -0
  241. package/dist/chunk-3CPWWGNK.js +920 -0
  242. package/dist/chunk-3ED2U6XE.js +37 -0
  243. package/dist/chunk-3GZA4BUW.js +216 -0
  244. package/dist/chunk-3IK6UYO6.js +1022 -0
  245. package/dist/chunk-3PZ7JZI2.js +431 -0
  246. package/dist/chunk-4DVJ6ONS.js +50 -0
  247. package/dist/chunk-4DVNUCRR.js +2386 -0
  248. package/dist/chunk-4DVNUCRR.js.map +1 -0
  249. package/dist/chunk-4E3ZJRTZ.js +41 -0
  250. package/dist/chunk-4SAWSRAA.js +141 -0
  251. package/dist/chunk-53AGXXZM.js +307 -0
  252. package/dist/chunk-54YW6SZZ.js +818 -0
  253. package/dist/chunk-57AZS3IE.js +2317 -0
  254. package/dist/chunk-5CPEEAFD.js +143 -0
  255. package/dist/chunk-5EWSRZ2Y.js +340 -0
  256. package/dist/chunk-5IE76VCY.js +387 -0
  257. package/dist/chunk-5NWEKLDZ.js +170 -0
  258. package/dist/chunk-5O2FCCHZ.js +198 -0
  259. package/dist/chunk-5QAY6K77.js +399 -0
  260. package/dist/chunk-5YKW2K6I.js +625 -0
  261. package/dist/chunk-5YKW2K6I.js.map +1 -0
  262. package/dist/chunk-6BCXNDEI.js +4116 -0
  263. package/dist/chunk-6BCXNDEI.js.map +1 -0
  264. package/dist/chunk-6DK6Z4UN.js +2599 -0
  265. package/dist/chunk-6DVCC7QS.js +702 -0
  266. package/dist/chunk-6JHU2UBS.js +2058 -0
  267. package/dist/chunk-6PZ7OBYU.js +490 -0
  268. package/dist/chunk-6WD2INST.js +539 -0
  269. package/dist/chunk-6WD2INST.js.map +1 -0
  270. package/dist/chunk-6WGRDRMA.js +163 -0
  271. package/dist/chunk-77WAKEAH.js +186 -0
  272. package/dist/chunk-7T2ZE3VT.js +5558 -0
  273. package/dist/chunk-7T2ZE3VT.js.map +1 -0
  274. package/dist/chunk-7TDO3CUM.js +393 -0
  275. package/dist/chunk-7TIX2UAR.js +247 -0
  276. package/dist/chunk-7V5REBCP.js +148 -0
  277. package/dist/chunk-7VMZGLYI.js +339 -0
  278. package/dist/chunk-7W37NS3I.js +236 -0
  279. package/dist/chunk-7X6SDK2C.js +111 -0
  280. package/dist/chunk-7ZNUHRP5.js +95 -0
  281. package/dist/chunk-A36PZALD.js +84 -0
  282. package/dist/chunk-AUI6VA63.js +107 -0
  283. package/dist/chunk-AW2MQB37.js +24 -0
  284. package/dist/chunk-AWKES45Y.js +198 -0
  285. package/dist/chunk-AXHZYXUV.js +132 -0
  286. package/dist/chunk-BHNSJVBC.js +129 -0
  287. package/dist/chunk-BJEJFISW.js +50 -0
  288. package/dist/chunk-BJFH6JI5.js +422 -0
  289. package/dist/chunk-BMICEQZQ.js +960 -0
  290. package/dist/chunk-BTLBYBLU.js +29 -0
  291. package/dist/chunk-BXBDYNRP.js +89 -0
  292. package/dist/chunk-C372BFOV.js +357 -0
  293. package/dist/chunk-C43KRXGA.js +234 -0
  294. package/dist/chunk-C43KRXGA.js.map +1 -0
  295. package/dist/chunk-CMKGILJK.js +4824 -0
  296. package/dist/chunk-CRAOSVHC.js +50 -0
  297. package/dist/chunk-CRU35QQH.js +281 -0
  298. package/dist/chunk-CUIWCGMA.js +172 -0
  299. package/dist/chunk-D5TWNFFE.js +38 -0
  300. package/dist/chunk-DF5EAHDN.js +4461 -0
  301. package/dist/chunk-DJAXC5OK.js +56 -0
  302. package/dist/chunk-DXBYWSL5.js +3550 -0
  303. package/dist/chunk-DXR5PDFP.js +84 -0
  304. package/dist/chunk-DZWARC4M.js +267 -0
  305. package/dist/chunk-DZXEDSQI.js +106 -0
  306. package/dist/chunk-E7XERZWC.js +48 -0
  307. package/dist/chunk-ECJBYNLJ.js +79 -0
  308. package/dist/chunk-EDI6SJ2N.js +43 -0
  309. package/dist/chunk-EWSOC6WF.js +114 -0
  310. package/dist/chunk-F2OPHAUN.js +103 -0
  311. package/dist/chunk-F4ISQGGM.js +81 -0
  312. package/dist/chunk-FO4LYKJL.js +197 -0
  313. package/dist/chunk-FPXASDG5.js +73 -0
  314. package/dist/chunk-FSOQDUCG.js +117 -0
  315. package/dist/chunk-FSOQDUCG.js.map +1 -0
  316. package/dist/chunk-FVXBNBHO.js +157 -0
  317. package/dist/chunk-FYWT2O76.js +34 -0
  318. package/dist/chunk-FYWT2O76.js.map +1 -0
  319. package/dist/chunk-FZC5N55X.js +981 -0
  320. package/dist/chunk-GAVYGBFI.js +99 -0
  321. package/dist/chunk-GFIMOUDT.js +846 -0
  322. package/dist/chunk-GFIMOUDT.js.map +1 -0
  323. package/dist/chunk-GKVJIDHF.js +33 -0
  324. package/dist/chunk-GVN5SZLX.js +212 -0
  325. package/dist/chunk-H3T7IWNA.js +134 -0
  326. package/dist/chunk-HAX4LCR5.js +261 -0
  327. package/dist/chunk-HC4JFZVU.js +121 -0
  328. package/dist/chunk-HEFPPMBQ.js +581 -0
  329. package/dist/chunk-HGKTHF2U.js +1356 -0
  330. package/dist/chunk-HGKTHF2U.js.map +1 -0
  331. package/dist/chunk-HNLR7Q4Z.js +83 -0
  332. package/dist/chunk-HSOXMJOT.js +12 -0
  333. package/dist/chunk-I4MRDSUF.js +281 -0
  334. package/dist/chunk-I4QEJ62Y.js +202 -0
  335. package/dist/chunk-I5B5L6Q4.js +56 -0
  336. package/dist/chunk-I5QZJODL.js +264 -0
  337. package/dist/chunk-I7ITSXSJ.js +603 -0
  338. package/dist/chunk-I7XIZRFD.js +390 -0
  339. package/dist/chunk-IDANQPRH.js +82 -0
  340. package/dist/chunk-IFB3WJ36.js +212 -0
  341. package/dist/chunk-IHTAKKTK.js +264 -0
  342. package/dist/chunk-IKXNLWAL.js +205 -0
  343. package/dist/chunk-IKXNLWAL.js.map +1 -0
  344. package/dist/chunk-ILDXWY37.js +173 -0
  345. package/dist/chunk-IMDQUHBJ.js +570 -0
  346. package/dist/chunk-IMZCQBOT.js +119 -0
  347. package/dist/chunk-IXPTECSC.js +403 -0
  348. package/dist/chunk-J255A3N5.js +71 -0
  349. package/dist/chunk-J5F5HPPW.js +141 -0
  350. package/dist/chunk-JDTGRRNU.js +5045 -0
  351. package/dist/chunk-JDTGRRNU.js.map +1 -0
  352. package/dist/chunk-JEA3QDX7.js +2469 -0
  353. package/dist/chunk-JEUPAVYY.js +156 -0
  354. package/dist/chunk-JKHKLL5W.js +194 -0
  355. package/dist/chunk-JQL7ZH6C.js +650 -0
  356. package/dist/chunk-JWB44UGJ.js +57 -0
  357. package/dist/chunk-JZ4NLCAP.js +333 -0
  358. package/dist/chunk-K2A5PXQ5.js +412 -0
  359. package/dist/chunk-K56XV3C3.js +623 -0
  360. package/dist/chunk-K6GAXXVA.js +23 -0
  361. package/dist/chunk-KCBMFSMS.js +199 -0
  362. package/dist/chunk-KF2FV3ZJ.js +268 -0
  363. package/dist/chunk-KJD65EJP.js +278 -0
  364. package/dist/chunk-KLEUWIMZ.js +386 -0
  365. package/dist/chunk-KODELWYT.js +309 -0
  366. package/dist/chunk-KRDR5RJD.js +83 -0
  367. package/dist/chunk-KUDGXAF7.js +914 -0
  368. package/dist/chunk-KY2R73CG.js +171 -0
  369. package/dist/chunk-KY2R73CG.js.map +1 -0
  370. package/dist/chunk-KYS77RPN.js +85 -0
  371. package/dist/chunk-L7YTNTIK.js +368 -0
  372. package/dist/chunk-LHPNABDH.js +686 -0
  373. package/dist/chunk-MFROMEKA.js +401 -0
  374. package/dist/chunk-MIHN76LX.js +2656 -0
  375. package/dist/chunk-MIYFS2XN.js +42 -0
  376. package/dist/chunk-MJUCFQMS.js +65 -0
  377. package/dist/chunk-MM4FNWI4.js +3064 -0
  378. package/dist/chunk-MNZG4OHU.js +790 -0
  379. package/dist/chunk-MVW6HNPI.js +250 -0
  380. package/dist/chunk-MVW6HNPI.js.map +1 -0
  381. package/dist/chunk-N6AACDUW.js +200 -0
  382. package/dist/chunk-NC55IFN3.js +781 -0
  383. package/dist/chunk-NC7PVOEK.js +98 -0
  384. package/dist/chunk-NCYMNCJO.js +70 -0
  385. package/dist/chunk-ND2BXV3P.js +259 -0
  386. package/dist/chunk-NDBTFUO6.js +272 -0
  387. package/dist/chunk-NDQJZ7HF.js +206 -0
  388. package/dist/chunk-NGJJJPZZ.js +162 -0
  389. package/dist/chunk-NJTSNNE7.js +251 -0
  390. package/dist/chunk-NPGISCU6.js +4159 -0
  391. package/dist/chunk-NPGISCU6.js.map +1 -0
  392. package/dist/chunk-NRTE7DNV.js +1270 -0
  393. package/dist/chunk-NULUNM7H.js +290 -0
  394. package/dist/chunk-NUNZS36W.js +227 -0
  395. package/dist/chunk-NW53H5RW.js +2424 -0
  396. package/dist/chunk-NXCMHIKI.js +263 -0
  397. package/dist/chunk-O3LKCBP5.js +159 -0
  398. package/dist/chunk-O4EA4F3W.js +103 -0
  399. package/dist/chunk-O4EA4F3W.js.map +1 -0
  400. package/dist/chunk-O4OOG3D6.js +116 -0
  401. package/dist/chunk-O4OOG3D6.js.map +1 -0
  402. package/dist/chunk-O6N4ABCA.js +376 -0
  403. package/dist/chunk-O732GAFC.js +112 -0
  404. package/dist/chunk-OF4TIKYC.js +690 -0
  405. package/dist/chunk-OMPVOMPP.js +70 -0
  406. package/dist/chunk-OPJJSKUK.js +118 -0
  407. package/dist/chunk-OPWCMA4D.js +196 -0
  408. package/dist/chunk-ORJPS5VN.js +1193 -0
  409. package/dist/chunk-OSY5K7L7.js +187 -0
  410. package/dist/chunk-OV6QJRT4.js +45 -0
  411. package/dist/chunk-OVKYVZMW.js +108 -0
  412. package/dist/chunk-OZCBM3UC.js +171 -0
  413. package/dist/chunk-P3A2EINJ.js +61 -0
  414. package/dist/chunk-PTAG4PDC.js +27 -0
  415. package/dist/chunk-PTF5B7TJ.js +298 -0
  416. package/dist/chunk-Q3DPEYX4.js +848 -0
  417. package/dist/chunk-Q6CGOPJD.js +215 -0
  418. package/dist/chunk-Q6CGOPJD.js.map +1 -0
  419. package/dist/chunk-QB2KMIDP.js +100 -0
  420. package/dist/chunk-QCSJ4CWE.js +1067 -0
  421. package/dist/chunk-QIOQ2NPQ.js +414 -0
  422. package/dist/chunk-QK5EFEUT.js +353 -0
  423. package/dist/chunk-QPQBLYQJ.js +41 -0
  424. package/dist/chunk-QPSGCC5D.js +184 -0
  425. package/dist/chunk-QZAAUQRN.js +474 -0
  426. package/dist/chunk-QZM6YDJW.js +489 -0
  427. package/dist/chunk-QZM6YDJW.js.map +1 -0
  428. package/dist/chunk-RGBI63KJ.js +188 -0
  429. package/dist/chunk-RLBKLAEY.js +138 -0
  430. package/dist/chunk-RMFKVOM7.js +304 -0
  431. package/dist/chunk-ROKQU7WG.js +258 -0
  432. package/dist/chunk-RPVREAU7.js +251 -0
  433. package/dist/chunk-RQKLF42C.js +723 -0
  434. package/dist/chunk-SC6RRD2D.js +38 -0
  435. package/dist/chunk-SC6RRD2D.js.map +1 -0
  436. package/dist/chunk-SEO7TICN.js +94 -0
  437. package/dist/chunk-SHHJCL7X.js +432 -0
  438. package/dist/chunk-SIRLACNZ.js +114 -0
  439. package/dist/chunk-SKPHMYAA.js +237 -0
  440. package/dist/chunk-SODC7T6L.js +1583 -0
  441. package/dist/chunk-SQJIKMN3.js +366 -0
  442. package/dist/chunk-SVINDKVW.js +26 -0
  443. package/dist/chunk-SYCDHPZF.js +335 -0
  444. package/dist/chunk-T2QX3FDP.js +133 -0
  445. package/dist/chunk-T3OWFVMS.js +1187 -0
  446. package/dist/chunk-T6XI5FLY.js +61 -0
  447. package/dist/chunk-T7OXJZCX.js +62 -0
  448. package/dist/chunk-TAT5USZN.js +353 -0
  449. package/dist/chunk-TPQTRNER.js +172 -0
  450. package/dist/chunk-TUIN4MB7.js +266 -0
  451. package/dist/chunk-TX3VECZU.js +71 -0
  452. package/dist/chunk-TXLIEOJX.js +9624 -0
  453. package/dist/chunk-U3DN4HEY.js +27 -0
  454. package/dist/chunk-U7XM7CB4.js +191 -0
  455. package/dist/chunk-UJK53QFL.js +140 -0
  456. package/dist/chunk-UMTXA2TH.js +319 -0
  457. package/dist/chunk-UPDSXFK5.js +199 -0
  458. package/dist/chunk-UTIAXH52.js +269 -0
  459. package/dist/chunk-UVN5TMHU.js +1184 -0
  460. package/dist/chunk-V4Z4B2E3.js +52 -0
  461. package/dist/chunk-V4Z4B2E3.js.map +1 -0
  462. package/dist/chunk-VGYXW3VG.js +246 -0
  463. package/dist/chunk-VS7AHPCZ.js +255 -0
  464. package/dist/chunk-VTTAJOQ7.js +121 -0
  465. package/dist/chunk-VWPOLUAO.js +99 -0
  466. package/dist/chunk-X3MWB2QU.js +3851 -0
  467. package/dist/chunk-X6KAJI3V.js +211 -0
  468. package/dist/chunk-XBLRHV5R.js +50 -0
  469. package/dist/chunk-XDFP2LMW.js +605 -0
  470. package/dist/chunk-XEQMZB3C.js +525 -0
  471. package/dist/chunk-XEYLT5VA.js +223 -0
  472. package/dist/chunk-XHIQ5I6N.js +918 -0
  473. package/dist/chunk-XLH7QY2R.js +378 -0
  474. package/dist/chunk-XWFAMUZQ.js +113 -0
  475. package/dist/chunk-Y4BB2KS2.js +294 -0
  476. package/dist/chunk-Y4BB2KS2.js.map +1 -0
  477. package/dist/chunk-Y4OBB2VN.js +84 -0
  478. package/dist/chunk-YCVD6CI3.js +234 -0
  479. package/dist/chunk-YENLNISG.js +270 -0
  480. package/dist/chunk-YIRVLKAX.js +351 -0
  481. package/dist/chunk-YL73CVNK.js +390 -0
  482. package/dist/chunk-YLS6QE5G.js +288 -0
  483. package/dist/chunk-YNF2OC54.js +366 -0
  484. package/dist/chunk-YNF2OC54.js.map +1 -0
  485. package/dist/chunk-YPWU5KPE.js +147 -0
  486. package/dist/chunk-YQXTDZSU.js +2984 -0
  487. package/dist/chunk-YSJEAAOL.js +178 -0
  488. package/dist/chunk-YWIFM7D7.js +499 -0
  489. package/dist/chunk-YWVI6ZMK.js +103 -0
  490. package/dist/chunk-Z4FMAFNH.js +847 -0
  491. package/dist/chunk-Z654FWNU.js +136 -0
  492. package/dist/chunk-Z7Y523PS.js +130 -0
  493. package/dist/chunk-ZD67RM6G.js +60 -0
  494. package/dist/chunk-ZEG4VPBL.js +187 -0
  495. package/dist/chunk-ZHDFQITM.js +283 -0
  496. package/dist/chunk-ZHDFQITM.js.map +1 -0
  497. package/dist/chunk-ZLYCOBHW.js +75 -0
  498. package/dist/chunk-ZNJ5MTXV.js +89 -0
  499. package/dist/chunk-ZSGY3H53.js +155 -0
  500. package/dist/chunk-ZTPXACWB.js +1788 -0
  501. package/dist/chunk-ZUA3JMI6.js +107 -0
  502. package/dist/chunk-ZYAZUPPV.js +559 -0
  503. package/dist/composer.js +8 -8
  504. package/dist/computer-viewer-TDDO25AV.js +21 -0
  505. package/dist/connect.js +12 -12
  506. package/dist/desktop-dictation.js +12 -10
  507. package/dist/desktop-dictation.js.map +1 -1
  508. package/dist/desktop.js +2 -2
  509. package/dist/editor.js +2 -2
  510. package/dist/embedded-new-voice-2G3VLPVQ.js +24 -0
  511. package/dist/embedded-voice-T5IWOWGD.js +24 -0
  512. package/dist/fleet-decision-row-WM64KXP3.js +361 -0
  513. package/dist/in-chat-connect-model.js +5 -5
  514. package/dist/index.js +51 -51
  515. package/dist/interaction.js +5 -5
  516. package/dist/machines.js +3 -3
  517. package/dist/meetings-recorder.js +1 -1
  518. package/dist/meetings.js +40 -32
  519. package/dist/meetings.js.map +1 -1
  520. package/dist/messages/en.d.ts +3 -0
  521. package/dist/messages.js +1 -1
  522. package/dist/model-policy-picker-menu-SMC6J6QN.js +22 -0
  523. package/dist/payment-page-card-G4U63KUV.js +223 -0
  524. package/dist/platform-activity-row-BUZGZAKZ.js +128 -0
  525. package/dist/queue-surface-implementation-4KUZ4PJV.js +908 -0
  526. package/dist/realtime.js +4 -4
  527. package/dist/recorder-host-WF2RRR56.js +69 -0
  528. package/dist/recorder-host-WF2RRR56.js.map +1 -0
  529. package/dist/recordings.js +3 -3
  530. package/dist/sandbox-files-ESDMOFSD.js +27 -0
  531. package/dist/session-app.js +211 -209
  532. package/dist/session-connect-cards-Q53KMMYY.js +25 -0
  533. package/dist/session-list-model.js +2 -2
  534. package/dist/session-realtime-CF3I35WJ.js +30 -0
  535. package/dist/session-realtime.js +2 -2
  536. package/dist/session-ui.js +33 -31
  537. package/dist/session.js +5 -5
  538. package/dist/sites.js +2 -2
  539. package/dist/terminal.js +2 -2
  540. package/dist/this-computer.js +3 -3
  541. package/dist/timeline-annotation-markers-CJK4RYZ4.js +157 -0
  542. package/dist/timeline-annotation-selection-67GF5H26.js +208 -0
  543. package/dist/timeline-annotations-dialog-ONJPQDJQ.js +283 -0
  544. package/dist/ui/access-list.js +11 -9
  545. package/dist/ui/access-list.js.map +1 -1
  546. package/dist/ui/api-error.d.ts +6 -3
  547. package/dist/ui/api-error.js +2 -1
  548. package/dist/ui/cadence-picker.js +6 -4
  549. package/dist/ui/choice-cards.js +5 -3
  550. package/dist/ui/confirm-dialog.js +2 -2
  551. package/dist/ui/copy-field.js +5 -3
  552. package/dist/ui/detail-page.js +2 -2
  553. package/dist/ui/detail-sheet.js +2 -2
  554. package/dist/ui/diff-view.js +4 -3
  555. package/dist/ui/disclosure.js +3 -3
  556. package/dist/ui/email-chips-input.js +5 -3
  557. package/dist/ui/error-message.js +2 -1
  558. package/dist/ui/error-reference.d.ts +15 -0
  559. package/dist/ui/error-text.d.ts +10 -0
  560. package/dist/ui/error-text.js +9 -0
  561. package/dist/ui/error-text.js.map +1 -0
  562. package/dist/ui/field.js +4 -2
  563. package/dist/ui/flush-form-page.js +8 -6
  564. package/dist/ui/form-dialog.js +7 -5
  565. package/dist/ui/list-row.js +3 -3
  566. package/dist/ui/load-failure.js +3 -2
  567. package/dist/ui/load-failure.js.map +1 -1
  568. package/dist/ui/notice.js +3 -1
  569. package/dist/ui/relative-time.js +2 -2
  570. package/dist/ui/revision-history.js +9 -7
  571. package/dist/ui/revision-history.js.map +1 -1
  572. package/dist/ui/role-select.js +10 -8
  573. package/dist/ui/segmented-control.js +4 -2
  574. package/dist/ui/select-menu.js +5 -3
  575. package/dist/ui/setting-row.js +3 -1
  576. package/dist/ui/switch.js +4 -2
  577. package/dist/ui/usage-meter.js +3 -3
  578. package/dist/ui/word-list-row.js +4 -2
  579. package/dist/usage.js +2 -2
  580. package/dist/workbench.js +4 -4
  581. package/package.json +5 -6
  582. package/src/app/app-state.tsx +126 -14
  583. package/src/app/components/artifacts/site-data.tsx +2 -2
  584. package/src/app/components/artifacts/site-settings.tsx +2 -2
  585. package/src/app/components/rail/session-list.tsx +7 -8
  586. package/src/app/components/rail/session-shell.tsx +3 -3
  587. package/src/app/components/repository-picker.tsx +8 -1
  588. package/src/app/components/session/model-context-inspector.tsx +2 -1
  589. package/src/app/components/session/session-admin-access.tsx +2 -2
  590. package/src/app/lib/actions/chat-operations.ts +4 -4
  591. package/src/app/lib/archive-session.test.tsx +265 -2
  592. package/src/app/lib/archive-session.tsx +175 -9
  593. package/src/app/lib/copy-link.ts +2 -2
  594. package/src/app/lib/inbox.tsx +2 -2
  595. package/src/app/lib/session-failure-toasts.ts +3 -2
  596. package/src/app/lib/toast.test.tsx +215 -0
  597. package/src/app/lib/toast.tsx +67 -2
  598. package/src/app/personal-github-reconnect.test.tsx +356 -0
  599. package/src/app/routes/artifacts.tsx +1 -2
  600. package/src/components/tool-action-review.tsx +14 -1
  601. package/src/meetings/delete-meeting-dialog.tsx +2 -1
  602. package/src/meetings/meeting-ask.tsx +2 -1
  603. package/src/meetings/meeting-detail-page.tsx +2 -1
  604. package/src/meetings/meeting-notes.tsx +2 -1
  605. package/src/meetings/meeting-settings.tsx +4 -1
  606. package/src/meetings/meeting-transcript.tsx +4 -1
  607. package/src/meetings/recorder-context.tsx +10 -0
  608. package/src/meetings/recorder-host.test.tsx +60 -2
  609. package/src/meetings/recorder-host.tsx +16 -3
  610. package/src/meetings/recorder-panel.tsx +2 -1
  611. package/src/meetings/recorder-workspace.test.tsx +26 -1
  612. package/src/messages/en.ts +6 -0
  613. package/src/ui/api-error.test.ts +29 -5
  614. package/src/ui/api-error.tsx +10 -4
  615. package/src/ui/error-message.tsx +8 -0
  616. package/src/ui/error-reference.test.ts +54 -0
  617. package/src/ui/error-reference.ts +51 -0
  618. package/src/ui/error-text.test.tsx +66 -0
  619. package/src/ui/error-text.tsx +49 -0
  620. package/src/ui/field.tsx +4 -1
  621. package/src/ui/notice.tsx +7 -2
  622. package/src/ui/setting-row.tsx +4 -1
  623. package/styles/app.css +12 -0
  624. package/styles/compiled.css +9 -0
  625. package/dist/browser-viewer-NOP5EAUO.js +0 -23
  626. package/dist/chat-interactive-block-G7O44JHR.js +0 -18
  627. package/dist/chunk-26RWVLRD.js +0 -135
  628. package/dist/chunk-2AHTY7OT.js +0 -247
  629. package/dist/chunk-2GDNWKSC.js +0 -3670
  630. package/dist/chunk-2JENKGCE.js +0 -339
  631. package/dist/chunk-2KYQC4T5.js +0 -155
  632. package/dist/chunk-2RREGDQH.js +0 -708
  633. package/dist/chunk-2T7DX6KR.js +0 -353
  634. package/dist/chunk-2VB2O4FQ.js +0 -920
  635. package/dist/chunk-2VTTKH23.js +0 -94
  636. package/dist/chunk-2XNG2KNT.js +0 -172
  637. package/dist/chunk-2YC6JQRO.js +0 -399
  638. package/dist/chunk-2ZVRJRXC.js +0 -27
  639. package/dist/chunk-35737UT4.js +0 -162
  640. package/dist/chunk-366XZ4PM.js +0 -41
  641. package/dist/chunk-36MIDGAH.js +0 -199
  642. package/dist/chunk-3FD76LXM.js +0 -212
  643. package/dist/chunk-3OVIXY4O.js +0 -213
  644. package/dist/chunk-3OVIXY4O.js.map +0 -1
  645. package/dist/chunk-3QNRBEYH.js +0 -432
  646. package/dist/chunk-3QX55WLC.js +0 -15
  647. package/dist/chunk-3USJPT2S.js +0 -1022
  648. package/dist/chunk-42CMQ5VR.js +0 -251
  649. package/dist/chunk-4LPOWQJY.js +0 -42
  650. package/dist/chunk-4NBTZRKT.js +0 -79
  651. package/dist/chunk-4OXI6HCV.js +0 -118
  652. package/dist/chunk-4SZZAFYQ.js +0 -2317
  653. package/dist/chunk-4TQL3WP2.js +0 -140
  654. package/dist/chunk-4Y6BK7IU.js +0 -196
  655. package/dist/chunk-4YD7YZC5.js +0 -373
  656. package/dist/chunk-5DTST3TP.js +0 -81
  657. package/dist/chunk-5FH5LQVS.js +0 -130
  658. package/dist/chunk-5KWMYPJV.js +0 -847
  659. package/dist/chunk-5MUJDC6C.js +0 -84
  660. package/dist/chunk-5QM2WPKV.js +0 -41
  661. package/dist/chunk-5WUN7XPD.js +0 -1184
  662. package/dist/chunk-64PO2WXU.js +0 -1067
  663. package/dist/chunk-6AHATAAY.js +0 -431
  664. package/dist/chunk-6ED2YWBT.js +0 -56
  665. package/dist/chunk-6GXVYAGR.js +0 -170
  666. package/dist/chunk-6H4SJBPE.js +0 -85
  667. package/dist/chunk-6MT3HHUB.js +0 -84
  668. package/dist/chunk-6UHCBH4G.js +0 -198
  669. package/dist/chunk-6WLX3NR3.js +0 -198
  670. package/dist/chunk-73NXYYWE.js +0 -112
  671. package/dist/chunk-76ERNKIZ.js +0 -603
  672. package/dist/chunk-776QZ573.js +0 -57
  673. package/dist/chunk-7BYWOFVH.js +0 -171
  674. package/dist/chunk-7O5CGGIQ.js +0 -108
  675. package/dist/chunk-7QOHRZ67.js +0 -251
  676. package/dist/chunk-7WIDB4PL.js +0 -2058
  677. package/dist/chunk-7WKP3DYJ.js +0 -37
  678. package/dist/chunk-7XOVTPDI.js +0 -227
  679. package/dist/chunk-AB5MBIXY.js +0 -281
  680. package/dist/chunk-ADNMXBCX.js +0 -1193
  681. package/dist/chunk-AFBJTUFK.js +0 -202
  682. package/dist/chunk-ALVRWCXE.js +0 -61
  683. package/dist/chunk-AOHU6O3M.js +0 -247
  684. package/dist/chunk-AOHU6O3M.js.map +0 -1
  685. package/dist/chunk-APW4T4SW.js +0 -270
  686. package/dist/chunk-AXBSYWKX.js +0 -2656
  687. package/dist/chunk-B2I5ZW35.js +0 -422
  688. package/dist/chunk-B3LMRTRF.js +0 -223
  689. package/dist/chunk-BE2XENG2.js +0 -292
  690. package/dist/chunk-BE2XENG2.js.map +0 -1
  691. package/dist/chunk-BF4SADKX.js +0 -29
  692. package/dist/chunk-BKP43KK4.js +0 -1788
  693. package/dist/chunk-BM3NEZ6X.js +0 -781
  694. package/dist/chunk-BT3BAGB5.js +0 -216
  695. package/dist/chunk-BTSYDIVJ.js +0 -357
  696. package/dist/chunk-BUBNGKWG.js +0 -70
  697. package/dist/chunk-BVUJV5WR.js +0 -126
  698. package/dist/chunk-BZO5ZMUP.js +0 -27
  699. package/dist/chunk-C3HUF3M2.js +0 -157
  700. package/dist/chunk-C5QCAOES.js +0 -264
  701. package/dist/chunk-CGK6ALQU.js +0 -159
  702. package/dist/chunk-CPYGO76Q.js +0 -335
  703. package/dist/chunk-CQH4FWYA.js +0 -490
  704. package/dist/chunk-CZP5QXNB.js +0 -234
  705. package/dist/chunk-D2TOWEYH.js +0 -266
  706. package/dist/chunk-D6L4GHRH.js +0 -340
  707. package/dist/chunk-DKT3N37I.js +0 -50
  708. package/dist/chunk-DMMJIFKA.js +0 -84
  709. package/dist/chunk-DO74DQC7.js +0 -26
  710. package/dist/chunk-DOFJZ2JU.js +0 -83
  711. package/dist/chunk-DSXVY5WZ.js +0 -119
  712. package/dist/chunk-E337C2VK.js +0 -82
  713. package/dist/chunk-E6NRSRBE.js +0 -114
  714. package/dist/chunk-E6SQKHAU.js +0 -114
  715. package/dist/chunk-E7UIVD7F.js +0 -236
  716. package/dist/chunk-EGBII4CP.js +0 -229
  717. package/dist/chunk-EILSAQVJ.js +0 -200
  718. package/dist/chunk-ELL6HSYR.js +0 -307
  719. package/dist/chunk-EUBGLFFR.js +0 -73
  720. package/dist/chunk-EW6RNWSH.js +0 -212
  721. package/dist/chunk-EYUT5Y6V.js +0 -2599
  722. package/dist/chunk-F7U3QPZ3.js +0 -304
  723. package/dist/chunk-FBTJKSTM.js +0 -1270
  724. package/dist/chunk-FC2FTSK3.js +0 -2424
  725. package/dist/chunk-FOGNA3BU.js +0 -148
  726. package/dist/chunk-FQFKHNC7.js +0 -650
  727. package/dist/chunk-FTCHM755.js +0 -50
  728. package/dist/chunk-FXSHP4JZ.js +0 -3550
  729. package/dist/chunk-G6ZZC543.js +0 -818
  730. package/dist/chunk-G7FU6PUA.js +0 -100
  731. package/dist/chunk-GA4YEAMX.js +0 -3851
  732. package/dist/chunk-GE33BGB7.js +0 -12
  733. package/dist/chunk-GQ67HSJY.js +0 -570
  734. package/dist/chunk-GXXZ3WAK.js +0 -106
  735. package/dist/chunk-H2TCRX3H.js +0 -237
  736. package/dist/chunk-HLL4PBO7.js +0 -60
  737. package/dist/chunk-HLOEPV5C.js +0 -259
  738. package/dist/chunk-HUAGBS4O.js +0 -56
  739. package/dist/chunk-I36GSRUJ.js +0 -211
  740. package/dist/chunk-I6VBHT7S.js +0 -261
  741. package/dist/chunk-ICNNNOXE.js +0 -333
  742. package/dist/chunk-ICX64J4U.js +0 -172
  743. package/dist/chunk-ID36Y46W.js +0 -5046
  744. package/dist/chunk-ID36Y46W.js.map +0 -1
  745. package/dist/chunk-IGVVXLKJ.js +0 -559
  746. package/dist/chunk-IKJLSBUI.js +0 -2984
  747. package/dist/chunk-IKMUFDVS.js +0 -50
  748. package/dist/chunk-IKUNOX7F.js +0 -255
  749. package/dist/chunk-ILKDYBON.js +0 -288
  750. package/dist/chunk-IVYJX3OY.js +0 -187
  751. package/dist/chunk-JCY4CMDH.js +0 -107
  752. package/dist/chunk-JJZPLGIP.js +0 -474
  753. package/dist/chunk-JW33RV4V.js +0 -143
  754. package/dist/chunk-JWPA6ZPZ.js +0 -351
  755. package/dist/chunk-JZ4QXS6D.js +0 -50
  756. package/dist/chunk-K42OUZQ3.js +0 -386
  757. package/dist/chunk-K5TOVX5A.js +0 -206
  758. package/dist/chunk-K63HGHZX.js +0 -99
  759. package/dist/chunk-K6R5T44I.js +0 -75
  760. package/dist/chunk-KHJ5PXFM.js +0 -914
  761. package/dist/chunk-KJZRQ55O.js +0 -2319
  762. package/dist/chunk-KJZRQ55O.js.map +0 -1
  763. package/dist/chunk-KKI55ZMW.js +0 -65
  764. package/dist/chunk-KRPLAAFP.js +0 -199
  765. package/dist/chunk-KVFEZDBO.js +0 -134
  766. package/dist/chunk-L4I665WK.js +0 -45
  767. package/dist/chunk-L4OF77LE.js +0 -110
  768. package/dist/chunk-L4OF77LE.js.map +0 -1
  769. package/dist/chunk-LA5T52RM.js +0 -70
  770. package/dist/chunk-LM2W5YAT.js +0 -401
  771. package/dist/chunk-LQ62ECE6.js +0 -390
  772. package/dist/chunk-LQDUHU3Y.js +0 -71
  773. package/dist/chunk-LRJIYTZW.js +0 -4157
  774. package/dist/chunk-LRJIYTZW.js.map +0 -1
  775. package/dist/chunk-LRN6GYAZ.js +0 -138
  776. package/dist/chunk-M4SDVTKJ.js +0 -790
  777. package/dist/chunk-MA6O7CM6.js +0 -99
  778. package/dist/chunk-MBIBB6GI.js +0 -197
  779. package/dist/chunk-MF3ZFB4H.js +0 -199
  780. package/dist/chunk-MJJGJMYJ.js +0 -98
  781. package/dist/chunk-MLJADQFI.js +0 -4824
  782. package/dist/chunk-MQG7RV3B.js +0 -62
  783. package/dist/chunk-MTTGSQA5.js +0 -186
  784. package/dist/chunk-MW7Y3T55.js +0 -525
  785. package/dist/chunk-MYUFMVCH.js +0 -121
  786. package/dist/chunk-N3OARGH2.js +0 -61
  787. package/dist/chunk-NB2HMRT2.js +0 -353
  788. package/dist/chunk-NFDFYWMV.js +0 -141
  789. package/dist/chunk-NWGNFN3N.js +0 -1187
  790. package/dist/chunk-NWJRPDIO.js +0 -840
  791. package/dist/chunk-NWJRPDIO.js.map +0 -1
  792. package/dist/chunk-NXWBBZJV.js +0 -267
  793. package/dist/chunk-NY2QWROL.js +0 -71
  794. package/dist/chunk-O2IOPP3R.js +0 -848
  795. package/dist/chunk-O2UWH5RG.js +0 -141
  796. package/dist/chunk-O5YWDLYF.js +0 -393
  797. package/dist/chunk-OBMCZO7E.js +0 -121
  798. package/dist/chunk-OD3DCCCB.js +0 -132
  799. package/dist/chunk-OMH7R6I3.js +0 -390
  800. package/dist/chunk-OSA5EQG5.js +0 -113
  801. package/dist/chunk-OSJ3MUTZ.js +0 -2936
  802. package/dist/chunk-OWAYJ2OV.js +0 -368
  803. package/dist/chunk-OYXBFSGK.js +0 -269
  804. package/dist/chunk-PC2EBA5G.js +0 -4116
  805. package/dist/chunk-PC2EBA5G.js.map +0 -1
  806. package/dist/chunk-PC2MVXIP.js +0 -363
  807. package/dist/chunk-PC2MVXIP.js.map +0 -1
  808. package/dist/chunk-PENGLDR5.js +0 -309
  809. package/dist/chunk-PSMAWRPL.js +0 -191
  810. package/dist/chunk-PW4IMTYR.js +0 -702
  811. package/dist/chunk-PW54V7T5.js +0 -387
  812. package/dist/chunk-Q2EXYSMO.js +0 -24
  813. package/dist/chunk-Q2XJK5I4.js +0 -51
  814. package/dist/chunk-Q2XJK5I4.js.map +0 -1
  815. package/dist/chunk-Q4EFRI6X.js +0 -258
  816. package/dist/chunk-Q52CXW6C.js +0 -48
  817. package/dist/chunk-Q6XQ2R37.js +0 -184
  818. package/dist/chunk-QAJ53XBW.js +0 -23
  819. package/dist/chunk-QDTKECT4.js +0 -129
  820. package/dist/chunk-QE3ZFGI3.js +0 -43
  821. package/dist/chunk-QHHSUR2Y.js +0 -298
  822. package/dist/chunk-QHNVNR7B.js +0 -173
  823. package/dist/chunk-QIK2Q6N5.js +0 -376
  824. package/dist/chunk-QWL4L366.js +0 -38
  825. package/dist/chunk-R3J2PTVQ.js +0 -690
  826. package/dist/chunk-RBRX5ZS3.js +0 -319
  827. package/dist/chunk-REX6JIC7.js +0 -33
  828. package/dist/chunk-RGZ7EEC3.js +0 -537
  829. package/dist/chunk-RGZ7EEC3.js.map +0 -1
  830. package/dist/chunk-RIPS7GFR.js +0 -960
  831. package/dist/chunk-RTBZNFNV.js +0 -1354
  832. package/dist/chunk-RTBZNFNV.js.map +0 -1
  833. package/dist/chunk-SKMNW4SW.js +0 -187
  834. package/dist/chunk-SRFARKXC.js +0 -623
  835. package/dist/chunk-SWIHWCTW.js +0 -4461
  836. package/dist/chunk-TA5CFTO4.js +0 -103
  837. package/dist/chunk-TF4ZVJLI.js +0 -156
  838. package/dist/chunk-TG7DADJR.js +0 -9624
  839. package/dist/chunk-TI4R2ZD5.js +0 -623
  840. package/dist/chunk-TI4R2ZD5.js.map +0 -1
  841. package/dist/chunk-TNKWOUWP.js +0 -412
  842. package/dist/chunk-TNUSPXPW.js +0 -5555
  843. package/dist/chunk-TNUSPXPW.js.map +0 -1
  844. package/dist/chunk-TNYFHKVV.js +0 -366
  845. package/dist/chunk-TPMZBOFH.js +0 -178
  846. package/dist/chunk-TW3LKRJF.js +0 -263
  847. package/dist/chunk-TZAO65I4.js +0 -83
  848. package/dist/chunk-U5EFEMYU.js +0 -89
  849. package/dist/chunk-U6M4LS3M.js +0 -378
  850. package/dist/chunk-UI4HI5QK.js +0 -918
  851. package/dist/chunk-UJDOWCQ3.js +0 -272
  852. package/dist/chunk-UJUQ2QOX.js +0 -581
  853. package/dist/chunk-UQ3IM6FY.js +0 -133
  854. package/dist/chunk-UYE47LO6.js +0 -246
  855. package/dist/chunk-VADHIT26.js +0 -89
  856. package/dist/chunk-VFQ3H6CO.js +0 -163
  857. package/dist/chunk-VGUN6VB2.js +0 -188
  858. package/dist/chunk-VGWWEVSD.js +0 -723
  859. package/dist/chunk-VIEFJ2DM.js +0 -2469
  860. package/dist/chunk-VLXM36VS.js +0 -268
  861. package/dist/chunk-W3BFRR2G.js +0 -499
  862. package/dist/chunk-W5MPXR3A.js +0 -981
  863. package/dist/chunk-W5OWKVZG.js +0 -136
  864. package/dist/chunk-W6FRORMX.js +0 -486
  865. package/dist/chunk-W6FRORMX.js.map +0 -1
  866. package/dist/chunk-W7XROSZO.js +0 -232
  867. package/dist/chunk-W7XROSZO.js.map +0 -1
  868. package/dist/chunk-WEZ5PXZP.js +0 -403
  869. package/dist/chunk-WHWUWN2X.js +0 -197
  870. package/dist/chunk-WHWUWN2X.js.map +0 -1
  871. package/dist/chunk-WLEDGIVS.js +0 -114
  872. package/dist/chunk-WLEDGIVS.js.map +0 -1
  873. package/dist/chunk-WNDAKLHG.js +0 -281
  874. package/dist/chunk-WTJ4PLMU.js +0 -103
  875. package/dist/chunk-WV2KPJUW.js +0 -107
  876. package/dist/chunk-X3VY5EGY.js +0 -277
  877. package/dist/chunk-X3VY5EGY.js.map +0 -1
  878. package/dist/chunk-XDBYWVCW.js +0 -418
  879. package/dist/chunk-XF7MA4U5.js +0 -36
  880. package/dist/chunk-XF7MA4U5.js.map +0 -1
  881. package/dist/chunk-XOSQP3YA.js +0 -605
  882. package/dist/chunk-XYBV4ZJQ.js +0 -271
  883. package/dist/chunk-YBKVGLQR.js +0 -147
  884. package/dist/chunk-YDCUBUWH.js +0 -1583
  885. package/dist/chunk-YG6NARQY.js +0 -51
  886. package/dist/chunk-YG6NARQY.js.map +0 -1
  887. package/dist/chunk-YSVD5HI4.js +0 -278
  888. package/dist/chunk-YT3WGNG6.js +0 -290
  889. package/dist/chunk-YYICQDK4.js +0 -414
  890. package/dist/chunk-YYLMZLI6.js +0 -686
  891. package/dist/chunk-ZAMTKG5U.js +0 -95
  892. package/dist/chunk-ZDLYSXKN.js +0 -111
  893. package/dist/chunk-ZG447FSS.js +0 -194
  894. package/dist/chunk-ZIT5KD4Q.js +0 -264
  895. package/dist/chunk-ZUDOVDKR.js +0 -3064
  896. package/dist/chunk-ZW2ECJ3A.js +0 -451
  897. package/dist/computer-viewer-LPZ763KF.js +0 -21
  898. package/dist/embedded-new-voice-YVMKSLKJ.js +0 -24
  899. package/dist/embedded-voice-BJPQFXSU.js +0 -24
  900. package/dist/fleet-decision-row-AA4H5CDT.js +0 -361
  901. package/dist/model-policy-picker-menu-HSMWVO4P.js +0 -22
  902. package/dist/payment-page-card-3LTSFJGN.js +0 -223
  903. package/dist/platform-activity-row-5VYV6TX4.js +0 -128
  904. package/dist/queue-surface-implementation-NXHZUKD2.js +0 -908
  905. package/dist/recorder-host-ZKRWTDBM.js +0 -57
  906. package/dist/recorder-host-ZKRWTDBM.js.map +0 -1
  907. package/dist/sandbox-files-YCMLQUFU.js +0 -27
  908. package/dist/session-connect-cards-KSQLMRM5.js +0 -25
  909. package/dist/session-realtime-ZR6JLG3Y.js +0 -30
  910. package/dist/timeline-annotation-markers-YAHDPWVG.js +0 -157
  911. package/dist/timeline-annotation-selection-KHXNCEJP.js +0 -208
  912. package/dist/timeline-annotations-dialog-Y4XD3N7B.js +0 -283
  913. /package/dist/{browser-viewer-NOP5EAUO.js.map → browser-viewer-TC27OCIP.js.map} +0 -0
  914. /package/dist/{chat-interactive-block-G7O44JHR.js.map → chat-interactive-block-RWPQBHVS.js.map} +0 -0
  915. /package/dist/{chunk-EGBII4CP.js.map → chunk-2BDT3UZQ.js.map} +0 -0
  916. /package/dist/{chunk-4YD7YZC5.js.map → chunk-2CLNIEK4.js.map} +0 -0
  917. /package/dist/{chunk-ZW2ECJ3A.js.map → chunk-2FSBSCZJ.js.map} +0 -0
  918. /package/dist/{chunk-KRPLAAFP.js.map → chunk-2I7HDP53.js.map} +0 -0
  919. /package/dist/{chunk-3QX55WLC.js.map → chunk-2INLDVK3.js.map} +0 -0
  920. /package/dist/{chunk-BVUJV5WR.js.map → chunk-2KALVELR.js.map} +0 -0
  921. /package/dist/{chunk-XDBYWVCW.js.map → chunk-2M3J7ZWQ.js.map} +0 -0
  922. /package/dist/{chunk-2RREGDQH.js.map → chunk-2OP6WLGV.js.map} +0 -0
  923. /package/dist/{chunk-OSJ3MUTZ.js.map → chunk-2RG7NIAS.js.map} +0 -0
  924. /package/dist/{chunk-26RWVLRD.js.map → chunk-2STUPWEL.js.map} +0 -0
  925. /package/dist/{chunk-XYBV4ZJQ.js.map → chunk-2YUOVM3G.js.map} +0 -0
  926. /package/dist/{chunk-2GDNWKSC.js.map → chunk-2Z3NQNTM.js.map} +0 -0
  927. /package/dist/{chunk-2VB2O4FQ.js.map → chunk-3CPWWGNK.js.map} +0 -0
  928. /package/dist/{chunk-7WKP3DYJ.js.map → chunk-3ED2U6XE.js.map} +0 -0
  929. /package/dist/{chunk-BT3BAGB5.js.map → chunk-3GZA4BUW.js.map} +0 -0
  930. /package/dist/{chunk-3USJPT2S.js.map → chunk-3IK6UYO6.js.map} +0 -0
  931. /package/dist/{chunk-6AHATAAY.js.map → chunk-3PZ7JZI2.js.map} +0 -0
  932. /package/dist/{chunk-JZ4QXS6D.js.map → chunk-4DVJ6ONS.js.map} +0 -0
  933. /package/dist/{chunk-5QM2WPKV.js.map → chunk-4E3ZJRTZ.js.map} +0 -0
  934. /package/dist/{chunk-NFDFYWMV.js.map → chunk-4SAWSRAA.js.map} +0 -0
  935. /package/dist/{chunk-ELL6HSYR.js.map → chunk-53AGXXZM.js.map} +0 -0
  936. /package/dist/{chunk-G6ZZC543.js.map → chunk-54YW6SZZ.js.map} +0 -0
  937. /package/dist/{chunk-4SZZAFYQ.js.map → chunk-57AZS3IE.js.map} +0 -0
  938. /package/dist/{chunk-JW33RV4V.js.map → chunk-5CPEEAFD.js.map} +0 -0
  939. /package/dist/{chunk-D6L4GHRH.js.map → chunk-5EWSRZ2Y.js.map} +0 -0
  940. /package/dist/{chunk-PW54V7T5.js.map → chunk-5IE76VCY.js.map} +0 -0
  941. /package/dist/{chunk-6GXVYAGR.js.map → chunk-5NWEKLDZ.js.map} +0 -0
  942. /package/dist/{chunk-6UHCBH4G.js.map → chunk-5O2FCCHZ.js.map} +0 -0
  943. /package/dist/{chunk-2YC6JQRO.js.map → chunk-5QAY6K77.js.map} +0 -0
  944. /package/dist/{chunk-EYUT5Y6V.js.map → chunk-6DK6Z4UN.js.map} +0 -0
  945. /package/dist/{chunk-PW4IMTYR.js.map → chunk-6DVCC7QS.js.map} +0 -0
  946. /package/dist/{chunk-7WIDB4PL.js.map → chunk-6JHU2UBS.js.map} +0 -0
  947. /package/dist/{chunk-CQH4FWYA.js.map → chunk-6PZ7OBYU.js.map} +0 -0
  948. /package/dist/{chunk-VFQ3H6CO.js.map → chunk-6WGRDRMA.js.map} +0 -0
  949. /package/dist/{chunk-MTTGSQA5.js.map → chunk-77WAKEAH.js.map} +0 -0
  950. /package/dist/{chunk-O5YWDLYF.js.map → chunk-7TDO3CUM.js.map} +0 -0
  951. /package/dist/{chunk-2AHTY7OT.js.map → chunk-7TIX2UAR.js.map} +0 -0
  952. /package/dist/{chunk-FOGNA3BU.js.map → chunk-7V5REBCP.js.map} +0 -0
  953. /package/dist/{chunk-2JENKGCE.js.map → chunk-7VMZGLYI.js.map} +0 -0
  954. /package/dist/{chunk-E7UIVD7F.js.map → chunk-7W37NS3I.js.map} +0 -0
  955. /package/dist/{chunk-ZDLYSXKN.js.map → chunk-7X6SDK2C.js.map} +0 -0
  956. /package/dist/{chunk-ZAMTKG5U.js.map → chunk-7ZNUHRP5.js.map} +0 -0
  957. /package/dist/{chunk-DMMJIFKA.js.map → chunk-A36PZALD.js.map} +0 -0
  958. /package/dist/{chunk-WV2KPJUW.js.map → chunk-AUI6VA63.js.map} +0 -0
  959. /package/dist/{chunk-Q2EXYSMO.js.map → chunk-AW2MQB37.js.map} +0 -0
  960. /package/dist/{chunk-6WLX3NR3.js.map → chunk-AWKES45Y.js.map} +0 -0
  961. /package/dist/{chunk-OD3DCCCB.js.map → chunk-AXHZYXUV.js.map} +0 -0
  962. /package/dist/{chunk-QDTKECT4.js.map → chunk-BHNSJVBC.js.map} +0 -0
  963. /package/dist/{chunk-FTCHM755.js.map → chunk-BJEJFISW.js.map} +0 -0
  964. /package/dist/{chunk-B2I5ZW35.js.map → chunk-BJFH6JI5.js.map} +0 -0
  965. /package/dist/{chunk-RIPS7GFR.js.map → chunk-BMICEQZQ.js.map} +0 -0
  966. /package/dist/{chunk-BF4SADKX.js.map → chunk-BTLBYBLU.js.map} +0 -0
  967. /package/dist/{chunk-U5EFEMYU.js.map → chunk-BXBDYNRP.js.map} +0 -0
  968. /package/dist/{chunk-BTSYDIVJ.js.map → chunk-C372BFOV.js.map} +0 -0
  969. /package/dist/{chunk-MLJADQFI.js.map → chunk-CMKGILJK.js.map} +0 -0
  970. /package/dist/{chunk-DKT3N37I.js.map → chunk-CRAOSVHC.js.map} +0 -0
  971. /package/dist/{chunk-WNDAKLHG.js.map → chunk-CRU35QQH.js.map} +0 -0
  972. /package/dist/{chunk-2XNG2KNT.js.map → chunk-CUIWCGMA.js.map} +0 -0
  973. /package/dist/{chunk-QWL4L366.js.map → chunk-D5TWNFFE.js.map} +0 -0
  974. /package/dist/{chunk-SWIHWCTW.js.map → chunk-DF5EAHDN.js.map} +0 -0
  975. /package/dist/{chunk-HUAGBS4O.js.map → chunk-DJAXC5OK.js.map} +0 -0
  976. /package/dist/{chunk-FXSHP4JZ.js.map → chunk-DXBYWSL5.js.map} +0 -0
  977. /package/dist/{chunk-5MUJDC6C.js.map → chunk-DXR5PDFP.js.map} +0 -0
  978. /package/dist/{chunk-NXWBBZJV.js.map → chunk-DZWARC4M.js.map} +0 -0
  979. /package/dist/{chunk-GXXZ3WAK.js.map → chunk-DZXEDSQI.js.map} +0 -0
  980. /package/dist/{chunk-Q52CXW6C.js.map → chunk-E7XERZWC.js.map} +0 -0
  981. /package/dist/{chunk-4NBTZRKT.js.map → chunk-ECJBYNLJ.js.map} +0 -0
  982. /package/dist/{chunk-QE3ZFGI3.js.map → chunk-EDI6SJ2N.js.map} +0 -0
  983. /package/dist/{chunk-E6NRSRBE.js.map → chunk-EWSOC6WF.js.map} +0 -0
  984. /package/dist/{chunk-TA5CFTO4.js.map → chunk-F2OPHAUN.js.map} +0 -0
  985. /package/dist/{chunk-5DTST3TP.js.map → chunk-F4ISQGGM.js.map} +0 -0
  986. /package/dist/{chunk-MBIBB6GI.js.map → chunk-FO4LYKJL.js.map} +0 -0
  987. /package/dist/{chunk-EUBGLFFR.js.map → chunk-FPXASDG5.js.map} +0 -0
  988. /package/dist/{chunk-C3HUF3M2.js.map → chunk-FVXBNBHO.js.map} +0 -0
  989. /package/dist/{chunk-W5MPXR3A.js.map → chunk-FZC5N55X.js.map} +0 -0
  990. /package/dist/{chunk-MA6O7CM6.js.map → chunk-GAVYGBFI.js.map} +0 -0
  991. /package/dist/{chunk-REX6JIC7.js.map → chunk-GKVJIDHF.js.map} +0 -0
  992. /package/dist/{chunk-EW6RNWSH.js.map → chunk-GVN5SZLX.js.map} +0 -0
  993. /package/dist/{chunk-KVFEZDBO.js.map → chunk-H3T7IWNA.js.map} +0 -0
  994. /package/dist/{chunk-I6VBHT7S.js.map → chunk-HAX4LCR5.js.map} +0 -0
  995. /package/dist/{chunk-OBMCZO7E.js.map → chunk-HC4JFZVU.js.map} +0 -0
  996. /package/dist/{chunk-UJUQ2QOX.js.map → chunk-HEFPPMBQ.js.map} +0 -0
  997. /package/dist/{chunk-DOFJZ2JU.js.map → chunk-HNLR7Q4Z.js.map} +0 -0
  998. /package/dist/{chunk-GE33BGB7.js.map → chunk-HSOXMJOT.js.map} +0 -0
  999. /package/dist/{chunk-AB5MBIXY.js.map → chunk-I4MRDSUF.js.map} +0 -0
  1000. /package/dist/{chunk-AFBJTUFK.js.map → chunk-I4QEJ62Y.js.map} +0 -0
  1001. /package/dist/{chunk-6ED2YWBT.js.map → chunk-I5B5L6Q4.js.map} +0 -0
  1002. /package/dist/{chunk-C5QCAOES.js.map → chunk-I5QZJODL.js.map} +0 -0
  1003. /package/dist/{chunk-76ERNKIZ.js.map → chunk-I7ITSXSJ.js.map} +0 -0
  1004. /package/dist/{chunk-OMH7R6I3.js.map → chunk-I7XIZRFD.js.map} +0 -0
  1005. /package/dist/{chunk-E337C2VK.js.map → chunk-IDANQPRH.js.map} +0 -0
  1006. /package/dist/{chunk-3FD76LXM.js.map → chunk-IFB3WJ36.js.map} +0 -0
  1007. /package/dist/{chunk-ZIT5KD4Q.js.map → chunk-IHTAKKTK.js.map} +0 -0
  1008. /package/dist/{chunk-QHNVNR7B.js.map → chunk-ILDXWY37.js.map} +0 -0
  1009. /package/dist/{chunk-GQ67HSJY.js.map → chunk-IMDQUHBJ.js.map} +0 -0
  1010. /package/dist/{chunk-DSXVY5WZ.js.map → chunk-IMZCQBOT.js.map} +0 -0
  1011. /package/dist/{chunk-WEZ5PXZP.js.map → chunk-IXPTECSC.js.map} +0 -0
  1012. /package/dist/{chunk-NY2QWROL.js.map → chunk-J255A3N5.js.map} +0 -0
  1013. /package/dist/{chunk-O2UWH5RG.js.map → chunk-J5F5HPPW.js.map} +0 -0
  1014. /package/dist/{chunk-VIEFJ2DM.js.map → chunk-JEA3QDX7.js.map} +0 -0
  1015. /package/dist/{chunk-TF4ZVJLI.js.map → chunk-JEUPAVYY.js.map} +0 -0
  1016. /package/dist/{chunk-ZG447FSS.js.map → chunk-JKHKLL5W.js.map} +0 -0
  1017. /package/dist/{chunk-FQFKHNC7.js.map → chunk-JQL7ZH6C.js.map} +0 -0
  1018. /package/dist/{chunk-776QZ573.js.map → chunk-JWB44UGJ.js.map} +0 -0
  1019. /package/dist/{chunk-ICNNNOXE.js.map → chunk-JZ4NLCAP.js.map} +0 -0
  1020. /package/dist/{chunk-TNKWOUWP.js.map → chunk-K2A5PXQ5.js.map} +0 -0
  1021. /package/dist/{chunk-SRFARKXC.js.map → chunk-K56XV3C3.js.map} +0 -0
  1022. /package/dist/{chunk-QAJ53XBW.js.map → chunk-K6GAXXVA.js.map} +0 -0
  1023. /package/dist/{chunk-MF3ZFB4H.js.map → chunk-KCBMFSMS.js.map} +0 -0
  1024. /package/dist/{chunk-VLXM36VS.js.map → chunk-KF2FV3ZJ.js.map} +0 -0
  1025. /package/dist/{chunk-YSVD5HI4.js.map → chunk-KJD65EJP.js.map} +0 -0
  1026. /package/dist/{chunk-K42OUZQ3.js.map → chunk-KLEUWIMZ.js.map} +0 -0
  1027. /package/dist/{chunk-PENGLDR5.js.map → chunk-KODELWYT.js.map} +0 -0
  1028. /package/dist/{chunk-TZAO65I4.js.map → chunk-KRDR5RJD.js.map} +0 -0
  1029. /package/dist/{chunk-KHJ5PXFM.js.map → chunk-KUDGXAF7.js.map} +0 -0
  1030. /package/dist/{chunk-6H4SJBPE.js.map → chunk-KYS77RPN.js.map} +0 -0
  1031. /package/dist/{chunk-OWAYJ2OV.js.map → chunk-L7YTNTIK.js.map} +0 -0
  1032. /package/dist/{chunk-YYLMZLI6.js.map → chunk-LHPNABDH.js.map} +0 -0
  1033. /package/dist/{chunk-LM2W5YAT.js.map → chunk-MFROMEKA.js.map} +0 -0
  1034. /package/dist/{chunk-AXBSYWKX.js.map → chunk-MIHN76LX.js.map} +0 -0
  1035. /package/dist/{chunk-4LPOWQJY.js.map → chunk-MIYFS2XN.js.map} +0 -0
  1036. /package/dist/{chunk-KKI55ZMW.js.map → chunk-MJUCFQMS.js.map} +0 -0
  1037. /package/dist/{chunk-ZUDOVDKR.js.map → chunk-MM4FNWI4.js.map} +0 -0
  1038. /package/dist/{chunk-M4SDVTKJ.js.map → chunk-MNZG4OHU.js.map} +0 -0
  1039. /package/dist/{chunk-EILSAQVJ.js.map → chunk-N6AACDUW.js.map} +0 -0
  1040. /package/dist/{chunk-BM3NEZ6X.js.map → chunk-NC55IFN3.js.map} +0 -0
  1041. /package/dist/{chunk-MJJGJMYJ.js.map → chunk-NC7PVOEK.js.map} +0 -0
  1042. /package/dist/{chunk-LA5T52RM.js.map → chunk-NCYMNCJO.js.map} +0 -0
  1043. /package/dist/{chunk-HLOEPV5C.js.map → chunk-ND2BXV3P.js.map} +0 -0
  1044. /package/dist/{chunk-UJDOWCQ3.js.map → chunk-NDBTFUO6.js.map} +0 -0
  1045. /package/dist/{chunk-K5TOVX5A.js.map → chunk-NDQJZ7HF.js.map} +0 -0
  1046. /package/dist/{chunk-35737UT4.js.map → chunk-NGJJJPZZ.js.map} +0 -0
  1047. /package/dist/{chunk-42CMQ5VR.js.map → chunk-NJTSNNE7.js.map} +0 -0
  1048. /package/dist/{chunk-FBTJKSTM.js.map → chunk-NRTE7DNV.js.map} +0 -0
  1049. /package/dist/{chunk-YT3WGNG6.js.map → chunk-NULUNM7H.js.map} +0 -0
  1050. /package/dist/{chunk-7XOVTPDI.js.map → chunk-NUNZS36W.js.map} +0 -0
  1051. /package/dist/{chunk-FC2FTSK3.js.map → chunk-NW53H5RW.js.map} +0 -0
  1052. /package/dist/{chunk-TW3LKRJF.js.map → chunk-NXCMHIKI.js.map} +0 -0
  1053. /package/dist/{chunk-CGK6ALQU.js.map → chunk-O3LKCBP5.js.map} +0 -0
  1054. /package/dist/{chunk-QIK2Q6N5.js.map → chunk-O6N4ABCA.js.map} +0 -0
  1055. /package/dist/{chunk-73NXYYWE.js.map → chunk-O732GAFC.js.map} +0 -0
  1056. /package/dist/{chunk-R3J2PTVQ.js.map → chunk-OF4TIKYC.js.map} +0 -0
  1057. /package/dist/{chunk-BUBNGKWG.js.map → chunk-OMPVOMPP.js.map} +0 -0
  1058. /package/dist/{chunk-4OXI6HCV.js.map → chunk-OPJJSKUK.js.map} +0 -0
  1059. /package/dist/{chunk-4Y6BK7IU.js.map → chunk-OPWCMA4D.js.map} +0 -0
  1060. /package/dist/{chunk-ADNMXBCX.js.map → chunk-ORJPS5VN.js.map} +0 -0
  1061. /package/dist/{chunk-SKMNW4SW.js.map → chunk-OSY5K7L7.js.map} +0 -0
  1062. /package/dist/{chunk-L4I665WK.js.map → chunk-OV6QJRT4.js.map} +0 -0
  1063. /package/dist/{chunk-7O5CGGIQ.js.map → chunk-OVKYVZMW.js.map} +0 -0
  1064. /package/dist/{chunk-7BYWOFVH.js.map → chunk-OZCBM3UC.js.map} +0 -0
  1065. /package/dist/{chunk-ALVRWCXE.js.map → chunk-P3A2EINJ.js.map} +0 -0
  1066. /package/dist/{chunk-BZO5ZMUP.js.map → chunk-PTAG4PDC.js.map} +0 -0
  1067. /package/dist/{chunk-QHHSUR2Y.js.map → chunk-PTF5B7TJ.js.map} +0 -0
  1068. /package/dist/{chunk-O2IOPP3R.js.map → chunk-Q3DPEYX4.js.map} +0 -0
  1069. /package/dist/{chunk-G7FU6PUA.js.map → chunk-QB2KMIDP.js.map} +0 -0
  1070. /package/dist/{chunk-64PO2WXU.js.map → chunk-QCSJ4CWE.js.map} +0 -0
  1071. /package/dist/{chunk-YYICQDK4.js.map → chunk-QIOQ2NPQ.js.map} +0 -0
  1072. /package/dist/{chunk-NB2HMRT2.js.map → chunk-QK5EFEUT.js.map} +0 -0
  1073. /package/dist/{chunk-366XZ4PM.js.map → chunk-QPQBLYQJ.js.map} +0 -0
  1074. /package/dist/{chunk-Q6XQ2R37.js.map → chunk-QPSGCC5D.js.map} +0 -0
  1075. /package/dist/{chunk-JJZPLGIP.js.map → chunk-QZAAUQRN.js.map} +0 -0
  1076. /package/dist/{chunk-VGUN6VB2.js.map → chunk-RGBI63KJ.js.map} +0 -0
  1077. /package/dist/{chunk-LRN6GYAZ.js.map → chunk-RLBKLAEY.js.map} +0 -0
  1078. /package/dist/{chunk-F7U3QPZ3.js.map → chunk-RMFKVOM7.js.map} +0 -0
  1079. /package/dist/{chunk-Q4EFRI6X.js.map → chunk-ROKQU7WG.js.map} +0 -0
  1080. /package/dist/{chunk-7QOHRZ67.js.map → chunk-RPVREAU7.js.map} +0 -0
  1081. /package/dist/{chunk-VGWWEVSD.js.map → chunk-RQKLF42C.js.map} +0 -0
  1082. /package/dist/{chunk-2VTTKH23.js.map → chunk-SEO7TICN.js.map} +0 -0
  1083. /package/dist/{chunk-3QNRBEYH.js.map → chunk-SHHJCL7X.js.map} +0 -0
  1084. /package/dist/{chunk-E6SQKHAU.js.map → chunk-SIRLACNZ.js.map} +0 -0
  1085. /package/dist/{chunk-H2TCRX3H.js.map → chunk-SKPHMYAA.js.map} +0 -0
  1086. /package/dist/{chunk-YDCUBUWH.js.map → chunk-SODC7T6L.js.map} +0 -0
  1087. /package/dist/{chunk-TNYFHKVV.js.map → chunk-SQJIKMN3.js.map} +0 -0
  1088. /package/dist/{chunk-DO74DQC7.js.map → chunk-SVINDKVW.js.map} +0 -0
  1089. /package/dist/{chunk-CPYGO76Q.js.map → chunk-SYCDHPZF.js.map} +0 -0
  1090. /package/dist/{chunk-UQ3IM6FY.js.map → chunk-T2QX3FDP.js.map} +0 -0
  1091. /package/dist/{chunk-NWGNFN3N.js.map → chunk-T3OWFVMS.js.map} +0 -0
  1092. /package/dist/{chunk-N3OARGH2.js.map → chunk-T6XI5FLY.js.map} +0 -0
  1093. /package/dist/{chunk-MQG7RV3B.js.map → chunk-T7OXJZCX.js.map} +0 -0
  1094. /package/dist/{chunk-2T7DX6KR.js.map → chunk-TAT5USZN.js.map} +0 -0
  1095. /package/dist/{chunk-ICX64J4U.js.map → chunk-TPQTRNER.js.map} +0 -0
  1096. /package/dist/{chunk-D2TOWEYH.js.map → chunk-TUIN4MB7.js.map} +0 -0
  1097. /package/dist/{chunk-LQDUHU3Y.js.map → chunk-TX3VECZU.js.map} +0 -0
  1098. /package/dist/{chunk-TG7DADJR.js.map → chunk-TXLIEOJX.js.map} +0 -0
  1099. /package/dist/{chunk-2ZVRJRXC.js.map → chunk-U3DN4HEY.js.map} +0 -0
  1100. /package/dist/{chunk-PSMAWRPL.js.map → chunk-U7XM7CB4.js.map} +0 -0
  1101. /package/dist/{chunk-4TQL3WP2.js.map → chunk-UJK53QFL.js.map} +0 -0
  1102. /package/dist/{chunk-RBRX5ZS3.js.map → chunk-UMTXA2TH.js.map} +0 -0
  1103. /package/dist/{chunk-36MIDGAH.js.map → chunk-UPDSXFK5.js.map} +0 -0
  1104. /package/dist/{chunk-OYXBFSGK.js.map → chunk-UTIAXH52.js.map} +0 -0
  1105. /package/dist/{chunk-5WUN7XPD.js.map → chunk-UVN5TMHU.js.map} +0 -0
  1106. /package/dist/{chunk-UYE47LO6.js.map → chunk-VGYXW3VG.js.map} +0 -0
  1107. /package/dist/{chunk-IKUNOX7F.js.map → chunk-VS7AHPCZ.js.map} +0 -0
  1108. /package/dist/{chunk-MYUFMVCH.js.map → chunk-VTTAJOQ7.js.map} +0 -0
  1109. /package/dist/{chunk-K63HGHZX.js.map → chunk-VWPOLUAO.js.map} +0 -0
  1110. /package/dist/{chunk-GA4YEAMX.js.map → chunk-X3MWB2QU.js.map} +0 -0
  1111. /package/dist/{chunk-I36GSRUJ.js.map → chunk-X6KAJI3V.js.map} +0 -0
  1112. /package/dist/{chunk-IKMUFDVS.js.map → chunk-XBLRHV5R.js.map} +0 -0
  1113. /package/dist/{chunk-XOSQP3YA.js.map → chunk-XDFP2LMW.js.map} +0 -0
  1114. /package/dist/{chunk-MW7Y3T55.js.map → chunk-XEQMZB3C.js.map} +0 -0
  1115. /package/dist/{chunk-B3LMRTRF.js.map → chunk-XEYLT5VA.js.map} +0 -0
  1116. /package/dist/{chunk-UI4HI5QK.js.map → chunk-XHIQ5I6N.js.map} +0 -0
  1117. /package/dist/{chunk-U6M4LS3M.js.map → chunk-XLH7QY2R.js.map} +0 -0
  1118. /package/dist/{chunk-OSA5EQG5.js.map → chunk-XWFAMUZQ.js.map} +0 -0
  1119. /package/dist/{chunk-6MT3HHUB.js.map → chunk-Y4OBB2VN.js.map} +0 -0
  1120. /package/dist/{chunk-CZP5QXNB.js.map → chunk-YCVD6CI3.js.map} +0 -0
  1121. /package/dist/{chunk-APW4T4SW.js.map → chunk-YENLNISG.js.map} +0 -0
  1122. /package/dist/{chunk-JWPA6ZPZ.js.map → chunk-YIRVLKAX.js.map} +0 -0
  1123. /package/dist/{chunk-LQ62ECE6.js.map → chunk-YL73CVNK.js.map} +0 -0
  1124. /package/dist/{chunk-ILKDYBON.js.map → chunk-YLS6QE5G.js.map} +0 -0
  1125. /package/dist/{chunk-YBKVGLQR.js.map → chunk-YPWU5KPE.js.map} +0 -0
  1126. /package/dist/{chunk-IKJLSBUI.js.map → chunk-YQXTDZSU.js.map} +0 -0
  1127. /package/dist/{chunk-TPMZBOFH.js.map → chunk-YSJEAAOL.js.map} +0 -0
  1128. /package/dist/{chunk-W3BFRR2G.js.map → chunk-YWIFM7D7.js.map} +0 -0
  1129. /package/dist/{chunk-WTJ4PLMU.js.map → chunk-YWVI6ZMK.js.map} +0 -0
  1130. /package/dist/{chunk-5KWMYPJV.js.map → chunk-Z4FMAFNH.js.map} +0 -0
  1131. /package/dist/{chunk-W5OWKVZG.js.map → chunk-Z654FWNU.js.map} +0 -0
  1132. /package/dist/{chunk-5FH5LQVS.js.map → chunk-Z7Y523PS.js.map} +0 -0
  1133. /package/dist/{chunk-HLL4PBO7.js.map → chunk-ZD67RM6G.js.map} +0 -0
  1134. /package/dist/{chunk-IVYJX3OY.js.map → chunk-ZEG4VPBL.js.map} +0 -0
  1135. /package/dist/{chunk-K6R5T44I.js.map → chunk-ZLYCOBHW.js.map} +0 -0
  1136. /package/dist/{chunk-VADHIT26.js.map → chunk-ZNJ5MTXV.js.map} +0 -0
  1137. /package/dist/{chunk-2KYQC4T5.js.map → chunk-ZSGY3H53.js.map} +0 -0
  1138. /package/dist/{chunk-BKP43KK4.js.map → chunk-ZTPXACWB.js.map} +0 -0
  1139. /package/dist/{chunk-JCY4CMDH.js.map → chunk-ZUA3JMI6.js.map} +0 -0
  1140. /package/dist/{chunk-IGVVXLKJ.js.map → chunk-ZYAZUPPV.js.map} +0 -0
  1141. /package/dist/{computer-viewer-LPZ763KF.js.map → computer-viewer-TDDO25AV.js.map} +0 -0
  1142. /package/dist/{embedded-new-voice-YVMKSLKJ.js.map → embedded-new-voice-2G3VLPVQ.js.map} +0 -0
  1143. /package/dist/{embedded-voice-BJPQFXSU.js.map → embedded-voice-T5IWOWGD.js.map} +0 -0
  1144. /package/dist/{fleet-decision-row-AA4H5CDT.js.map → fleet-decision-row-WM64KXP3.js.map} +0 -0
  1145. /package/dist/{model-policy-picker-menu-HSMWVO4P.js.map → model-policy-picker-menu-SMC6J6QN.js.map} +0 -0
  1146. /package/dist/{payment-page-card-3LTSFJGN.js.map → payment-page-card-G4U63KUV.js.map} +0 -0
  1147. /package/dist/{platform-activity-row-5VYV6TX4.js.map → platform-activity-row-BUZGZAKZ.js.map} +0 -0
  1148. /package/dist/{queue-surface-implementation-NXHZUKD2.js.map → queue-surface-implementation-4KUZ4PJV.js.map} +0 -0
  1149. /package/dist/{sandbox-files-YCMLQUFU.js.map → sandbox-files-ESDMOFSD.js.map} +0 -0
  1150. /package/dist/{session-connect-cards-KSQLMRM5.js.map → session-connect-cards-Q53KMMYY.js.map} +0 -0
  1151. /package/dist/{session-realtime-ZR6JLG3Y.js.map → session-realtime-CF3I35WJ.js.map} +0 -0
  1152. /package/dist/{timeline-annotation-markers-YAHDPWVG.js.map → timeline-annotation-markers-CJK4RYZ4.js.map} +0 -0
  1153. /package/dist/{timeline-annotation-selection-KHXNCEJP.js.map → timeline-annotation-selection-67GF5H26.js.map} +0 -0
  1154. /package/dist/{timeline-annotations-dialog-Y4XD3N7B.js.map → timeline-annotations-dialog-ONJPQDJQ.js.map} +0 -0
@@ -1,4461 +0,0 @@
1
- "use client";
2
- import {
3
- useSessionStartupState
4
- } from "./chunk-EMIVOS73.js";
5
- import {
6
- deniesRetainedView,
7
- useRetainedSessionView
8
- } from "./chunk-YUNVW3I2.js";
9
- import {
10
- admissionRecheckControl
11
- } from "./chunk-JWKGPA6Q.js";
12
- import {
13
- projectPendingApprovals
14
- } from "./chunk-VXORMNU4.js";
15
- import {
16
- buildTimeline,
17
- groupTimeline,
18
- isToolOutputPreviewEvent,
19
- sessionStatusFromEvents,
20
- useToolOutputReads
21
- } from "./chunk-4YCA2Y73.js";
22
- import {
23
- useFileAttachments
24
- } from "./chunk-I6FIXEL4.js";
25
- import {
26
- forgetSessionHumanInputDrafts,
27
- pruneHumanInputDrafts
28
- } from "./chunk-X62OJCQW.js";
29
- import {
30
- useSharedQuery
31
- } from "./chunk-IWUGGOXA.js";
32
- import {
33
- isActionableHumanInputRequest
34
- } from "./chunk-57MB2QGY.js";
35
- import {
36
- readAcknowledgementFrontier,
37
- sessionAttentionReadThroughSequence
38
- } from "./chunk-C5ZCSVZ7.js";
39
- import {
40
- promptSendDestination,
41
- sessionTurnKeepsRunControl
42
- } from "./chunk-TSENLSW6.js";
43
- import {
44
- useClientConfigFlags
45
- } from "./chunk-XESA3B7W.js";
46
- import {
47
- joinClientConfigRead
48
- } from "./chunk-IGVL3ELX.js";
49
- import {
50
- FILE_ONLY_MESSAGE_TEXT,
51
- notifyObserver,
52
- useComposer
53
- } from "./chunk-AXBSYWKX.js";
54
- import {
55
- DEFAULT_TRANSIENT_READ_RETRY,
56
- projectionReadThrough,
57
- transientReadRetryStep,
58
- useDebouncedCallback,
59
- useMutationRunner,
60
- usePageLiveActivity,
61
- usePolledValue,
62
- useSessionEventTrigger
63
- } from "./chunk-RV3O5OCQ.js";
64
- import {
65
- normalizeError
66
- } from "./chunk-CM7LVUKC.js";
67
- import {
68
- useEmbeddedGoal,
69
- useEmbeddedHumanInputSession,
70
- useEmbeddedSession,
71
- useEmbeddedSessionRead,
72
- useOpenGeni,
73
- useOpenGeniClient
74
- } from "./chunk-TVQCDDSZ.js";
75
- import {
76
- coerceReasoningEffortForModel,
77
- defaultEffortForModel,
78
- projectPickerRows,
79
- runnableLatencyModesForModel,
80
- sortPickerRows
81
- } from "./chunk-ZHC47M2B.js";
82
- import {
83
- useOpenGeniText
84
- } from "./chunk-TNUSPXPW.js";
85
-
86
- // src/hooks/use-session.ts
87
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
88
-
89
- // src/lib/session-detail-read.ts
90
- var lastOrdinal = 0;
91
- var reads = /* @__PURE__ */ new WeakMap();
92
- function readKey(workspaceId, sessionId) {
93
- return `${workspaceId}\0${sessionId}`;
94
- }
95
- function sessionDetailReadMark() {
96
- return lastOrdinal;
97
- }
98
- function readFreshSessionDetail(client, workspaceId, sessionId, options = {}) {
99
- const promise = client.getSession(workspaceId, sessionId, { ...options, fresh: true });
100
- const read = { promise, ordinal: ++lastOrdinal };
101
- let scoped = reads.get(client);
102
- if (!scoped) {
103
- scoped = /* @__PURE__ */ new Map();
104
- reads.set(client, scoped);
105
- }
106
- const key = readKey(workspaceId, sessionId);
107
- scoped.set(key, read);
108
- promise.catch(() => {
109
- if (scoped.get(key) === read) scoped.delete(key);
110
- });
111
- return promise;
112
- }
113
- function joinSessionDetailRead(client, workspaceId, sessionId, mark) {
114
- const read = reads.get(client)?.get(readKey(workspaceId, sessionId));
115
- return read && read.ordinal > mark ? read.promise : null;
116
- }
117
-
118
- // src/hooks/use-session.ts
119
- function isTitleEvent(event) {
120
- return event.type === "session.title_set";
121
- }
122
- function isSessionDetailEvent(event) {
123
- return isTitleEvent(event) || // Description or avatar edits (by a person or the agent) refresh the header.
124
- event.type === "session.profile_set" || // The chat's model, effort or speed changed (for example by the agent).
125
- event.type === "session.model_settings.updated" || event.type.startsWith("session.command.") || event.type.startsWith("session.wait.") || event.type === "session.status.changed" || event.type === "system.update.pending";
126
- }
127
- function useSession(sessionId, options = {}) {
128
- const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } = useEmbeddedSessionRead(options);
129
- const enabled = (options.enabled ?? true) && Boolean(sessionId);
130
- const [override, setOverride] = useState(null);
131
- const nextReadRevision = useRef(0);
132
- const nextReadGeneration = useRef(0);
133
- const beginRead = options.beginRead;
134
- const { run, mutating, mutationError, clearMutationError } = useMutationRunner();
135
- const load = useCallback(
136
- async (signal) => {
137
- if (!sessionId) {
138
- return null;
139
- }
140
- let readGeneration2 = 0;
141
- const fetched = await readFreshSessionDetail(client, workspaceId, sessionId, {
142
- signal,
143
- onRequestStart: () => {
144
- readGeneration2 = beginRead?.() ?? ++nextReadGeneration.current;
145
- }
146
- });
147
- setOverride(null);
148
- return {
149
- session: fetched,
150
- revision: ++nextReadRevision.current,
151
- readGeneration: readGeneration2
152
- };
153
- },
154
- [beginRead, client, workspaceId, sessionId]
155
- );
156
- const { data, loading, error, refresh } = usePolledValue(load, {
157
- pollIntervalMs: options.pollIntervalMs,
158
- enabled
159
- });
160
- useEffect(() => {
161
- if (enabled && workspaceControlEvent) void refresh();
162
- }, [enabled, refresh, workspaceControlEvent]);
163
- useEffect(() => {
164
- if (!sessionId || !enabled) return;
165
- return registerSessionReconciler(sessionId, "session", refresh);
166
- }, [enabled, refresh, registerSessionReconciler, sessionId]);
167
- const retained = useRetainedSessionView(
168
- client,
169
- workspaceId,
170
- sessionId,
171
- "detail",
172
- data?.session ?? null,
173
- { enabled, discard: deniesRetainedView(error) }
174
- );
175
- const base = data?.session ?? null;
176
- const readRevision = data?.revision ?? 0;
177
- const readGeneration = data?.readGeneration ?? 0;
178
- const session = useMemo(
179
- () => base && override && override.id === base.id ? { ...base, title: override.title, titleSource: override.titleSource } : base ?? retained,
180
- [base, override, retained]
181
- );
182
- const sharedEvents = options.events;
183
- const refreshDetail = useCallback(() => void refresh(), [refresh]);
184
- const onTitleEvent = useCallback(
185
- (event) => {
186
- if (sharedEvents?.some(
187
- (item) => item.sessionId === sessionId && !isTitleEvent(item) && isSessionDetailEvent(item) && item.sequence > (base?.lastSequence ?? -1)
188
- )) {
189
- void refresh();
190
- } else if (!isTitleEvent(event)) {
191
- if (!base || event.sequence > base.lastSequence) void refresh();
192
- return;
193
- }
194
- if (!base || event.sequence <= base.lastSequence) {
195
- return;
196
- }
197
- const payload = event.payload ?? {};
198
- const title = payload.title;
199
- if (typeof title !== "string") {
200
- return;
201
- }
202
- const source = payload.source === "user" || payload.source === "agent" ? payload.source : null;
203
- setOverride((current) => {
204
- const next = current ?? base;
205
- return { ...next, title, titleSource: source };
206
- });
207
- },
208
- [base, refresh, sharedEvents, sessionId]
209
- );
210
- useSessionEventTrigger(client, workspaceId, sessionId, isSessionDetailEvent, onTitleEvent, {
211
- enabled,
212
- ...options.events !== void 0 ? { events: options.events } : {},
213
- // The detail row is authoritative through its lastSequence: only a later
214
- // event can make it stale, and one that arrives first waits for the read.
215
- readThrough: base ? base.lastSequence : loading ? "reading" : null,
216
- refresh: refreshDetail
217
- });
218
- const updateTitle = useCallback(
219
- async (title) => {
220
- if (!sessionId) {
221
- return null;
222
- }
223
- const result = await run(() => client.updateSession(workspaceId, sessionId, { title }));
224
- if (result) {
225
- setOverride(result);
226
- }
227
- return result;
228
- },
229
- [client, workspaceId, sessionId, run]
230
- );
231
- return {
232
- session,
233
- loading: loading && retained === null,
234
- error,
235
- readRevision,
236
- readGeneration,
237
- refresh,
238
- updateTitle,
239
- updating: mutating,
240
- mutationError,
241
- clearMutationError
242
- };
243
- }
244
-
245
- // src/older-history.ts
246
- var activeReceiptCapture;
247
- var preserveTailForAutomaticLoad = false;
248
- function invokeOlderHistoryLoaderWithReceiptCapture(load, capture, preserveTail = false) {
249
- const previousCapture = activeReceiptCapture;
250
- const previousPreserveTail = preserveTailForAutomaticLoad;
251
- activeReceiptCapture = capture;
252
- preserveTailForAutomaticLoad = preserveTail;
253
- try {
254
- return load();
255
- } finally {
256
- activeReceiptCapture = previousCapture;
257
- preserveTailForAutomaticLoad = previousPreserveTail;
258
- }
259
- }
260
- function createOlderHistoryLoadReceipt(load) {
261
- let resolveResult;
262
- let rejectResult;
263
- const result = new Promise((resolve, reject) => {
264
- resolveResult = resolve;
265
- rejectResult = reject;
266
- });
267
- result.committed = false;
268
- result.tailPreserved = false;
269
- activeReceiptCapture?.(result);
270
- try {
271
- const loaded = load(
272
- () => {
273
- result.committed = true;
274
- },
275
- preserveTailForAutomaticLoad,
276
- () => {
277
- result.tailPreserved = true;
278
- }
279
- );
280
- Promise.resolve(loaded).then(resolveResult, rejectResult);
281
- } catch (error) {
282
- rejectResult(error);
283
- }
284
- return result;
285
- }
286
-
287
- // src/hooks/use-session-events.ts
288
- import {
289
- isPresentedSessionToolCall,
290
- isRetryableStreamError,
291
- isSessionModelResponsePhase,
292
- isTransientRequestError,
293
- SESSION_EVENT_COMPAT_EXCLUDED_STEP_TYPES,
294
- SESSION_EVENT_CONTENT_STEP_TYPES,
295
- SESSION_EVENT_CONVERSATION_FILTER_VERSION,
296
- SESSION_EVENT_STEP_TYPES,
297
- sessionEventStreamCoveredThrough
298
- } from "@opengeni/sdk";
299
- import { startTransition, useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
300
-
301
- // src/hooks/page-wake.ts
302
- var PAGE_WAKE_CHECK_INTERVAL_MS = 2e3;
303
- var PAGE_WAKE_GAP_MS = 15e3;
304
- var listeners = /* @__PURE__ */ new Set();
305
- var stopDetector = null;
306
- function subscribePageWake(listener) {
307
- listeners.add(listener);
308
- stopDetector ??= startDetector();
309
- return () => {
310
- listeners.delete(listener);
311
- if (listeners.size === 0 && stopDetector) {
312
- stopDetector();
313
- stopDetector = null;
314
- }
315
- };
316
- }
317
- function emitPageWake() {
318
- for (const listener of [...listeners]) {
319
- try {
320
- listener();
321
- } catch {
322
- }
323
- }
324
- }
325
- function startDetector() {
326
- if (typeof window === "undefined" || typeof document === "undefined") return () => {
327
- };
328
- let lastTick = Date.now();
329
- const check = () => {
330
- const now = Date.now();
331
- const elapsed = now - lastTick;
332
- lastTick = now;
333
- if (elapsed > PAGE_WAKE_GAP_MS) emitPageWake();
334
- };
335
- const onVisibility = () => {
336
- if (document.visibilityState !== "hidden") check();
337
- };
338
- const onPageShow = (event) => {
339
- lastTick = Date.now();
340
- if (event.persisted) emitPageWake();
341
- };
342
- const onResume = () => {
343
- lastTick = Date.now();
344
- emitPageWake();
345
- };
346
- const timer = setInterval(check, PAGE_WAKE_CHECK_INTERVAL_MS);
347
- document.addEventListener("visibilitychange", onVisibility);
348
- document.addEventListener("resume", onResume);
349
- window.addEventListener("pageshow", onPageShow);
350
- window.addEventListener("online", onResume);
351
- return () => {
352
- clearInterval(timer);
353
- document.removeEventListener("visibilitychange", onVisibility);
354
- document.removeEventListener("resume", onResume);
355
- window.removeEventListener("pageshow", onPageShow);
356
- window.removeEventListener("online", onResume);
357
- };
358
- }
359
-
360
- // src/hooks/turnless-output-gaps.ts
361
- import { useCallback as useCallback2, useSyncExternalStore } from "react";
362
- var MAX_IDLE_ENTRIES = 256;
363
- var entries = /* @__PURE__ */ new Map();
364
- function gapKey(workspaceId, sessionId) {
365
- return `${workspaceId}\0${sessionId}`;
366
- }
367
- function gapEntry(key) {
368
- let entry = entries.get(key);
369
- if (!entry) {
370
- entry = { generation: 0, listeners: /* @__PURE__ */ new Set() };
371
- entries.set(key, entry);
372
- if (entries.size > MAX_IDLE_ENTRIES) {
373
- for (const [candidate, held] of entries) {
374
- if (entries.size <= MAX_IDLE_ENTRIES) break;
375
- if (candidate !== key && held.listeners.size === 0) entries.delete(candidate);
376
- }
377
- }
378
- }
379
- return entry;
380
- }
381
- function markTurnlessOutputGap(workspaceId, sessionId) {
382
- const entry = gapEntry(gapKey(workspaceId, sessionId));
383
- entry.generation += 1;
384
- for (const listener of [...entry.listeners]) listener();
385
- }
386
- function useTurnlessOutputGap(workspaceId, sessionId) {
387
- const key = sessionId ? gapKey(workspaceId, sessionId) : null;
388
- const subscribe = useCallback2(
389
- (listener) => {
390
- if (!key) return () => {
391
- };
392
- const entry = gapEntry(key);
393
- entry.listeners.add(listener);
394
- return () => {
395
- entry.listeners.delete(listener);
396
- };
397
- },
398
- [key]
399
- );
400
- const read = useCallback2(() => key ? entries.get(key)?.generation ?? 0 : 0, [key]);
401
- return useSyncExternalStore(subscribe, read, read);
402
- }
403
-
404
- // src/hooks/use-session-events.ts
405
- import { errorMessage } from "@opengeni/contracts/values";
406
- var SESSION_FIRST_WINDOW_PAGE_SIZE = 255;
407
- var SESSION_HISTORY_PAGE_SIZE = 1e3;
408
- var INITIAL_FETCH_CAP = 1;
409
- var OLDER_GROUP_TARGET = 32;
410
- var OLDER_FETCH_CAP = 2;
411
- var NEWER_GROUP_TARGET = 32;
412
- var NEWER_FETCH_CAP = 2;
413
- var OLDEST_GROUP_TARGET = 32;
414
- var OLDEST_FETCH_CAP = 2;
415
- var BOUNDARY_PAGE_CAP = 1;
416
- var FILTERED_PAGE_CAP = 32;
417
- var DIRECT_REPLAY_MAX_SEQUENCES = 16;
418
- var CATCHUP_MAX_PAGES = 2;
419
- var STRICT_REJOIN_ATTEMPTS = 5;
420
- var REJOIN_STALL_TIMEOUT_MS = 3e4;
421
- var FOREGROUND_REJOIN_RETRY_MS = 500;
422
- var FOREGROUND_REJOIN_RETRY_MAX_MS = 8e3;
423
- var EMPTY_EVENTS = [];
424
- var encoder = new TextEncoder();
425
- var SESSION_EVENT_BROWSER_MAX_BYTES = 16 * 1024 * 1024;
426
- var SESSION_EVENT_BROWSER_MAX_COUNT = 2e4;
427
- var SESSION_EVENT_BROWSER_PENDING_MAX_BYTES = 1024 * 1024;
428
- var SESSION_EVENT_BROWSER_PENDING_MAX_COUNT = 256;
429
- var EMPTY_EVENT_WINDOW = {
430
- events: EMPTY_EVENTS,
431
- bytes: 2,
432
- truncated: false
433
- };
434
- function useSessionEvents(sessionId, options = {}) {
435
- const t = useOpenGeniText();
436
- const { client, workspaceId, reconcileSession } = useEmbeddedSession(options);
437
- const enabled = options.enabled ?? true;
438
- const pageLive = usePageLiveActivity();
439
- const streamEnabled = enabled && pageLive;
440
- const after = options.after ?? 0;
441
- const replay = options.replay ?? "windowed";
442
- const fullReplay = replay === "full" || after !== 0;
443
- const streamKey = `${workspaceId}\0${sessionId ?? ""}\0${after}\0${fullReplay ? "full" : "windowed"}`;
444
- const navigationIdentityRef = useRef2({ client, streamKey, enabled });
445
- if (navigationIdentityRef.current.client !== client || navigationIdentityRef.current.streamKey !== streamKey || navigationIdentityRef.current.enabled !== enabled) {
446
- navigationIdentityRef.current = { client, streamKey, enabled };
447
- }
448
- const navigationIdentity = navigationIdentityRef.current;
449
- const ownsNavigation = useCallback3(
450
- () => navigationIdentityRef.current === navigationIdentity,
451
- [navigationIdentity]
452
- );
453
- const [eventWindow, setEventWindow] = useState2(EMPTY_EVENT_WINDOW);
454
- const [questionEvidence, setQuestionEvidence] = useState2(null);
455
- const [connectionState, setConnectionState] = useState2("idle");
456
- const [error, setError] = useState2(null);
457
- const [newerError, setNewerError] = useState2(null);
458
- const [hasOlder, setHasOlder] = useState2(false);
459
- const [hasNewer, setHasNewer] = useState2(false);
460
- const [sessionStatusProjection, setSessionStatusProjection] = useState2(
461
- null
462
- );
463
- const [initialLoading, setInitialLoading] = useState2(true);
464
- const [initialHistoryReady, setInitialHistoryReady] = useState2(false);
465
- const [loadingOlder, setLoadingOlder] = useState2(false);
466
- const [loadingNewer, setLoadingNewer] = useState2(false);
467
- const [loadingOldest, setLoadingOldest] = useState2(false);
468
- const [loadingLatest, setLoadingLatest] = useState2(false);
469
- const [loadingTarget, setLoadingTarget] = useState2(false);
470
- const loadingTargetRef = useRef2(false);
471
- const [streamEpoch, setStreamEpoch] = useState2(0);
472
- const [viewMode, setViewMode] = useState2("live");
473
- const lastSequenceRef = useRef2(after);
474
- const streamResumeSequenceRef = useRef2(after);
475
- const skippedStepsThroughRef = useRef2(null);
476
- const oldestSequenceRef = useRef2(null);
477
- const newestSequenceRef = useRef2(null);
478
- const hasOlderRef = useRef2(false);
479
- const hasNewerRef = useRef2(false);
480
- const loadingOlderRef = useRef2(false);
481
- const loadingNewerRef = useRef2(false);
482
- const loadingOldestRef = useRef2(false);
483
- const loadingLatestRef = useRef2(false);
484
- const viewModeRef = useRef2("live");
485
- const initialWindowLoadedRef = useRef2(false);
486
- const openedStreamKeyRef = useRef2(null);
487
- const reconcileAfterPageResumeRef = useRef2(false);
488
- const streamAbortRef = useRef2(null);
489
- const streamKeyRef = useRef2(null);
490
- const generationRef = useRef2(0);
491
- const navigationGenerationRef = useRef2(0);
492
- const eventWindowRef = useRef2(EMPTY_EVENT_WINDOW);
493
- const sessionStatusRef = useRef2({
494
- sequence: after,
495
- status: null
496
- });
497
- const [stateStreamKey, setStateStreamKey] = useState2(streamKey);
498
- const historyFilter = fullReplay ? void 0 : CONVERSATION_FILTER;
499
- const [stepStores, setStepStores] = useState2(EMPTY_STEP_STORES);
500
- const stepStoresRef = useRef2(EMPTY_STEP_STORES);
501
- const [turnlessSteps, setTurnlessSteps] = useState2(EMPTY_TURNLESS_STEPS);
502
- const turnlessStepsRef = useRef2(EMPTY_TURNLESS_STEPS);
503
- const renderedTurnlessRef = useRef2({ appended: 0, marked: false });
504
- useEffect2(() => {
505
- renderedTurnlessRef.current = { appended: turnlessSteps.appended, marked: false };
506
- }, [turnlessSteps]);
507
- const liveThroughRef = useRef2(0);
508
- const stepGenerationRef = useRef2(0);
509
- const stepRequestRef = useRef2(0);
510
- const retainedTurnsRef = useRef2(/* @__PURE__ */ new Map());
511
- const turnStepHandlesRef = useRef2(/* @__PURE__ */ new Map());
512
- const presentedCallIdsRef = useRef2(/* @__PURE__ */ new Set());
513
- const presentedScanRef = useRef2(null);
514
- const startupRef = useRef2(emptyStartupTurns());
515
- const [presentedOutputs, setPresentedOutputs] = useState2(EMPTY_PRESENTED_OUTPUTS);
516
- const presentedRequestedRef = useRef2(/* @__PURE__ */ new Map());
517
- const presentedFailuresRef = useRef2(/* @__PURE__ */ new Map());
518
- const [presentedPass, setPresentedPass] = useState2(0);
519
- const rejoinPendingRef = useRef2(false);
520
- const streamTransientStreakRef = useRef2(null);
521
- const commitStepStores = useCallback3((next) => {
522
- stepStoresRef.current = next;
523
- setStepStores(next);
524
- }, []);
525
- const pruneStepStores = useCallback3(
526
- (window2, sealedBy, rereading = null) => {
527
- const present = windowTurns(window2);
528
- const settled = sealedBy ? settledTurns(sealedBy) : null;
529
- const next = /* @__PURE__ */ new Map();
530
- for (const [turnId, store] of stepStoresRef.current) {
531
- if (present.has(turnId) && (!settled || settled.has(turnId) || turnId === rereading)) {
532
- next.set(turnId, store);
533
- }
534
- }
535
- if (next.size !== stepStoresRef.current.size) commitStepStores(next);
536
- if (sealedBy) {
537
- presentedRequestedRef.current = /* @__PURE__ */ new Map();
538
- } else {
539
- for (const [callId, request] of presentedRequestedRef.current) {
540
- if (request.turnId && !present.has(request.turnId)) {
541
- presentedRequestedRef.current.delete(callId);
542
- }
543
- }
544
- }
545
- setPresentedOutputs((current) => {
546
- let kept = null;
547
- for (const [callId, output] of current) {
548
- if (output.turnId && present.has(output.turnId)) continue;
549
- kept ??= new Map(current);
550
- kept.delete(callId);
551
- }
552
- return kept ?? current;
553
- });
554
- },
555
- [commitStepStores]
556
- );
557
- const presentedCallIds = useCallback3((event) => {
558
- const ids = presentedCallIdsRef.current;
559
- if (event.type === "agent.toolCall.created") {
560
- notePresentedCalls([event], ids);
561
- } else if (event.type === "agent.toolCall.output") {
562
- const payload = event.payload;
563
- const windowEvents = eventWindowRef.current.events;
564
- if (typeof payload?.id === "string" && !ids.has(payload.id) && presentedScanRef.current !== windowEvents) {
565
- presentedScanRef.current = windowEvents;
566
- notePresentedCalls(windowEvents, ids);
567
- }
568
- }
569
- return ids;
570
- }, []);
571
- const startupTurns = useCallback3(() => {
572
- const windowEvents = eventWindowRef.current.events;
573
- if (startupRef.current.window !== windowEvents) {
574
- const state = emptyStartupTurns();
575
- noteStartupTurns(windowEvents, state);
576
- state.window = windowEvents;
577
- startupRef.current = state;
578
- }
579
- return startupRef.current;
580
- }, []);
581
- const appendLiveSteps = useCallback3(
582
- (steps) => {
583
- if (steps.some((event) => !event.turnId)) {
584
- const incoming = steps.filter((event) => !event.turnId);
585
- const turnless = appendTurnlessSteps(turnlessStepsRef.current, incoming);
586
- const rendered = renderedTurnlessRef.current;
587
- if (!rendered.marked && turnless.appended - rendered.appended > turnless.events.length) {
588
- rendered.marked = true;
589
- if (sessionId) markTurnlessOutputGap(workspaceId, sessionId);
590
- }
591
- turnlessStepsRef.current = turnless;
592
- setTurnlessSteps(turnless);
593
- }
594
- const windowEvents = withTurnlessSteps(
595
- eventWindowRef.current.events,
596
- turnlessStepsRef.current
597
- );
598
- const next = new Map(stepStoresRef.current);
599
- const now = Date.now();
600
- for (const [turnId, events] of groupByTurn(steps)) {
601
- const existing = next.get(turnId);
602
- const store = existing ?? {
603
- events: [],
604
- bytes: 2,
605
- // Earlier steps exist when the window skips sequences between the
606
- // turn's start and this first live step.
607
- hasOlder: turnHasHiddenSequences(windowEvents, turnId, events[0].sequence),
608
- cursor: null,
609
- floor: null,
610
- pinned: null,
611
- loading: false,
612
- error: false,
613
- touched: now,
614
- requestId: 0
615
- };
616
- let updated = { ...store, ...appendStepEvents(store, events), touched: now };
617
- if (!retainedTurnsRef.current.get(turnId)) updated = trimLiveStepTail(updated);
618
- next.set(turnId, updated);
619
- }
620
- commitStepStores(boundStepStores(next, retainedTurnsRef.current));
621
- },
622
- [commitStepStores, workspaceId, sessionId]
623
- );
624
- const loadTurnSteps = useCallback3(
625
- (turnId, before) => {
626
- if (!ownsNavigation() || !sessionId || fullReplay) return;
627
- const current = stepStoresRef.current.get(turnId);
628
- const pinnedUpper = before ?? (current?.error && current.pinned !== null ? current.pinned : void 0);
629
- const pinned = pinnedUpper !== void 0;
630
- if (!pinned && current?.loading) return;
631
- const bounds = conversationTurnBounds(eventWindowRef.current.events).get(turnId);
632
- if (!bounds) return;
633
- if (!pinned && current && !stepStoreHasOlder(current, bounds) && !current.error) return;
634
- const upper = pinnedUpper ?? current?.cursor ?? current?.events[0]?.sequence ?? (bounds.terminal !== null ? bounds.terminal + 1 : Number.MAX_SAFE_INTEGER);
635
- const exactStart = bounds.started !== null;
636
- const lower = turnStepLowerBound(bounds);
637
- const generation = stepGenerationRef.current;
638
- const requestId = ++stepRequestRef.current;
639
- const isCurrent = () => ownsNavigation() && generation === stepGenerationRef.current && stepStoresRef.current.get(turnId)?.requestId === requestId;
640
- const base = current ?? {
641
- events: [],
642
- bytes: 2,
643
- hasOlder: true,
644
- cursor: null,
645
- floor: null,
646
- pinned: null,
647
- loading: false,
648
- error: false,
649
- touched: 0,
650
- requestId
651
- };
652
- commitStepStores(
653
- new Map(stepStoresRef.current).set(turnId, {
654
- ...base,
655
- pinned: pinned ? upper : null,
656
- loading: true,
657
- error: false,
658
- touched: Date.now(),
659
- requestId
660
- })
661
- );
662
- void readEventPage(client, workspaceId, sessionId, {
663
- // Bookkeeping too, whichever read built this window: rows it already
664
- // holds (a fallback read keeps them) merge once by id.
665
- includeTypes: [...TURN_STEP_READ_TYPES],
666
- after: Math.max(0, lower),
667
- before: upper,
668
- direction: "before",
669
- limit: SESSION_TURN_STEP_PAGE_SIZE,
670
- compact: true,
671
- payloadMode: "full",
672
- // Large tool outputs arrive as bounded previews; a row reads its
673
- // exact output when the reader needs it (see useToolOutputReads).
674
- toolOutputs: "preview"
675
- }).then(
676
- (page) => {
677
- if (!isCurrent()) return;
678
- const own = page.events.filter((event) => event.turnId === turnId);
679
- const latest = stepStoresRef.current.get(turnId);
680
- const merged = pinned ? appendStepEvents(
681
- { events: [], bytes: 2 },
682
- [...own, ...latest.events.filter((event) => event.sequence >= upper)].sort(
683
- (left, right) => left.sequence - right.sequence
684
- )
685
- ) : appendStepEvents(latest, own);
686
- const oldestOwn = merged.events[0]?.sequence ?? upper;
687
- const passedStart = !exactStart && page.events.some(
688
- (event) => !!event.turnId && event.turnId !== turnId && event.sequence < oldestOwn
689
- );
690
- const moreBelow = !passedStart && (page.hasMore ?? page.events.length > 0);
691
- const reachedFloor = !moreBelow && !passedStart && !exactStart;
692
- const next = new Map(stepStoresRef.current).set(turnId, {
693
- ...merged,
694
- // A page read without a continuation fact (a client without
695
- // listEventPage) offers one more page until a read comes back empty.
696
- hasOlder: moreBelow,
697
- // The next page continues below this page's oldest row, even when
698
- // the page held only other turns' rows, or below the floor.
699
- cursor: reachedFloor ? lower + 1 : page.events.reduce((oldest, event) => Math.min(oldest, event.sequence), upper),
700
- floor: reachedFloor ? lower : null,
701
- pinned: null,
702
- loading: false,
703
- error: false,
704
- touched: Date.now(),
705
- requestId
706
- });
707
- commitStepStores(boundStepStores(next, retainedTurnsRef.current));
708
- },
709
- () => {
710
- if (!isCurrent()) return;
711
- const latest = stepStoresRef.current.get(turnId);
712
- commitStepStores(
713
- new Map(stepStoresRef.current).set(turnId, { ...latest, loading: false, error: true })
714
- );
715
- }
716
- );
717
- },
718
- [client, workspaceId, sessionId, fullReplay, ownsNavigation, commitStepStores]
719
- );
720
- const loadTurnStepsRef = useRef2(loadTurnSteps);
721
- useEffect2(() => {
722
- loadTurnStepsRef.current = loadTurnSteps;
723
- }, [loadTurnSteps]);
724
- const turnStepHandle = useCallback3((turnId) => {
725
- let handle = turnStepHandlesRef.current.get(turnId);
726
- if (!handle) {
727
- const retained = retainedTurnsRef.current;
728
- handle = {
729
- load: () => loadTurnStepsRef.current(turnId),
730
- retain: () => {
731
- retained.set(turnId, (retained.get(turnId) ?? 0) + 1);
732
- let released = false;
733
- return () => {
734
- if (released) return;
735
- released = true;
736
- const count = (retained.get(turnId) ?? 1) - 1;
737
- if (count > 0) retained.set(turnId, count);
738
- else retained.delete(turnId);
739
- };
740
- }
741
- };
742
- turnStepHandlesRef.current.set(turnId, handle);
743
- }
744
- return handle;
745
- }, []);
746
- useEffect2(() => {
747
- navigationGenerationRef.current += 1;
748
- setNewerError(null);
749
- loadingOlderRef.current = false;
750
- loadingNewerRef.current = false;
751
- loadingOldestRef.current = false;
752
- loadingTargetRef.current = false;
753
- setQuestionEvidence(null);
754
- setLoadingTarget(false);
755
- setLoadingOlder(false);
756
- setLoadingNewer(false);
757
- setLoadingOldest(false);
758
- return () => {
759
- navigationGenerationRef.current += 1;
760
- };
761
- }, [client, workspaceId, sessionId, after, enabled, fullReplay]);
762
- useEffect2(() => {
763
- if (streamKeyRef.current !== streamKey) {
764
- streamKeyRef.current = streamKey;
765
- setStateStreamKey(streamKey);
766
- eventWindowRef.current = EMPTY_EVENT_WINDOW;
767
- setEventWindow(EMPTY_EVENT_WINDOW);
768
- setError(null);
769
- setHasOlder(false);
770
- setHasNewer(false);
771
- sessionStatusRef.current = { sequence: after, status: null };
772
- setSessionStatusProjection(null);
773
- setLoadingOlder(false);
774
- setLoadingNewer(false);
775
- setLoadingOldest(false);
776
- setLoadingLatest(false);
777
- setInitialLoading(true);
778
- setInitialHistoryReady(false);
779
- lastSequenceRef.current = after;
780
- streamResumeSequenceRef.current = after;
781
- liveThroughRef.current = after;
782
- skippedStepsThroughRef.current = null;
783
- oldestSequenceRef.current = null;
784
- newestSequenceRef.current = null;
785
- hasOlderRef.current = false;
786
- hasNewerRef.current = false;
787
- loadingOlderRef.current = false;
788
- loadingNewerRef.current = false;
789
- loadingOldestRef.current = false;
790
- loadingLatestRef.current = false;
791
- viewModeRef.current = "live";
792
- setViewMode("live");
793
- initialWindowLoadedRef.current = false;
794
- reconcileAfterPageResumeRef.current = false;
795
- rejoinPendingRef.current = false;
796
- streamTransientStreakRef.current = null;
797
- stepGenerationRef.current += 1;
798
- stepStoresRef.current = EMPTY_STEP_STORES;
799
- setStepStores(EMPTY_STEP_STORES);
800
- turnlessStepsRef.current = EMPTY_TURNLESS_STEPS;
801
- setTurnlessSteps(EMPTY_TURNLESS_STEPS);
802
- turnStepHandlesRef.current = /* @__PURE__ */ new Map();
803
- presentedCallIdsRef.current = /* @__PURE__ */ new Set();
804
- presentedScanRef.current = null;
805
- startupRef.current = emptyStartupTurns();
806
- presentedRequestedRef.current = /* @__PURE__ */ new Map();
807
- presentedFailuresRef.current = /* @__PURE__ */ new Map();
808
- setPresentedOutputs(EMPTY_PRESENTED_OUTPUTS);
809
- }
810
- const generation = generationRef.current + 1;
811
- generationRef.current = generation;
812
- if (!sessionId || !streamEnabled) {
813
- streamTransientStreakRef.current = null;
814
- if (sessionId && enabled && !pageLive && !fullReplay && viewModeRef.current === "live" && initialWindowLoadedRef.current) {
815
- reconcileAfterPageResumeRef.current = true;
816
- }
817
- setConnectionState("idle");
818
- return;
819
- }
820
- if (viewMode === "history") {
821
- reconcileAfterPageResumeRef.current = false;
822
- setConnectionState("idle");
823
- setInitialLoading(false);
824
- return;
825
- }
826
- const reconcileForegroundResume = reconcileAfterPageResumeRef.current && !fullReplay;
827
- reconcileAfterPageResumeRef.current = false;
828
- const controller = new AbortController();
829
- const detailReadMark = sessionDetailReadMark();
830
- const isCurrent = () => generationRef.current === generation && !controller.signal.aborted && navigationIdentityRef.current.client === client && navigationIdentityRef.current.streamKey === streamKey && navigationIdentityRef.current.enabled === enabled;
831
- streamAbortRef.current = controller;
832
- let transientRetryTimer = null;
833
- const scheduleTransientRetry = (delayMs, retry) => {
834
- if (transientRetryTimer !== null) clearTimeout(transientRetryTimer);
835
- transientRetryTimer = setTimeout(() => {
836
- transientRetryTimer = null;
837
- if (isCurrent()) retry();
838
- }, delayMs);
839
- };
840
- let pending = [];
841
- let pendingBytes = 2;
842
- let flushTimer = null;
843
- const flush = () => {
844
- if (flushTimer !== null) {
845
- clearTimeout(flushTimer);
846
- flushTimer = null;
847
- }
848
- if (!isCurrent()) {
849
- pending = [];
850
- pendingBytes = 2;
851
- return;
852
- }
853
- if (pending.length === 0) {
854
- return;
855
- }
856
- const batch = pending;
857
- pending = [];
858
- pendingBytes = 2;
859
- const lastInBatch = batch[batch.length - 1];
860
- if (lastInBatch) {
861
- const batchResumeSequence = Math.max(...batch.map(eventResumeSequence));
862
- lastSequenceRef.current = Math.max(lastSequenceRef.current, batchResumeSequence);
863
- streamResumeSequenceRef.current = Math.max(
864
- streamResumeSequenceRef.current,
865
- batchResumeSequence
866
- );
867
- liveThroughRef.current = Math.max(liveThroughRef.current, batchResumeSequence);
868
- }
869
- const status = observeSessionStatus(batch, sessionStatusRef);
870
- if (status !== void 0) {
871
- setSessionStatusProjection(status);
872
- }
873
- let conversation = batch;
874
- const steps = [];
875
- if (!fullReplay) {
876
- const windowNewest = newestSequenceRef.current ?? 0;
877
- const startup = startupTurns();
878
- conversation = [];
879
- for (const event of batch) {
880
- if (!isConversationHistoryEvent(event, presentedCallIds(event), startup.open)) {
881
- steps.push(event);
882
- } else if (event.sequence > windowNewest) conversation.push(event);
883
- noteStartupTurns([event], startup);
884
- }
885
- }
886
- if (conversation.length > 0) {
887
- const current = eventWindowRef.current;
888
- const next = appendBrowserSessionEventWindow(current, conversation);
889
- const retained = {
890
- ...next,
891
- truncated: current.truncated || next.truncated
892
- };
893
- eventWindowRef.current = retained;
894
- setEventWindow(retained);
895
- if (!fullReplay) startupRef.current.window = retained.events;
896
- oldestSequenceRef.current = retained.events[0]?.sequence ?? null;
897
- newestSequenceRef.current = maxResumeSequenceOrNull(retained.events);
898
- if (retained.truncated) {
899
- hasOlderRef.current = true;
900
- setHasOlder(true);
901
- }
902
- }
903
- if (steps.length > 0) appendLiveSteps(steps);
904
- };
905
- const scheduleFlush = () => {
906
- if (!isCurrent()) return;
907
- flushTimer ??= setTimeout(flush, 16);
908
- };
909
- const installCatchup = (events, head) => {
910
- const current = eventWindowRef.current;
911
- const windowNewest = newestSequenceRef.current ?? 0;
912
- const fresh = events.filter((event) => event.sequence > windowNewest);
913
- const status = observeSessionStatus(fresh, sessionStatusRef);
914
- const next = appendBrowserSessionEventWindow(current, fresh);
915
- const retained = { ...next, truncated: current.truncated || next.truncated };
916
- eventWindowRef.current = retained;
917
- oldestSequenceRef.current = retained.events[0]?.sequence ?? oldestSequenceRef.current;
918
- newestSequenceRef.current = maxResumeSequenceOrNull(retained.events) ?? newestSequenceRef.current;
919
- lastSequenceRef.current = Math.max(lastSequenceRef.current, head);
920
- streamResumeSequenceRef.current = Math.max(streamResumeSequenceRef.current, head);
921
- if (skippedStepsThroughRef.current !== null) {
922
- skippedStepsThroughRef.current = Math.max(skippedStepsThroughRef.current, head);
923
- }
924
- if (status !== void 0) setSessionStatusProjection(status);
925
- if (fresh.length > 0) setEventWindow(retained);
926
- if (retained.truncated) {
927
- hasOlderRef.current = true;
928
- setHasOlder(true);
929
- }
930
- };
931
- const effectScope = { signal: controller.signal, isCurrent };
932
- const readSessionHead = async (mark, scope) => {
933
- const joined = joinSessionDetailRead(client, workspaceId, sessionId, mark);
934
- if (joined) {
935
- try {
936
- return await joined;
937
- } catch (cause) {
938
- if (scope.signal.aborted) throw cause;
939
- }
940
- }
941
- return await client.getSession(workspaceId, sessionId, {
942
- fresh: true,
943
- signal: scope.signal
944
- });
945
- };
946
- const rejoinLive = async (force, {
947
- strict = false,
948
- mark = detailReadMark,
949
- scope = effectScope
950
- } = {}) => {
951
- const activeTurn = activeConversationTurn(eventWindowRef.current.events);
952
- if (!force && !activeTurn) return "joined";
953
- const cursor = streamResumeSequenceRef.current;
954
- let head;
955
- let sessionActiveTurn = null;
956
- try {
957
- const session = await readSessionHead(mark, scope);
958
- scope.progress?.();
959
- head = session.lastSequence;
960
- sessionActiveTurn = session.activeTurnId;
961
- } catch (cause) {
962
- if (!scope.isCurrent() || strict && isRetryableStreamError(cause)) throw cause;
963
- return "joined";
964
- }
965
- if (!scope.isCurrent()) throw abortError();
966
- if (!Number.isSafeInteger(head) || head - cursor <= DIRECT_REPLAY_MAX_SEQUENCES) {
967
- return "joined";
968
- }
969
- let catchup;
970
- try {
971
- catchup = await loadConversationCatchup(
972
- client,
973
- workspaceId,
974
- sessionId,
975
- cursor,
976
- head,
977
- scope
978
- );
979
- } catch (cause) {
980
- if (!scope.isCurrent() || strict && isRetryableStreamError(cause)) throw cause;
981
- return "joined";
982
- }
983
- if (!scope.isCurrent()) throw abortError();
984
- if (catchup === null) return "reload";
985
- const previous = eventWindowRef.current.events;
986
- installCatchup(catchup, head);
987
- const working = sessionActiveTurn ?? activeConversationTurn(eventWindowRef.current.events);
988
- pruneStepStores(eventWindowRef.current.events, previous, working);
989
- if (working) loadTurnStepsRef.current(working, head + 1);
990
- if (working && conversationTurnBounds(eventWindowRef.current.events).has(working)) {
991
- skippedStepsThroughRef.current = null;
992
- }
993
- return "joined";
994
- };
995
- const loadLatestWindow = async (scope = effectScope) => {
996
- const window2 = await loadEventWindow(t, client, workspaceId, sessionId, {
997
- before: Number.MAX_SAFE_INTEGER,
998
- pageSize: SESSION_FIRST_WINDOW_PAGE_SIZE,
999
- targetGroups: Number.POSITIVE_INFINITY,
1000
- maxFetches: INITIAL_FETCH_CAP,
1001
- boundaryPageCap: BOUNDARY_PAGE_CAP,
1002
- signal: scope.signal,
1003
- ...scope.progress ? { progress: scope.progress } : {},
1004
- filter: CONVERSATION_FILTER
1005
- });
1006
- if (!scope.isCurrent()) {
1007
- return false;
1008
- }
1009
- const status = observeSessionStatus(window2.events, sessionStatusRef);
1010
- const retained = boundBrowserSessionEventWindow(window2.events);
1011
- navigationGenerationRef.current += 1;
1012
- loadingOlderRef.current = false;
1013
- loadingNewerRef.current = false;
1014
- loadingOldestRef.current = false;
1015
- setLoadingOlder(false);
1016
- setLoadingNewer(false);
1017
- setLoadingOldest(false);
1018
- const previous = eventWindowRef.current.events;
1019
- eventWindowRef.current = retained;
1020
- pruneStepStores(retained.events, previous);
1021
- oldestSequenceRef.current = retained.events[0]?.sequence ?? window2.oldestSequence ?? window2.scanCursor;
1022
- newestSequenceRef.current = maxResumeSequenceOrNull(retained.events) ?? window2.newestSequence;
1023
- hasOlderRef.current = window2.hasOlder || retained.truncated;
1024
- hasNewerRef.current = false;
1025
- lastSequenceRef.current = Math.max(lastSequenceRef.current, window2.newestSequence);
1026
- streamResumeSequenceRef.current = window2.newestSequence;
1027
- skippedStepsThroughRef.current = retained.events.length === 0 && window2.newestSequence > 0 ? window2.newestSequence : null;
1028
- initialWindowLoadedRef.current = true;
1029
- streamTransientStreakRef.current = null;
1030
- setInitialHistoryReady(true);
1031
- setError(null);
1032
- if (status !== void 0) {
1033
- setSessionStatusProjection(status);
1034
- }
1035
- setEventWindow(retained);
1036
- setHasOlder(window2.hasOlder || retained.truncated);
1037
- setHasNewer(false);
1038
- setInitialLoading(false);
1039
- return true;
1040
- };
1041
- const noteStreamResume = () => {
1042
- if (!fullReplay && streamResumeSequenceRef.current > liveThroughRef.current) {
1043
- markTurnlessOutputGap(workspaceId, sessionId);
1044
- }
1045
- liveThroughRef.current = Math.max(liveThroughRef.current, streamResumeSequenceRef.current);
1046
- };
1047
- const reconcileAfterOpen = (initialOpen, streak = null) => {
1048
- void Promise.resolve().then(() => reconcileSession(sessionId, { initialOpen })).catch((cause) => {
1049
- if (!isCurrent()) return;
1050
- if (isTransientRequestError(cause)) {
1051
- const now = Date.now();
1052
- const current = streak ?? { since: now, attempts: 0, surfaced: false };
1053
- const step = transientReadRetryStep(current, now, DEFAULT_TRANSIENT_READ_RETRY, cause);
1054
- if (step.quiet) {
1055
- scheduleTransientRetry(step.delayMs, () => reconcileAfterOpen(initialOpen, current));
1056
- return;
1057
- }
1058
- }
1059
- setError(normalizeError(cause));
1060
- });
1061
- };
1062
- const boundedRejoin = async (strict, join) => {
1063
- if (!isCurrent()) throw abortError();
1064
- const attempt = new AbortController();
1065
- let timedOut = false;
1066
- const abortAttempt = () => attempt.abort();
1067
- controller.signal.addEventListener("abort", abortAttempt, { once: true });
1068
- const stalled = () => {
1069
- timedOut = true;
1070
- attempt.abort();
1071
- };
1072
- let timer = setTimeout(stalled, REJOIN_STALL_TIMEOUT_MS);
1073
- let stopWaiting;
1074
- const stopped = new Promise((_resolve, reject) => {
1075
- stopWaiting = () => reject(abortError());
1076
- attempt.signal.addEventListener("abort", stopWaiting, { once: true });
1077
- });
1078
- const scope = {
1079
- signal: attempt.signal,
1080
- isCurrent: () => isCurrent() && !attempt.signal.aborted,
1081
- progress: () => {
1082
- if (attempt.signal.aborted) return;
1083
- clearTimeout(timer);
1084
- timer = setTimeout(stalled, REJOIN_STALL_TIMEOUT_MS);
1085
- }
1086
- };
1087
- try {
1088
- return await Promise.race([join(scope), stopped]);
1089
- } catch (cause) {
1090
- if (!isCurrent()) throw cause;
1091
- if (timedOut) {
1092
- return strict ? {
1093
- retry: new TypeError(
1094
- `rejoining the live session stalled for ${REJOIN_STALL_TIMEOUT_MS}ms`
1095
- )
1096
- } : "joined";
1097
- }
1098
- if (strict && isRetryableStreamError(cause)) return { retry: cause };
1099
- throw cause;
1100
- } finally {
1101
- clearTimeout(timer);
1102
- controller.signal.removeEventListener("abort", abortAttempt);
1103
- if (stopWaiting) attempt.signal.removeEventListener("abort", stopWaiting);
1104
- }
1105
- };
1106
- const leniently = async (join) => {
1107
- const result = await boundedRejoin(false, join);
1108
- return typeof result === "string" ? result : "joined";
1109
- };
1110
- let strictFailures = 0;
1111
- const beforeReconnect = async (cursor) => {
1112
- flush();
1113
- if (!isCurrent()) throw abortError();
1114
- const strict = strictFailures < STRICT_REJOIN_ATTEMPTS;
1115
- const mark = sessionDetailReadMark();
1116
- let result;
1117
- try {
1118
- result = await boundedRejoin(strict, async (scope) => {
1119
- if (await rejoinLive(true, { strict, mark, scope }) === "joined") return "joined";
1120
- let loaded;
1121
- try {
1122
- loaded = await loadLatestWindow(scope);
1123
- } catch (cause) {
1124
- if (!scope.isCurrent() || strict && isRetryableStreamError(cause)) throw cause;
1125
- return "joined";
1126
- }
1127
- if (!loaded) throw abortError();
1128
- if (await rejoinLive(true, { strict, mark, scope }) === "reload" && strict) {
1129
- throw new TypeError("the session outran a fresh window while rejoining it");
1130
- }
1131
- return "joined";
1132
- });
1133
- } catch (cause) {
1134
- if (!isCurrent()) throw abortError();
1135
- if (!isRetryableStreamError(cause)) throw cause;
1136
- throw new Error(`rejoining the live session failed: ${errorMessage(cause)}`, { cause });
1137
- }
1138
- if (!isCurrent()) throw abortError();
1139
- if (typeof result === "object") {
1140
- strictFailures += 1;
1141
- throw result.retry;
1142
- }
1143
- noteStreamResume();
1144
- return Math.max(cursor, streamResumeSequenceRef.current);
1145
- };
1146
- void (async () => {
1147
- try {
1148
- if (reconcileForegroundResume) {
1149
- setConnectionState("connecting");
1150
- let outcome;
1151
- for (let attempt = 0; ; attempt += 1) {
1152
- const strict = attempt < STRICT_REJOIN_ATTEMPTS;
1153
- const result = await boundedRejoin(
1154
- strict,
1155
- (scope) => rejoinLive(true, { strict, scope })
1156
- );
1157
- if (typeof result === "string") {
1158
- outcome = result;
1159
- break;
1160
- }
1161
- await abortableDelay(
1162
- Math.min(FOREGROUND_REJOIN_RETRY_MS * 2 ** attempt, FOREGROUND_REJOIN_RETRY_MAX_MS),
1163
- controller.signal
1164
- );
1165
- }
1166
- if (outcome === "reload") {
1167
- initialWindowLoadedRef.current = false;
1168
- setError(null);
1169
- }
1170
- } else if (!fullReplay && initialWindowLoadedRef.current && rejoinPendingRef.current) {
1171
- rejoinPendingRef.current = false;
1172
- if (await leniently((scope) => rejoinLive(false, { scope })) === "reload") {
1173
- initialWindowLoadedRef.current = false;
1174
- }
1175
- }
1176
- rejoinPendingRef.current = false;
1177
- const windowPasses = fullReplay ? 0 : 2;
1178
- for (let attempt = 0; attempt < windowPasses && !initialWindowLoadedRef.current; attempt += 1) {
1179
- setConnectionState("connecting");
1180
- if (!await loadLatestWindow()) {
1181
- return;
1182
- }
1183
- if (await leniently((scope) => rejoinLive(true, { scope })) === "reload" && attempt === 0) {
1184
- initialWindowLoadedRef.current = false;
1185
- }
1186
- }
1187
- if (fullReplay) {
1188
- setInitialLoading(false);
1189
- }
1190
- noteStreamResume();
1191
- const stream = client.streamEvents(workspaceId, sessionId, {
1192
- after: streamResumeSequenceRef.current,
1193
- signal: controller.signal,
1194
- // Full replay keeps the SDK's exactly-once reconnects.
1195
- ...fullReplay ? {} : { beforeReconnect },
1196
- onOpen: () => {
1197
- const initialOpen = openedStreamKeyRef.current !== streamKey;
1198
- openedStreamKeyRef.current = streamKey;
1199
- strictFailures = 0;
1200
- if (streamTransientStreakRef.current?.surfaced) setError(null);
1201
- streamTransientStreakRef.current = null;
1202
- reconcileAfterOpen(initialOpen);
1203
- },
1204
- onStateChange: (state) => {
1205
- if (isCurrent()) {
1206
- setConnectionState(state);
1207
- }
1208
- }
1209
- });
1210
- for await (const event of stream) {
1211
- if (!isCurrent()) break;
1212
- const boundedEvent = event;
1213
- const boundedEventBytes = browserJsonBytes(boundedEvent);
1214
- const separatorBytes = pending.length === 0 ? 0 : 1;
1215
- if (pending.length > 0 && (pending.length >= SESSION_EVENT_BROWSER_PENDING_MAX_COUNT || pendingBytes + separatorBytes + boundedEventBytes > SESSION_EVENT_BROWSER_PENDING_MAX_BYTES)) {
1216
- flush();
1217
- }
1218
- pending.push(boundedEvent);
1219
- pendingBytes += (pending.length === 1 ? 0 : 1) + boundedEventBytes;
1220
- if (pending.length >= SESSION_EVENT_BROWSER_PENDING_MAX_COUNT || pendingBytes >= SESSION_EVENT_BROWSER_PENDING_MAX_BYTES) {
1221
- flush();
1222
- } else {
1223
- scheduleFlush();
1224
- }
1225
- }
1226
- if (isCurrent()) {
1227
- flush();
1228
- setConnectionState("ended");
1229
- }
1230
- } catch (cause) {
1231
- if (isCurrent()) {
1232
- flush();
1233
- let announce = true;
1234
- if (isTransientRequestError(cause)) {
1235
- const now = Date.now();
1236
- const streak = streamTransientStreakRef.current ??= {
1237
- since: now,
1238
- attempts: 0,
1239
- surfaced: false
1240
- };
1241
- const step = transientReadRetryStep(streak, now, DEFAULT_TRANSIENT_READ_RETRY, cause);
1242
- scheduleTransientRetry(step.delayMs, () => setStreamEpoch((epoch) => epoch + 1));
1243
- if (step.quiet) {
1244
- setConnectionState("connecting");
1245
- return;
1246
- }
1247
- announce = !streak.surfaced;
1248
- streak.surfaced = true;
1249
- } else {
1250
- streamTransientStreakRef.current = null;
1251
- }
1252
- if (announce) setError(normalizeError(cause));
1253
- setConnectionState("error");
1254
- setInitialLoading(false);
1255
- }
1256
- }
1257
- })();
1258
- return () => {
1259
- controller.abort();
1260
- if (transientRetryTimer !== null) clearTimeout(transientRetryTimer);
1261
- if (generationRef.current === generation) {
1262
- generationRef.current = generation + 1;
1263
- }
1264
- if (streamAbortRef.current === controller) {
1265
- streamAbortRef.current = null;
1266
- }
1267
- if (flushTimer !== null) {
1268
- clearTimeout(flushTimer);
1269
- }
1270
- };
1271
- }, [
1272
- client,
1273
- workspaceId,
1274
- sessionId,
1275
- after,
1276
- enabled,
1277
- pageLive,
1278
- streamEnabled,
1279
- fullReplay,
1280
- streamKey,
1281
- streamEpoch,
1282
- viewMode,
1283
- reconcileSession,
1284
- t,
1285
- pruneStepStores,
1286
- appendLiveSteps,
1287
- presentedCallIds,
1288
- startupTurns
1289
- ]);
1290
- useEffect2(() => {
1291
- if (!sessionId || !streamEnabled) return;
1292
- return subscribePageWake(() => {
1293
- const stream = streamAbortRef.current;
1294
- if (!stream || stream.signal.aborted || viewModeRef.current !== "live") return;
1295
- if (!fullReplay && initialWindowLoadedRef.current) {
1296
- reconcileAfterPageResumeRef.current = true;
1297
- }
1298
- setStreamEpoch((epoch) => epoch + 1);
1299
- });
1300
- }, [sessionId, streamEnabled, fullReplay]);
1301
- const navigationBusy = () => loadingTargetRef.current || loadingOlderRef.current || loadingNewerRef.current || loadingOldestRef.current || loadingLatestRef.current;
1302
- const loadOlder = useCallback3(
1303
- () => createOlderHistoryLoadReceipt(async (markCommitted, preserveTail, markTailPreserved) => {
1304
- if (!ownsNavigation() || !sessionId || navigationBusy() || !hasOlderRef.current) {
1305
- return false;
1306
- }
1307
- const before = oldestSequenceRef.current;
1308
- if (before === null) {
1309
- oldestSequenceRef.current = null;
1310
- hasOlderRef.current = false;
1311
- setHasOlder(false);
1312
- return false;
1313
- }
1314
- const generation = navigationGenerationRef.current;
1315
- const isCurrent = () => ownsNavigation() && navigationGenerationRef.current === generation;
1316
- loadingOlderRef.current = true;
1317
- setLoadingOlder(true);
1318
- let published = false;
1319
- try {
1320
- const window2 = await loadEventWindow(t, client, workspaceId, sessionId, {
1321
- before,
1322
- pageSize: SESSION_HISTORY_PAGE_SIZE,
1323
- targetGroups: OLDER_GROUP_TARGET,
1324
- maxFetches: OLDER_FETCH_CAP,
1325
- filteredPageCap: FILTERED_PAGE_CAP,
1326
- isCurrent,
1327
- filter: historyFilter
1328
- });
1329
- if (!isCurrent()) {
1330
- return false;
1331
- }
1332
- if (window2.events.length === 0) {
1333
- if (window2.hasOlder && window2.scanCursor < before) {
1334
- oldestSequenceRef.current = window2.scanCursor;
1335
- return true;
1336
- }
1337
- oldestSequenceRef.current = null;
1338
- hasOlderRef.current = false;
1339
- setHasOlder(false);
1340
- return false;
1341
- }
1342
- const current = eventWindowRef.current;
1343
- assertPrependOrder(current.events, window2.events);
1344
- const next = boundBrowserSessionEventWindow([...window2.events, ...current.events], {
1345
- direction: "oldest"
1346
- });
1347
- if (preserveTail && maxResumeSequence(next.events) < maxResumeSequence(current.events)) {
1348
- markTailPreserved();
1349
- return false;
1350
- }
1351
- const status = observeSessionStatus(window2.events, sessionStatusRef);
1352
- const retained = {
1353
- ...next,
1354
- truncated: current.truncated || next.truncated
1355
- };
1356
- const retainedOldest = retained.events[0]?.sequence ?? null;
1357
- if (retainedOldest === null || retainedOldest >= before) {
1358
- throw new Error("@opengeni/react: loadOlder made no durable sequence progress");
1359
- }
1360
- const retainedNewest = maxResumeSequenceOrNull(retained.events);
1361
- const previousNewest = maxResumeSequenceOrNull(current.events);
1362
- const evictedLiveTail = previousNewest !== null && retainedNewest !== null && retainedNewest < previousNewest;
1363
- if (evictedLiveTail && viewModeRef.current === "live") {
1364
- streamAbortRef.current?.abort();
1365
- }
1366
- eventWindowRef.current = retained;
1367
- if (evictedLiveTail) {
1368
- skippedStepsThroughRef.current = null;
1369
- pruneStepStores(retained.events, current.events);
1370
- } else {
1371
- const skippedThrough = skippedStepsThroughRef.current;
1372
- if (skippedThrough !== null && windowTurns(window2.events).size > 0) {
1373
- skippedStepsThroughRef.current = null;
1374
- const working = activeConversationTurn(retained.events);
1375
- const bounds = working ? conversationTurnBounds(retained.events).get(working) : void 0;
1376
- if (working && bounds && bounds.first <= skippedThrough) {
1377
- loadTurnStepsRef.current(working, skippedThrough + 1);
1378
- }
1379
- }
1380
- }
1381
- markCommitted();
1382
- oldestSequenceRef.current = retainedOldest;
1383
- newestSequenceRef.current = retainedNewest;
1384
- if (evictedLiveTail) {
1385
- streamResumeSequenceRef.current = maxResumeSequence(retained.events);
1386
- }
1387
- const olderStillAvailable = window2.hasOlder;
1388
- hasOlderRef.current = olderStillAvailable;
1389
- let newer = null;
1390
- let enterHistory = false;
1391
- if (viewModeRef.current === "history" || evictedLiveTail) {
1392
- const highWater = lastSequenceRef.current;
1393
- newer = retainedNewest !== null && (retainedNewest < highWater || retained.truncated);
1394
- hasNewerRef.current = newer;
1395
- if (evictedLiveTail) {
1396
- viewModeRef.current = "history";
1397
- enterHistory = true;
1398
- }
1399
- }
1400
- loadingOlderRef.current = false;
1401
- startTransition(() => {
1402
- if (status !== void 0) {
1403
- setSessionStatusProjection(status);
1404
- }
1405
- setEventWindow(retained);
1406
- setHasOlder(olderStillAvailable);
1407
- if (newer !== null) {
1408
- setHasNewer(newer);
1409
- }
1410
- if (enterHistory) {
1411
- setViewMode("history");
1412
- }
1413
- setLoadingOlder(false);
1414
- });
1415
- published = true;
1416
- return olderStillAvailable;
1417
- } catch (reason) {
1418
- if (!isCurrent()) return false;
1419
- throw reason;
1420
- } finally {
1421
- if (!published && isCurrent()) {
1422
- loadingOlderRef.current = false;
1423
- setLoadingOlder(false);
1424
- }
1425
- }
1426
- }),
1427
- [client, workspaceId, sessionId, ownsNavigation, t, historyFilter, pruneStepStores]
1428
- );
1429
- const loadOldest = useCallback3(async () => {
1430
- if (!ownsNavigation() || !sessionId || navigationBusy() || !hasOlderRef.current) {
1431
- return false;
1432
- }
1433
- const generation = ++navigationGenerationRef.current;
1434
- const isCurrent = () => ownsNavigation() && navigationGenerationRef.current === generation;
1435
- setQuestionEvidence(null);
1436
- loadingOldestRef.current = true;
1437
- setLoadingOldest(true);
1438
- let published = false;
1439
- try {
1440
- const window2 = await loadForwardEventWindow(t, client, workspaceId, sessionId, {
1441
- after: 0,
1442
- pageSize: SESSION_HISTORY_PAGE_SIZE,
1443
- targetGroups: OLDEST_GROUP_TARGET,
1444
- maxFetches: OLDEST_FETCH_CAP,
1445
- isCurrent,
1446
- filter: historyFilter
1447
- });
1448
- if (!isCurrent()) {
1449
- return false;
1450
- }
1451
- if (window2.events.length === 0) {
1452
- hasOlderRef.current = false;
1453
- setHasOlder(false);
1454
- return false;
1455
- }
1456
- streamAbortRef.current?.abort();
1457
- const status = observeSessionStatus(window2.events, sessionStatusRef);
1458
- const retained = boundBrowserSessionEventWindow(window2.events, { direction: "oldest" });
1459
- const retainedOldest = retained.events[0]?.sequence ?? null;
1460
- const retainedNewest = maxResumeSequenceOrNull(retained.events);
1461
- const previous = eventWindowRef.current.events;
1462
- eventWindowRef.current = retained;
1463
- skippedStepsThroughRef.current = null;
1464
- pruneStepStores(retained.events, previous);
1465
- oldestSequenceRef.current = retainedOldest;
1466
- newestSequenceRef.current = retainedNewest;
1467
- hasOlderRef.current = false;
1468
- const highWater = Math.max(lastSequenceRef.current, retainedNewest ?? 0);
1469
- lastSequenceRef.current = highWater;
1470
- const newer = window2.hasNewer || retained.truncated || retainedNewest !== null && retainedNewest < highWater;
1471
- hasNewerRef.current = newer;
1472
- initialWindowLoadedRef.current = true;
1473
- setInitialHistoryReady(true);
1474
- setError(null);
1475
- viewModeRef.current = "history";
1476
- loadingOldestRef.current = false;
1477
- setNewerError(null);
1478
- startTransition(() => {
1479
- if (status !== void 0) {
1480
- setSessionStatusProjection(status);
1481
- }
1482
- setEventWindow(retained);
1483
- setHasOlder(false);
1484
- setHasNewer(newer);
1485
- setViewMode("history");
1486
- setLoadingOldest(false);
1487
- });
1488
- published = true;
1489
- return newer;
1490
- } catch (reason) {
1491
- if (!isCurrent()) return false;
1492
- throw reason;
1493
- } finally {
1494
- if (!published && isCurrent()) {
1495
- loadingOldestRef.current = false;
1496
- setLoadingOldest(false);
1497
- }
1498
- }
1499
- }, [client, workspaceId, sessionId, ownsNavigation, t, historyFilter, pruneStepStores]);
1500
- const loadNewer = useCallback3(async () => {
1501
- if (!ownsNavigation() || !sessionId || navigationBusy() || !hasNewerRef.current) {
1502
- return false;
1503
- }
1504
- const afterSequence = newestSequenceRef.current;
1505
- if (afterSequence === null) {
1506
- hasNewerRef.current = false;
1507
- setHasNewer(false);
1508
- return false;
1509
- }
1510
- const generation = navigationGenerationRef.current;
1511
- const isCurrent = () => ownsNavigation() && navigationGenerationRef.current === generation;
1512
- loadingNewerRef.current = true;
1513
- setLoadingNewer(true);
1514
- let published = false;
1515
- try {
1516
- const window2 = await loadForwardEventWindow(t, client, workspaceId, sessionId, {
1517
- after: afterSequence,
1518
- pageSize: SESSION_HISTORY_PAGE_SIZE,
1519
- targetGroups: NEWER_GROUP_TARGET,
1520
- maxFetches: NEWER_FETCH_CAP,
1521
- filteredPageCap: FILTERED_PAGE_CAP,
1522
- isCurrent,
1523
- filter: historyFilter
1524
- });
1525
- if (!isCurrent()) {
1526
- return false;
1527
- }
1528
- if (window2.events.length === 0) {
1529
- if (window2.hasNewer && window2.scanCursor > afterSequence) {
1530
- newestSequenceRef.current = window2.scanCursor;
1531
- return true;
1532
- }
1533
- setNewerError(null);
1534
- hasNewerRef.current = false;
1535
- setHasNewer(false);
1536
- streamResumeSequenceRef.current = afterSequence;
1537
- rejoinPendingRef.current = true;
1538
- viewModeRef.current = "live";
1539
- setViewMode("live");
1540
- setStreamEpoch((epoch) => epoch + 1);
1541
- return false;
1542
- }
1543
- const current = eventWindowRef.current;
1544
- assertAppendOrder(current.events, window2.events);
1545
- const status = observeSessionStatus(window2.events, sessionStatusRef);
1546
- const previousOldest = current.events[0]?.sequence ?? null;
1547
- const next = appendBrowserSessionEventWindow(current, window2.events);
1548
- const retained = {
1549
- ...next,
1550
- truncated: current.truncated || next.truncated || window2.hasNewer
1551
- };
1552
- const retainedOldest = retained.events[0]?.sequence ?? null;
1553
- const retainedNewest = maxResumeSequenceOrNull(retained.events);
1554
- if (retainedNewest === null || retainedNewest <= afterSequence) {
1555
- throw new Error("@opengeni/react: loadNewer made no durable sequence progress");
1556
- }
1557
- eventWindowRef.current = retained;
1558
- pruneStepStores(retained.events, null);
1559
- oldestSequenceRef.current = retainedOldest;
1560
- newestSequenceRef.current = retainedNewest;
1561
- if (retainedOldest !== null && (previousOldest === null || retainedOldest > previousOldest || retained.truncated && retained.events[0]?.type !== "session.created" && retainedOldest > 1)) {
1562
- hasOlderRef.current = true;
1563
- }
1564
- const rearmedOlder = hasOlderRef.current;
1565
- const highWater = Math.max(lastSequenceRef.current, retainedNewest);
1566
- lastSequenceRef.current = highWater;
1567
- const newer = window2.hasNewer || retainedNewest < highWater;
1568
- hasNewerRef.current = newer;
1569
- let resumeLive = false;
1570
- if (!newer) {
1571
- streamResumeSequenceRef.current = retainedNewest;
1572
- rejoinPendingRef.current = true;
1573
- viewModeRef.current = "live";
1574
- resumeLive = true;
1575
- }
1576
- loadingNewerRef.current = false;
1577
- setNewerError(null);
1578
- startTransition(() => {
1579
- if (status !== void 0) {
1580
- setSessionStatusProjection(status);
1581
- }
1582
- setEventWindow(retained);
1583
- setHasOlder(rearmedOlder);
1584
- setHasNewer(newer);
1585
- if (resumeLive) {
1586
- setViewMode("live");
1587
- setStreamEpoch((epoch) => epoch + 1);
1588
- }
1589
- setLoadingNewer(false);
1590
- });
1591
- published = true;
1592
- return newer;
1593
- } catch (reason) {
1594
- if (!isCurrent()) {
1595
- return false;
1596
- }
1597
- setNewerError(normalizeError(reason));
1598
- throw reason;
1599
- } finally {
1600
- if (!published && isCurrent()) {
1601
- loadingNewerRef.current = false;
1602
- setLoadingNewer(false);
1603
- }
1604
- }
1605
- }, [client, workspaceId, sessionId, ownsNavigation, t, historyFilter, pruneStepStores]);
1606
- const jumpToSequence = useCallback3(
1607
- async (sequence, navigationOptions) => {
1608
- const signal = navigationOptions?.signal;
1609
- if (!ownsNavigation() || !sessionId || !Number.isSafeInteger(sequence) || sequence < 1)
1610
- return false;
1611
- if (signal?.aborted) return false;
1612
- const generation = ++navigationGenerationRef.current;
1613
- setQuestionEvidence(null);
1614
- const current = () => generation === navigationGenerationRef.current && ownsNavigation();
1615
- const previousMode = viewModeRef.current;
1616
- streamAbortRef.current?.abort();
1617
- generationRef.current += 1;
1618
- viewModeRef.current = "history";
1619
- setViewMode("history");
1620
- loadingOlderRef.current = loadingNewerRef.current = loadingOldestRef.current = false;
1621
- setLoadingOlder(false);
1622
- setLoadingNewer(false);
1623
- setLoadingOldest(false);
1624
- loadingTargetRef.current = true;
1625
- setLoadingTarget(true);
1626
- let published = false;
1627
- try {
1628
- const around = (filter) => Promise.all([
1629
- loadPreviousPage(client, workspaceId, sessionId, sequence + 1, {
1630
- pageSize: 128,
1631
- filter
1632
- }),
1633
- loadNextPage(client, workspaceId, sessionId, sequence, { pageSize: 128, filter })
1634
- ]);
1635
- let [before, following] = await around(historyFilter);
1636
- if (historyFilter && current() && !before.some((event) => event.sequence === sequence)) {
1637
- [before, following] = await around(void 0);
1638
- }
1639
- if (signal?.aborted) return false;
1640
- if (!current()) return false;
1641
- if (!before.some((event) => event.sequence === sequence)) return false;
1642
- const prefix = boundBrowserSessionEventWindow(before, {
1643
- direction: "newest",
1644
- maxBytes: SESSION_EVENT_BROWSER_MAX_BYTES / 2
1645
- });
1646
- const retained = boundBrowserSessionEventWindow([...prefix.events, ...following], {
1647
- direction: "oldest"
1648
- });
1649
- if (!retained.events.some((event) => event.sequence === sequence)) return false;
1650
- streamAbortRef.current?.abort();
1651
- generationRef.current += 1;
1652
- const status = observeSessionStatus(retained.events, sessionStatusRef);
1653
- const previous = eventWindowRef.current.events;
1654
- eventWindowRef.current = retained;
1655
- pruneStepStores(retained.events, previous);
1656
- oldestSequenceRef.current = retained.events[0].sequence;
1657
- newestSequenceRef.current = maxResumeSequenceOrNull(retained.events);
1658
- lastSequenceRef.current = Math.max(lastSequenceRef.current, newestSequenceRef.current ?? 0);
1659
- hasOlderRef.current = !isLogStart(retained.events[0]);
1660
- hasNewerRef.current = following.length > 0 || retained.truncated || (newestSequenceRef.current ?? 0) < lastSequenceRef.current;
1661
- initialWindowLoadedRef.current = true;
1662
- setInitialHistoryReady(true);
1663
- setError(null);
1664
- viewModeRef.current = "history";
1665
- setEventWindow(retained);
1666
- setHasOlder(hasOlderRef.current);
1667
- setHasNewer(hasNewerRef.current);
1668
- setInitialLoading(false);
1669
- setViewMode("history");
1670
- setNewerError(null);
1671
- if (status !== void 0) setSessionStatusProjection(status);
1672
- published = true;
1673
- return true;
1674
- } catch (reason) {
1675
- if (!current() || signal?.aborted) return false;
1676
- throw reason;
1677
- } finally {
1678
- if (current()) {
1679
- loadingTargetRef.current = false;
1680
- setLoadingTarget(false);
1681
- if (!published && previousMode === "live") {
1682
- viewModeRef.current = "live";
1683
- setViewMode("live");
1684
- setStreamEpoch((epoch) => epoch + 1);
1685
- }
1686
- }
1687
- }
1688
- },
1689
- [client, workspaceId, sessionId, ownsNavigation, historyFilter, pruneStepStores]
1690
- );
1691
- const jumpToLatestQuestion = useCallback3(
1692
- async (questionOptions) => {
1693
- if (!sessionId || !ownsNavigation()) return null;
1694
- let generation = navigationGenerationRef.current;
1695
- const current = () => ownsNavigation() && generation === navigationGenerationRef.current;
1696
- try {
1697
- const { resolveLatestQuestion } = await import("./latest-question-OX56OVQ5.js");
1698
- if (!current()) return null;
1699
- const destination = await resolveLatestQuestion(t, {
1700
- client,
1701
- workspaceId,
1702
- sessionId,
1703
- isCurrent: current,
1704
- resumeSequence: maxResumeSequence,
1705
- options: questionOptions
1706
- });
1707
- if (!destination || !current()) return null;
1708
- if (!eventWindowRef.current.events.some((event) => event.sequence === destination.anchor)) {
1709
- const navigation = jumpToSequence(destination.anchor);
1710
- generation = navigationGenerationRef.current;
1711
- if (!await navigation || !current()) return null;
1712
- }
1713
- setQuestionEvidence({
1714
- client,
1715
- streamKey,
1716
- anchor: destination.anchor,
1717
- events: destination.events
1718
- });
1719
- return destination.questionSequence;
1720
- } catch (reason) {
1721
- if (!current()) return null;
1722
- throw reason;
1723
- }
1724
- },
1725
- [client, workspaceId, sessionId, streamKey, ownsNavigation, jumpToSequence, t]
1726
- );
1727
- const jumpToLatest = useCallback3(async () => {
1728
- if (!ownsNavigation()) return;
1729
- if (loadingTargetRef.current) {
1730
- navigationGenerationRef.current += 1;
1731
- loadingTargetRef.current = false;
1732
- setLoadingTarget(false);
1733
- }
1734
- if (!sessionId || navigationBusy()) {
1735
- return;
1736
- }
1737
- navigationGenerationRef.current += 1;
1738
- setQuestionEvidence(null);
1739
- loadingLatestRef.current = true;
1740
- setLoadingLatest(true);
1741
- setNewerError(null);
1742
- setError(null);
1743
- let published = false;
1744
- try {
1745
- streamAbortRef.current?.abort();
1746
- hasNewerRef.current = false;
1747
- hasOlderRef.current = false;
1748
- newestSequenceRef.current = null;
1749
- oldestSequenceRef.current = null;
1750
- eventWindowRef.current = EMPTY_EVENT_WINDOW;
1751
- initialWindowLoadedRef.current = false;
1752
- streamResumeSequenceRef.current = after;
1753
- viewModeRef.current = "live";
1754
- loadingLatestRef.current = false;
1755
- startTransition(() => {
1756
- setHasNewer(false);
1757
- setHasOlder(false);
1758
- setEventWindow(EMPTY_EVENT_WINDOW);
1759
- setInitialLoading(true);
1760
- setViewMode("live");
1761
- setStreamEpoch((epoch) => epoch + 1);
1762
- setLoadingLatest(false);
1763
- });
1764
- published = true;
1765
- await Promise.resolve();
1766
- } finally {
1767
- if (!published) {
1768
- loadingLatestRef.current = false;
1769
- setLoadingLatest(false);
1770
- }
1771
- }
1772
- }, [after, sessionId, ownsNavigation]);
1773
- const identityMatches = stateStreamKey === streamKey;
1774
- const freshTail = identityMatches && initialHistoryReady && viewMode === "live" && !fullReplay ? {
1775
- events: eventWindow.events,
1776
- hasOlder,
1777
- truncated: eventWindow.truncated,
1778
- bytes: eventWindow.bytes,
1779
- sessionStatus: sessionStatusProjection
1780
- } : null;
1781
- const retainedTail = useRetainedSessionView(client, workspaceId, sessionId, "events", freshTail, {
1782
- enabled: !fullReplay,
1783
- bytes: (tail) => tail.bytes,
1784
- budgetBytes: SESSION_EVENT_BROWSER_MAX_BYTES,
1785
- discard: identityMatches && deniesRetainedView(error)
1786
- });
1787
- const showRetained = retainedTail !== null && !(identityMatches && initialHistoryReady);
1788
- const visibleEvents = showRetained ? retainedTail.events : identityMatches ? eventWindow.events : EMPTY_EVENTS;
1789
- const visibleHasOlder = showRetained ? retainedTail.hasOlder : identityMatches && hasOlder;
1790
- const visibleTruncated = showRetained ? retainedTail.truncated : eventWindow.truncated;
1791
- const liveSteps = identityMatches && !showRetained;
1792
- const visibleStepStores = liveSteps ? stepStores : EMPTY_STEP_STORES;
1793
- const visiblePresentedOutputs = liveSteps ? presentedOutputs : EMPTY_PRESENTED_OUTPUTS;
1794
- const visibleTurnless = liveSteps ? turnlessSteps : EMPTY_TURNLESS_STEPS;
1795
- const readToolOutput = useCallback3(
1796
- async (sequence) => sessionId ? (await readEventPage(client, workspaceId, sessionId, {
1797
- includeTypes: ["agent.toolCall.output"],
1798
- after: Math.max(0, sequence - 1),
1799
- before: sequence + 1,
1800
- direction: "after",
1801
- limit: 1,
1802
- payloadMode: "full"
1803
- })).events : [],
1804
- [client, workspaceId, sessionId]
1805
- );
1806
- const toolOutputs = useToolOutputReads(readToolOutput, stepStores);
1807
- const visibleToolOutputs = liveSteps ? toolOutputs.exact : EMPTY_PRESENTED_OUTPUTS;
1808
- const loadedEvents = useMemo2(
1809
- () => mergeLoadedEvents(
1810
- visibleEvents,
1811
- visibleStepStores,
1812
- visiblePresentedOutputs,
1813
- visibleTurnless.events,
1814
- visibleToolOutputs
1815
- ),
1816
- [
1817
- visibleEvents,
1818
- visibleStepStores,
1819
- visiblePresentedOutputs,
1820
- visibleTurnless,
1821
- visibleToolOutputs
1822
- ]
1823
- );
1824
- const turnSteps = useMemo2(() => {
1825
- if (fullReplay) return void 0;
1826
- const markers = /* @__PURE__ */ new Map();
1827
- const bounded = withTurnlessSteps(visibleEvents, visibleTurnless);
1828
- for (const [turnId, bounds] of conversationTurnBounds(bounded)) {
1829
- const store = visibleStepStores.get(turnId);
1830
- if (store && !store.loading && !store.error && !stepStoreHasOlder(store, bounds)) {
1831
- if (!store.events.some((event) => CONTENT_STEP_TYPES.has(event.type))) continue;
1832
- }
1833
- const state = store ? store.loading ? "loading" : store.error ? "error" : stepStoreHasOlder(store, bounds) ? "partial" : "complete" : bounds.hidden ? "idle" : null;
1834
- if (state === null) continue;
1835
- markers.set(turnId, { state, ...liveSteps ? turnStepHandle(turnId) : RETAINED_VIEW_STEPS });
1836
- }
1837
- return markers;
1838
- }, [fullReplay, visibleEvents, visibleTurnless, visibleStepStores, liveSteps, turnStepHandle]);
1839
- const timeline = useMemo2(() => {
1840
- const witness = questionEvidence?.client === client && questionEvidence.streamKey === streamKey && visibleEvents.some((event) => event.sequence === questionEvidence.anchor) ? questionEvidence.events : EMPTY_EVENTS;
1841
- const timelineOptions = {
1842
- partialStart: visibleHasOlder || visibleTruncated || after > 0,
1843
- ...turnSteps ? { turnSteps } : {},
1844
- ...liveSteps ? { toolOutputs: toolOutputs.reader } : {}
1845
- };
1846
- if (witness.length === 0) return buildTimeline(t, loadedEvents, timelineOptions);
1847
- const ids = new Set(loadedEvents.map((event) => event.id));
1848
- return buildTimeline(
1849
- t,
1850
- [...loadedEvents, ...witness.filter((event) => !ids.has(event.id))],
1851
- timelineOptions
1852
- );
1853
- }, [
1854
- loadedEvents,
1855
- visibleEvents,
1856
- visibleHasOlder,
1857
- visibleTruncated,
1858
- after,
1859
- questionEvidence,
1860
- client,
1861
- streamKey,
1862
- turnSteps,
1863
- liveSteps,
1864
- toolOutputs.reader,
1865
- t
1866
- ]);
1867
- useEffect2(() => {
1868
- if (fullReplay || !sessionId || !identityMatches || !initialHistoryReady) return;
1869
- const resolved = new Set(presentedOutputs.keys());
1870
- const collect = (events) => {
1871
- for (const event of events) {
1872
- if (event.type !== "agent.toolCall.output" || isToolOutputPreviewEvent(event)) continue;
1873
- const id = event.payload?.id;
1874
- if (typeof id === "string") resolved.add(id);
1875
- }
1876
- };
1877
- collect(eventWindow.events);
1878
- for (const store of stepStores.values()) collect(store.events);
1879
- const requested = presentedRequestedRef.current;
1880
- let inFlight = 0;
1881
- for (const request of requested.values()) if (request.pending) inFlight += 1;
1882
- const room = PRESENTED_OUTPUT_READS_PER_PASS - inFlight;
1883
- if (room <= 0) return;
1884
- const missing = [];
1885
- for (const event of eventWindow.events) {
1886
- if (event.type !== "agent.toolCall.created") continue;
1887
- const payload = event.payload;
1888
- const callId = payload?.id;
1889
- if (typeof callId !== "string" || resolved.has(callId) || requested.has(callId) || !isPresentedSessionToolCall(payload)) {
1890
- continue;
1891
- }
1892
- missing.push({ callId, sequence: event.sequence, turnId: event.turnId ?? null });
1893
- }
1894
- if (missing.length === 0) return;
1895
- const bounds = conversationTurnBounds(eventWindow.events);
1896
- for (const { callId, sequence, turnId } of missing.slice(-room)) {
1897
- const request = { turnId, pending: true };
1898
- requested.set(callId, request);
1899
- const isCurrent = () => presentedRequestedRef.current === requested && requested.get(callId) === request;
1900
- const terminal = turnId ? bounds.get(turnId)?.terminal ?? null : null;
1901
- void findPresentedOutput(client, workspaceId, sessionId, callId, sequence, terminal).then(
1902
- (output) => {
1903
- if (!ownsNavigation() || !isCurrent()) return;
1904
- request.pending = false;
1905
- if (output) setPresentedOutputs((current) => new Map(current).set(callId, output));
1906
- setPresentedPass((pass) => pass + 1);
1907
- },
1908
- () => {
1909
- if (!isCurrent()) return;
1910
- requested.delete(callId);
1911
- const failures = (presentedFailuresRef.current.get(callId) ?? 0) + 1;
1912
- presentedFailuresRef.current.set(callId, failures);
1913
- if (failures > PRESENTED_OUTPUT_RETRIES) return;
1914
- setTimeout(() => {
1915
- if (ownsNavigation()) setPresentedPass((pass) => pass + 1);
1916
- }, PRESENTED_OUTPUT_RETRY_MS * failures);
1917
- }
1918
- );
1919
- }
1920
- }, [
1921
- fullReplay,
1922
- sessionId,
1923
- identityMatches,
1924
- initialHistoryReady,
1925
- eventWindow,
1926
- stepStores,
1927
- presentedOutputs,
1928
- presentedPass,
1929
- client,
1930
- workspaceId,
1931
- ownsNavigation
1932
- ]);
1933
- return {
1934
- events: loadedEvents,
1935
- timeline,
1936
- sessionStatus: showRetained ? retainedTail.sessionStatus : identityMatches ? sessionStatusProjection : null,
1937
- sessionStatusSequence: identityMatches ? sessionStatusRef.current.sequence : 0,
1938
- connectionState: identityMatches ? connectionState : "idle",
1939
- lastSequence: identityMatches ? lastSequenceRef.current : after,
1940
- windowBytes: identityMatches ? eventWindow.bytes : 2,
1941
- windowTruncated: identityMatches ? eventWindow.truncated : false,
1942
- initialLoading: fullReplay || showRetained ? false : identityMatches ? initialLoading : true,
1943
- initialHistoryReady: identityMatches && initialHistoryReady,
1944
- hasOlder: visibleHasOlder,
1945
- loadingOlder: !identityMatches ? false : loadingOlder,
1946
- loadOlder,
1947
- hasNewer: !identityMatches ? false : hasNewer,
1948
- loadingNewer: !identityMatches ? false : loadingNewer,
1949
- loadNewer,
1950
- loadingOldest: !identityMatches ? false : loadingOldest,
1951
- loadOldest,
1952
- loadingLatest: !identityMatches ? false : loadingLatest,
1953
- jumpToLatest,
1954
- jumpToLatestQuestion,
1955
- jumpToSequence,
1956
- loadingTarget: identityMatches && loadingTarget,
1957
- error: identityMatches ? newerError ?? error : null
1958
- };
1959
- }
1960
- function boundBrowserSessionEventWindow(events, options = {}) {
1961
- const maxBytes = Math.max(1024, options.maxBytes ?? SESSION_EVENT_BROWSER_MAX_BYTES);
1962
- const maxCount = Math.max(1, Math.floor(options.maxCount ?? SESSION_EVENT_BROWSER_MAX_COUNT));
1963
- const safe = events;
1964
- const selected = [];
1965
- let bytes = 2;
1966
- const direction = options.direction ?? "newest";
1967
- const start = direction === "newest" ? safe.length - 1 : 0;
1968
- const end = direction === "newest" ? Math.max(-1, safe.length - maxCount - 1) : safe.length;
1969
- const step = direction === "newest" ? -1 : 1;
1970
- for (let index = start; index !== end && selected.length < maxCount; index += step) {
1971
- const event = safe[index];
1972
- const eventBytes = browserJsonBytes(event);
1973
- const separator = selected.length === 0 ? 0 : 1;
1974
- if (selected.length > 0 && bytes + separator + eventBytes > maxBytes) break;
1975
- selected.push(event);
1976
- bytes += separator + eventBytes;
1977
- }
1978
- if (direction === "newest") selected.reverse();
1979
- return {
1980
- events: selected,
1981
- bytes,
1982
- truncated: selected.length < safe.length
1983
- };
1984
- }
1985
- function appendBrowserSessionEventWindow(current, batch, options = {}) {
1986
- const maxBytes = Math.max(1024, options.maxBytes ?? SESSION_EVENT_BROWSER_MAX_BYTES);
1987
- const maxCount = Math.max(1, Math.floor(options.maxCount ?? SESSION_EVENT_BROWSER_MAX_COUNT));
1988
- const events = [...current.events, ...batch];
1989
- let bytes = current.bytes;
1990
- for (let index = 0; index < batch.length; index += 1) {
1991
- bytes += browserJsonBytes(batch[index]) + (current.events.length + index > 0 ? 1 : 0);
1992
- }
1993
- let start = 0;
1994
- while (events.length - start > 1 && (bytes > maxBytes || events.length - start > maxCount)) {
1995
- bytes -= browserJsonBytes(events[start]) + 1;
1996
- start += 1;
1997
- }
1998
- return {
1999
- events: start === 0 ? events : events.slice(start),
2000
- bytes,
2001
- truncated: current.truncated || start > 0
2002
- };
2003
- }
2004
- function browserJsonBytes(value) {
2005
- return encoder.encode(JSON.stringify(value)).byteLength;
2006
- }
2007
- function observeSessionStatus(events, ref) {
2008
- let latest = null;
2009
- for (const event of events) {
2010
- const status = sessionStatusFromEvents([event]);
2011
- if (status && (!latest || event.sequence >= latest.sequence)) {
2012
- latest = { sequence: event.sequence, status };
2013
- }
2014
- }
2015
- if (!latest || latest.sequence < ref.current.sequence) return void 0;
2016
- ref.current = latest;
2017
- return latest.status;
2018
- }
2019
- async function loadConversationCatchup(client, workspaceId, sessionId, cursor, head, options) {
2020
- const events = [];
2021
- let after = cursor;
2022
- for (let fetch = 0; fetch < CATCHUP_MAX_PAGES; fetch += 1) {
2023
- if (options.signal?.aborted) throw abortError();
2024
- const page = await readConversationPage(client, workspaceId, sessionId, {
2025
- after,
2026
- before: head + 1,
2027
- direction: "after",
2028
- limit: SESSION_HISTORY_PAGE_SIZE,
2029
- compact: true,
2030
- payloadMode: "full"
2031
- });
2032
- if (!options.isCurrent()) throw abortError();
2033
- options.progress?.();
2034
- const fresh = page.filter((event) => eventResumeSequence(event) > after);
2035
- assertAscending(fresh);
2036
- events.push(...fresh);
2037
- if (page.raw.newest === null || page.raw.newest <= after) return events;
2038
- after = page.raw.newest;
2039
- if (after >= head || page.hasMore === false) return events;
2040
- }
2041
- return null;
2042
- }
2043
- async function loadEventWindow(t, client, workspaceId, sessionId, options) {
2044
- let cursor = options.before;
2045
- let buffer = [];
2046
- let reachedStart = false;
2047
- let fetches = 0;
2048
- let filteredPages = 0;
2049
- let rawNewest = 0;
2050
- const counts = (page) => {
2051
- rawNewest = Math.max(rawNewest, page.raw.newest ?? 0);
2052
- return page.length > 0 || (filteredPages += 1) > (options.filteredPageCap ?? 0);
2053
- };
2054
- while (fetches < options.maxFetches) {
2055
- if (buffer.length > 0 && groupCount(t, buffer) >= options.targetGroups) {
2056
- break;
2057
- }
2058
- const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {
2059
- pageSize: options.pageSize,
2060
- filter: options.filter,
2061
- ...options.signal ? { signal: options.signal } : {}
2062
- });
2063
- if (options.isCurrent?.() === false) throw abortError();
2064
- options.progress?.();
2065
- if (page.raw.oldest === null) {
2066
- reachedStart = true;
2067
- break;
2068
- }
2069
- if (counts(page)) fetches += 1;
2070
- assertAscending(page);
2071
- buffer = [...page, ...buffer];
2072
- cursor = page.raw.oldest;
2073
- if (page.raw.oldest <= 1 || page[0] !== void 0 && isLogStart(page[0])) {
2074
- reachedStart = true;
2075
- break;
2076
- }
2077
- }
2078
- let snapPages = 0;
2079
- while (!reachedStart && findBoundaryIndex(buffer) === -1 && snapPages < (options.boundaryPageCap ?? 0)) {
2080
- const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {
2081
- pageSize: options.pageSize,
2082
- filter: options.filter,
2083
- ...options.signal ? { signal: options.signal } : {}
2084
- });
2085
- if (options.isCurrent?.() === false) throw abortError();
2086
- options.progress?.();
2087
- if (page.raw.oldest === null) {
2088
- reachedStart = true;
2089
- break;
2090
- }
2091
- if (counts(page)) {
2092
- fetches += 1;
2093
- snapPages += 1;
2094
- }
2095
- assertAscending(page);
2096
- buffer = [...page, ...buffer];
2097
- cursor = page.raw.oldest;
2098
- if (page.raw.oldest <= 1 || page[0] !== void 0 && isLogStart(page[0])) {
2099
- reachedStart = true;
2100
- break;
2101
- }
2102
- }
2103
- if (!reachedStart) {
2104
- const boundary = findBoundaryIndex(buffer);
2105
- if (boundary > 0) {
2106
- buffer = buffer.slice(boundary);
2107
- }
2108
- }
2109
- const densityWindow = trimBackwardToGroupTarget(t, buffer, options.targetGroups);
2110
- buffer = densityWindow.events;
2111
- const oldest = buffer[0] ?? null;
2112
- const newest = buffer[buffer.length - 1] ?? null;
2113
- return {
2114
- events: buffer,
2115
- oldestSequence: oldest?.sequence ?? null,
2116
- // A window that kept nothing resumes a live stream above the rows it read,
2117
- // not at the start of history. Otherwise rows dropped above its newest
2118
- // kept row are replayed (or caught up) into their turn's steps, so a
2119
- // working turn's latest tool calls still show.
2120
- newestSequence: newest ? maxResumeSequence(buffer) : rawNewest,
2121
- // An empty window that stopped before the start is still pageable.
2122
- hasOlder: buffer.length > 0 ? densityWindow.trimmed || !reachedStart && oldest?.type !== "session.created" : !reachedStart,
2123
- scanCursor: cursor
2124
- };
2125
- }
2126
- function findBoundaryIndex(events) {
2127
- for (let index = 0; index < events.length; index += 1) {
2128
- if (isTurnBoundary(events[index])) {
2129
- return index;
2130
- }
2131
- }
2132
- return -1;
2133
- }
2134
- function isTurnBoundary(event) {
2135
- return event.type === "session.created" || event.type === "user.message";
2136
- }
2137
- async function loadForwardEventWindow(t, client, workspaceId, sessionId, options) {
2138
- let cursor = options.after;
2139
- let buffer = [];
2140
- let fetches = 0;
2141
- let reachedEnd = false;
2142
- let filteredPages = 0;
2143
- while (fetches < options.maxFetches) {
2144
- if (buffer.length > 0 && groupCount(t, buffer) >= options.targetGroups) {
2145
- break;
2146
- }
2147
- const page = await loadNextPage(client, workspaceId, sessionId, cursor, {
2148
- pageSize: options.pageSize,
2149
- filter: options.filter,
2150
- ...options.signal ? { signal: options.signal } : {}
2151
- });
2152
- if (options.isCurrent?.() === false) throw abortError();
2153
- if (page.raw.newest === null) {
2154
- reachedEnd = true;
2155
- break;
2156
- }
2157
- if (page.length > 0 || (filteredPages += 1) > (options.filteredPageCap ?? 0)) fetches += 1;
2158
- assertAscending(page);
2159
- buffer = [...buffer, ...page];
2160
- cursor = page.raw.newest;
2161
- }
2162
- const densityWindow = trimForwardToGroupTarget(t, buffer, options.targetGroups);
2163
- buffer = densityWindow.events;
2164
- const oldest = buffer[0] ?? null;
2165
- const newest = buffer[buffer.length - 1] ?? null;
2166
- return {
2167
- events: buffer,
2168
- oldestSequence: oldest?.sequence ?? null,
2169
- newestSequence: newest ? maxResumeSequence(buffer) : 0,
2170
- // An empty window that stopped before the end is still pageable.
2171
- hasNewer: buffer.length > 0 ? densityWindow.trimmed || !reachedEnd : !reachedEnd,
2172
- scanCursor: cursor
2173
- };
2174
- }
2175
- function trimBackwardToGroupTarget(t, events, targetGroups) {
2176
- if (!Number.isFinite(targetGroups) || targetGroups <= 0 || events.length === 0) {
2177
- return { events, trimmed: false };
2178
- }
2179
- for (let index = events.length - 1; index > 0; index -= 1) {
2180
- if (!isTurnBoundary(events[index])) continue;
2181
- const candidate = events.slice(index);
2182
- if (groupCount(t, candidate) >= targetGroups) {
2183
- return { events: candidate, trimmed: true };
2184
- }
2185
- }
2186
- return { events, trimmed: false };
2187
- }
2188
- function trimForwardToGroupTarget(t, events, targetGroups) {
2189
- if (!Number.isFinite(targetGroups) || targetGroups <= 0 || events.length === 0) {
2190
- return { events, trimmed: false };
2191
- }
2192
- for (let index = 1; index < events.length; index += 1) {
2193
- if (!isTurnBoundary(events[index])) continue;
2194
- const candidate = events.slice(0, index);
2195
- if (groupCount(t, candidate) >= targetGroups) {
2196
- return { events: candidate, trimmed: true };
2197
- }
2198
- }
2199
- return { events, trimmed: false };
2200
- }
2201
- function rawPageExtent(events) {
2202
- return events.length === 0 ? { oldest: null, newest: null } : { oldest: events[0].sequence, newest: maxResumeSequence(events) };
2203
- }
2204
- function historyPage(events, requested, raw = rawPageExtent(events)) {
2205
- return Object.assign(events, { requested, raw });
2206
- }
2207
- async function loadPreviousPage(client, workspaceId, sessionId, before, options) {
2208
- if (options.signal?.aborted) {
2209
- throw abortError();
2210
- }
2211
- const requested = options.pageSize;
2212
- if (requested === 0) {
2213
- return historyPage([], requested);
2214
- }
2215
- const read = {
2216
- before,
2217
- limit: requested,
2218
- compact: true,
2219
- // Monitoring summaries omit correlation fields once a bounded durable
2220
- // payload exceeds their preview threshold. The browser timeline needs the
2221
- // exact stored payload so persisted tool outputs still match their
2222
- // calls and expose truthful truncation telemetry after a reload.
2223
- payloadMode: "full"
2224
- };
2225
- const page = options.filter ? await readConversationPage(client, workspaceId, sessionId, read) : historyPage(await client.listEvents(workspaceId, sessionId, read), requested);
2226
- if (options.signal?.aborted) {
2227
- throw abortError();
2228
- }
2229
- return Object.assign(page, { requested });
2230
- }
2231
- async function loadNextPage(client, workspaceId, sessionId, after, options) {
2232
- if (options.signal?.aborted) {
2233
- throw abortError();
2234
- }
2235
- const requested = options.pageSize;
2236
- if (requested === 0) {
2237
- return historyPage([], requested);
2238
- }
2239
- const read = {
2240
- ...options.before !== void 0 ? { before: options.before } : {},
2241
- after,
2242
- limit: requested,
2243
- compact: true,
2244
- direction: "after",
2245
- payloadMode: "full"
2246
- };
2247
- const page = options.filter ? await readConversationPage(client, workspaceId, sessionId, read) : historyPage(await client.listEvents(workspaceId, sessionId, read), requested);
2248
- if (options.signal?.aborted) {
2249
- throw abortError();
2250
- }
2251
- return Object.assign(page, { requested });
2252
- }
2253
- function groupCount(t, events) {
2254
- if (events.length === 0) {
2255
- return 0;
2256
- }
2257
- return groupTimeline(t, buildTimeline(t, events)).length;
2258
- }
2259
- function isLogStart(event) {
2260
- return event.type === "session.created" || event.sequence <= 1;
2261
- }
2262
- function maxResumeSequence(events) {
2263
- return events.reduce((max, event) => Math.max(max, eventResumeSequence(event)), 0);
2264
- }
2265
- function maxResumeSequenceOrNull(events) {
2266
- return events.length > 0 ? maxResumeSequence(events) : null;
2267
- }
2268
- function eventResumeSequence(event) {
2269
- const streamedCoverage = sessionEventStreamCoveredThrough(event);
2270
- if (streamedCoverage !== null) return streamedCoverage;
2271
- return typeof event.coveredThrough === "number" && Number.isSafeInteger(event.coveredThrough) && event.coveredThrough >= event.sequence ? event.coveredThrough : event.sequence;
2272
- }
2273
- function assertAscending(events) {
2274
- for (let index = 1; index < events.length; index += 1) {
2275
- if (events[index - 1].sequence >= events[index].sequence) {
2276
- throw new Error("@opengeni/react: session events must be ordered by ascending sequence");
2277
- }
2278
- }
2279
- }
2280
- function assertPrependOrder(existing, older) {
2281
- if (!shouldAssertDevelopment() || existing.length === 0 || older.length === 0) {
2282
- return;
2283
- }
2284
- if (older[older.length - 1].sequence >= existing[0].sequence) {
2285
- throw new Error("@opengeni/react: loadOlder returned overlapping session events");
2286
- }
2287
- }
2288
- function assertAppendOrder(existing, newer) {
2289
- if (!shouldAssertDevelopment() || existing.length === 0 || newer.length === 0) {
2290
- return;
2291
- }
2292
- if (newer[0].sequence <= existing[existing.length - 1].sequence) {
2293
- throw new Error("@opengeni/react: loadNewer returned overlapping session events");
2294
- }
2295
- }
2296
- function shouldAssertDevelopment() {
2297
- const processEnv = globalThis.process?.env;
2298
- return processEnv !== void 0 && processEnv.NODE_ENV !== "production";
2299
- }
2300
- function abortError() {
2301
- const error = new Error("The operation was aborted.");
2302
- error.name = "AbortError";
2303
- return error;
2304
- }
2305
- function abortableDelay(ms, signal) {
2306
- return new Promise((resolve, reject) => {
2307
- if (signal.aborted) {
2308
- reject(abortError());
2309
- return;
2310
- }
2311
- const onAbort = () => {
2312
- clearTimeout(timer);
2313
- reject(abortError());
2314
- };
2315
- const timer = setTimeout(() => {
2316
- signal.removeEventListener("abort", onAbort);
2317
- resolve();
2318
- }, ms);
2319
- signal.addEventListener("abort", onAbort, { once: true });
2320
- });
2321
- }
2322
- var CONTENT_STEP_TYPES = new Set(SESSION_EVENT_CONTENT_STEP_TYPES);
2323
- var COMPAT_EXCLUDED_TYPES = new Set(
2324
- SESSION_EVENT_COMPAT_EXCLUDED_STEP_TYPES
2325
- );
2326
- var CONVERSATION_FILTER = "conversation";
2327
- var SESSION_TURN_STEP_PAGE_SIZE = 200;
2328
- var SESSION_TURN_LIVE_STEP_TAIL = 200;
2329
- var SESSION_TURN_LIVE_STEP_TAIL_BYTES = 2 * 1024 * 1024;
2330
- var TURNLESS_STEP_TAIL = 1e3;
2331
- var TURNLESS_STEP_TAIL_BYTES = 4 * 1024 * 1024;
2332
- var TURN_STEP_READ_TYPES = SESSION_EVENT_STEP_TYPES.filter(
2333
- (type) => type !== "terminal.pty.output.delta"
2334
- );
2335
- var SESSION_STEP_BROWSER_MAX_BYTES = 16 * 1024 * 1024;
2336
- var TERMINAL_TURN_TYPES = /* @__PURE__ */ new Set([
2337
- "turn.completed",
2338
- "turn.failed",
2339
- "turn.cancelled",
2340
- "turn.superseded"
2341
- ]);
2342
- var EMPTY_STEP_STORES = /* @__PURE__ */ new Map();
2343
- var EMPTY_TURNLESS_STEPS = { events: [], bytes: 2, ranges: [], appended: 0 };
2344
- var TURNLESS_STEP_MAX_RANGES = 4096;
2345
- function appendTurnlessSteps(current, incoming) {
2346
- const ranges = current.ranges.map((range) => [range[0], range[1]]);
2347
- for (const event of incoming) {
2348
- const sequence = event.sequence;
2349
- const last = ranges.at(-1);
2350
- if (last && sequence >= last[0] && sequence <= last[1]) continue;
2351
- if (last && sequence === last[1] + 1) last[1] = sequence;
2352
- else if (!last || sequence > last[1]) ranges.push([sequence, sequence]);
2353
- else if (!ranges.some(([first, end]) => sequence >= first && sequence <= end)) {
2354
- ranges.push([sequence, sequence]);
2355
- ranges.sort((left, right) => left[0] - right[0]);
2356
- }
2357
- }
2358
- if (ranges.length > TURNLESS_STEP_MAX_RANGES) {
2359
- ranges.splice(0, ranges.length - TURNLESS_STEP_MAX_RANGES);
2360
- }
2361
- const next = appendStepEvents(current, incoming);
2362
- const appended = current.appended + incoming.length;
2363
- if (next.events.length <= TURNLESS_STEP_TAIL && next.bytes <= TURNLESS_STEP_TAIL_BYTES) {
2364
- return { ...next, ranges, appended };
2365
- }
2366
- const kept = boundBrowserSessionEventWindow(next.events, {
2367
- maxCount: TURNLESS_STEP_TAIL,
2368
- maxBytes: TURNLESS_STEP_TAIL_BYTES
2369
- });
2370
- return { events: kept.events, bytes: kept.bytes, ranges, appended };
2371
- }
2372
- function withTurnlessSteps(window2, turnless) {
2373
- const first = window2[0]?.sequence;
2374
- if (first === void 0 || turnless.ranges.length === 0) return window2;
2375
- const placeholders = [];
2376
- for (const [start, end] of turnless.ranges) {
2377
- if (end < first) continue;
2378
- placeholders.push({
2379
- id: `turnless-steps-${start}`,
2380
- workspaceId: window2[0].workspaceId,
2381
- sessionId: window2[0].sessionId,
2382
- sequence: start,
2383
- coveredThrough: end,
2384
- type: "terminal.pty.output.delta",
2385
- payload: null,
2386
- occurredAt: window2[0].occurredAt,
2387
- turnId: null
2388
- });
2389
- }
2390
- if (placeholders.length === 0) return window2;
2391
- return [...window2, ...placeholders].sort((left, right) => left.sequence - right.sequence);
2392
- }
2393
- function turnStepLowerBound(bounds) {
2394
- return bounds.started !== null ? bounds.started - 1 : bounds.previous;
2395
- }
2396
- function stepStoreHasOlder(store, bounds) {
2397
- return store.hasOlder || store.floor !== null && turnStepLowerBound(bounds) < store.floor;
2398
- }
2399
- function isConversationHistoryEvent(event, presentedCallIds, startupTurns) {
2400
- if (event.turnId) {
2401
- if (event.type === "agent.model.usage") return startupTurns === void 0;
2402
- if (event.type === "agent.model.request") {
2403
- return startupTurns === void 0 || startupTurns.has(event.turnId);
2404
- }
2405
- }
2406
- if (!CONTENT_STEP_TYPES.has(event.type)) return true;
2407
- const payload = event.payload;
2408
- if (event.type === "agent.toolCall.created") return isPresentedSessionToolCall(payload);
2409
- if (event.type === "agent.toolCall.output") {
2410
- return typeof payload?.id === "string" && presentedCallIds.has(payload.id);
2411
- }
2412
- return false;
2413
- }
2414
- function emptyStartupTurns() {
2415
- return { window: null, open: /* @__PURE__ */ new Set(), responded: /* @__PURE__ */ new Set() };
2416
- }
2417
- function noteStartupTurns(events, state) {
2418
- for (const event of events) {
2419
- const turnId = event.turnId;
2420
- if (!turnId) continue;
2421
- if (event.type === "turn.started") {
2422
- if (!state.responded.has(turnId)) state.open.add(turnId);
2423
- } else if (event.type === "agent.model.request" && isSessionModelResponsePhase(event.payload?.phase)) {
2424
- state.open.delete(turnId);
2425
- state.responded.add(turnId);
2426
- }
2427
- }
2428
- }
2429
- var conversationFilterModes = /* @__PURE__ */ new WeakMap();
2430
- var CONVERSATION_READS = {
2431
- v2: { excludeTypes: [...SESSION_EVENT_STEP_TYPES], presentedToolCalls: "include" },
2432
- compat: {
2433
- excludeTypes: [...SESSION_EVENT_COMPAT_EXCLUDED_STEP_TYPES],
2434
- presentedToolCalls: "include"
2435
- }
2436
- };
2437
- function conversationFilterMode(client) {
2438
- if (typeof client.listEventPage !== "function") {
2439
- return "compat";
2440
- }
2441
- return conversationFilterModes.get(client) ?? "v2";
2442
- }
2443
- async function readConversationPage(client, workspaceId, sessionId, options) {
2444
- let mode = conversationFilterMode(client);
2445
- for (; ; ) {
2446
- const read = await readEventPage(client, workspaceId, sessionId, {
2447
- ...CONVERSATION_READS[mode],
2448
- ...options
2449
- });
2450
- const announced = (read.conversationFilter ?? 0) >= SESSION_EVENT_CONVERSATION_FILTER_VERSION;
2451
- if (read.conversationFilter !== void 0) {
2452
- conversationFilterModes.set(client, announced ? "v2" : "compat");
2453
- }
2454
- if (mode === "v2" && !announced) {
2455
- mode = "compat";
2456
- continue;
2457
- }
2458
- const events = mode === "compat" ? read.events.filter(isCompatConversationEvent) : read.events;
2459
- return Object.assign(events === read.events ? [...events] : events, {
2460
- requested: options.limit,
2461
- raw: rawPageExtent(read.events),
2462
- hasMore: read.hasMore
2463
- });
2464
- }
2465
- }
2466
- function isCompatConversationEvent(event) {
2467
- if (COMPAT_EXCLUDED_TYPES.has(event.type)) return false;
2468
- if (event.type !== "agent.toolCall.created") return true;
2469
- return isPresentedSessionToolCall(event.payload);
2470
- }
2471
- function notePresentedCalls(events, ids) {
2472
- for (const event of events) {
2473
- if (event.type !== "agent.toolCall.created") continue;
2474
- const payload = event.payload;
2475
- if (typeof payload?.id === "string" && isPresentedSessionToolCall(payload)) {
2476
- ids.add(payload.id);
2477
- }
2478
- }
2479
- }
2480
- function conversationTurnBounds(events) {
2481
- const bounds = /* @__PURE__ */ new Map();
2482
- const gaps = [];
2483
- let expected = null;
2484
- let previous = 0;
2485
- for (const event of events) {
2486
- if (expected !== null && event.sequence > expected) gaps.push(expected);
2487
- const resume = eventResumeSequence(event);
2488
- expected = Math.max(expected ?? 0, resume + 1);
2489
- const turnId = event.turnId;
2490
- if (!turnId) continue;
2491
- const current = bounds.get(turnId);
2492
- if (!current) {
2493
- bounds.set(turnId, {
2494
- first: event.sequence,
2495
- started: event.type === "turn.started" ? event.sequence : null,
2496
- previous,
2497
- last: resume,
2498
- terminal: TERMINAL_TURN_TYPES.has(event.type) ? event.sequence : null,
2499
- hidden: false
2500
- });
2501
- } else {
2502
- current.last = Math.max(current.last, resume);
2503
- if (event.type === "turn.started" && current.started === null) {
2504
- current.started = event.sequence;
2505
- }
2506
- if (TERMINAL_TURN_TYPES.has(event.type)) current.terminal = event.sequence;
2507
- }
2508
- if (!PRE_START_TURN_TYPES.has(event.type)) previous = resume;
2509
- }
2510
- for (const turn of bounds.values()) {
2511
- let low = 0;
2512
- let high = gaps.length;
2513
- while (low < high) {
2514
- const middle = low + high >> 1;
2515
- if (gaps[middle] <= turn.first) low = middle + 1;
2516
- else high = middle;
2517
- }
2518
- turn.hidden = low < gaps.length && gaps[low] < turn.last;
2519
- }
2520
- return bounds;
2521
- }
2522
- function activeConversationTurn(events) {
2523
- for (let index = events.length - 1; index >= 0; index -= 1) {
2524
- const event = events[index];
2525
- if (!event.turnId) continue;
2526
- if (TERMINAL_TURN_TYPES.has(event.type)) return null;
2527
- if (event.type === "turn.started") return event.turnId;
2528
- }
2529
- return null;
2530
- }
2531
- function settledTurns(events) {
2532
- const settled = /* @__PURE__ */ new Set();
2533
- for (const event of events) {
2534
- if (event.turnId && TERMINAL_TURN_TYPES.has(event.type)) settled.add(event.turnId);
2535
- }
2536
- return settled;
2537
- }
2538
- function windowTurns(events) {
2539
- const turns = /* @__PURE__ */ new Set();
2540
- for (const event of events) if (event.turnId) turns.add(event.turnId);
2541
- return turns;
2542
- }
2543
- var EMPTY_PRESENTED_OUTPUTS = /* @__PURE__ */ new Map();
2544
- var PRE_START_TURN_TYPES = /* @__PURE__ */ new Set(["turn.queued", "turn.capacity_waiting"]);
2545
- var PRESENTED_OUTPUT_READS_PER_PASS = 8;
2546
- var PRESENTED_OUTPUT_PAGE_SIZE = 16;
2547
- var PRESENTED_OUTPUT_MAX_PAGES = 16;
2548
- var PRESENTED_OUTPUT_RETRIES = 3;
2549
- var PRESENTED_OUTPUT_RETRY_MS = 2e3;
2550
- var RETAINED_VIEW_STEPS = {
2551
- load: () => {
2552
- },
2553
- retain: () => () => {
2554
- }
2555
- };
2556
- function mergeLoadedEvents(conversation, stores, presented, turnless, exactOutputs = EMPTY_PRESENTED_OUTPUTS) {
2557
- if (stores.size === 0 && presented.size === 0 && turnless.length === 0 && exactOutputs.size === 0) {
2558
- return conversation;
2559
- }
2560
- const turns = windowTurns(conversation);
2561
- const ids = new Set(conversation.map((event) => event.id));
2562
- const extra = [];
2563
- const add = (event) => {
2564
- if (ids.has(event.id) || !event.turnId || !turns.has(event.turnId)) return;
2565
- ids.add(event.id);
2566
- extra.push(event);
2567
- };
2568
- presented.forEach(add);
2569
- exactOutputs.forEach(add);
2570
- for (const [turnId, store] of stores) if (turns.has(turnId)) store.events.forEach(add);
2571
- for (const event of turnless) {
2572
- if (ids.has(event.id)) continue;
2573
- ids.add(event.id);
2574
- extra.push(event);
2575
- }
2576
- if (extra.length === 0) return conversation;
2577
- return [...conversation, ...extra].sort((left, right) => left.sequence - right.sequence);
2578
- }
2579
- function groupByTurn(events) {
2580
- const turns = /* @__PURE__ */ new Map();
2581
- for (const event of events) {
2582
- if (!event.turnId) continue;
2583
- const list = turns.get(event.turnId);
2584
- if (list) list.push(event);
2585
- else turns.set(event.turnId, [event]);
2586
- }
2587
- return turns;
2588
- }
2589
- function appendStepEvents(store, incoming) {
2590
- if (incoming.length === 0) return { events: store.events, bytes: store.bytes };
2591
- const ids = new Set(store.events.map((event) => event.id));
2592
- let bytes = store.bytes;
2593
- const fresh = [];
2594
- for (const event of incoming) {
2595
- if (ids.has(event.id)) continue;
2596
- ids.add(event.id);
2597
- fresh.push(event);
2598
- bytes += browserJsonBytes(event) + (store.events.length + fresh.length > 1 ? 1 : 0);
2599
- }
2600
- if (fresh.length === 0) return { events: store.events, bytes: store.bytes };
2601
- const last = store.events[store.events.length - 1];
2602
- const events = [...store.events, ...fresh];
2603
- if (last && fresh.some((event) => event.sequence < last.sequence)) {
2604
- events.sort((left, right) => left.sequence - right.sequence);
2605
- } else if (!last) {
2606
- events.sort((left, right) => left.sequence - right.sequence);
2607
- }
2608
- return { events, bytes };
2609
- }
2610
- function turnHasHiddenSequences(events, turnId, before) {
2611
- const start = events.findIndex((event) => event.turnId === turnId);
2612
- if (start < 0) return true;
2613
- let expected = eventResumeSequence(events[start]) + 1;
2614
- for (let index = start + 1; index < events.length; index += 1) {
2615
- const event = events[index];
2616
- if (event.sequence >= before) break;
2617
- if (event.sequence > expected) return true;
2618
- expected = Math.max(expected, eventResumeSequence(event) + 1);
2619
- }
2620
- return expected < before;
2621
- }
2622
- function trimLiveStepTail(store) {
2623
- if (store.events.length <= SESSION_TURN_LIVE_STEP_TAIL && store.bytes <= SESSION_TURN_LIVE_STEP_TAIL_BYTES) {
2624
- return store;
2625
- }
2626
- const kept = boundBrowserSessionEventWindow(store.events, {
2627
- maxCount: SESSION_TURN_LIVE_STEP_TAIL,
2628
- maxBytes: SESSION_TURN_LIVE_STEP_TAIL_BYTES
2629
- });
2630
- return { ...store, events: kept.events, bytes: kept.bytes, hasOlder: true, cursor: null };
2631
- }
2632
- function boundStepStores(stores, retained) {
2633
- let total = 0;
2634
- for (const [turnId, store] of stores) {
2635
- if (!retained.get(turnId)) total += store.bytes;
2636
- }
2637
- if (total <= SESSION_STEP_BROWSER_MAX_BYTES) return stores;
2638
- const candidates = [...stores].filter(([turnId, store]) => !retained.get(turnId) && !store.loading).sort((left, right) => left[1].touched - right[1].touched);
2639
- for (const [turnId, store] of candidates) {
2640
- if (total <= SESSION_STEP_BROWSER_MAX_BYTES) break;
2641
- stores.delete(turnId);
2642
- total -= store.bytes;
2643
- }
2644
- return stores;
2645
- }
2646
- async function findPresentedOutput(client, workspaceId, sessionId, callId, after, terminal) {
2647
- let cursor = after;
2648
- for (let page = 0; page < PRESENTED_OUTPUT_MAX_PAGES; page += 1) {
2649
- const read = await readEventPage(client, workspaceId, sessionId, {
2650
- includeTypes: ["agent.toolCall.output"],
2651
- after: cursor,
2652
- ...terminal !== null ? { before: terminal + 1 } : {},
2653
- direction: "after",
2654
- limit: PRESENTED_OUTPUT_PAGE_SIZE,
2655
- payloadMode: "full"
2656
- });
2657
- const output = read.events.find(
2658
- (event) => event.payload?.id === callId
2659
- );
2660
- if (output) return output;
2661
- const last = read.events.at(-1);
2662
- if (!last || !(read.hasMore ?? read.events.length >= PRESENTED_OUTPUT_PAGE_SIZE)) return null;
2663
- cursor = last.sequence;
2664
- }
2665
- return null;
2666
- }
2667
- async function readEventPage(client, workspaceId, sessionId, options) {
2668
- const pageClient = client;
2669
- if (typeof pageClient.listEventPage === "function") {
2670
- const page = await pageClient.listEventPage(workspaceId, sessionId, options);
2671
- return {
2672
- events: page.events,
2673
- hasMore: page.hasMore,
2674
- // An SDK that predates the announcement reports nothing: treat it as none.
2675
- conversationFilter: page.conversationFilter ?? null
2676
- };
2677
- }
2678
- return { events: await client.listEvents(workspaceId, sessionId, options), hasMore: null };
2679
- }
2680
-
2681
- // src/hooks/use-turn-queue.ts
2682
- import { isTransientRequestError as isTransientRequestError2 } from "@opengeni/sdk";
2683
- import { useCallback as useCallback4, useEffect as useEffect3, useLayoutEffect, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
2684
- function isTurnQueueEvent(event) {
2685
- return event.type.startsWith("turn.") || event.type.startsWith("session.queue.") || event.type.startsWith("session.control.") || event.type.startsWith("system.update.") || event.type.startsWith("workspace.inference.");
2686
- }
2687
- function queueSnapshotCovers(candidate, observed) {
2688
- return Boolean(
2689
- candidate && candidate.version >= observed.version && candidate.effectiveControl.controlVersion >= observed.effectiveControl.controlVersion
2690
- );
2691
- }
2692
- var EMPTY_PENDING_BY_TURN = {};
2693
- function useTurnQueue(sessionId, options = {}) {
2694
- const t = useOpenGeniText();
2695
- const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } = useEmbeddedSession(options);
2696
- const enabled = (options.enabled ?? true) && Boolean(sessionId);
2697
- const targetKey = `${workspaceId}\0${sessionId ?? ""}`;
2698
- const pageLive = usePageLiveActivity();
2699
- const pageLiveRef = useRef3(pageLive);
2700
- pageLiveRef.current = pageLive;
2701
- const [snapshot, setSnapshot] = useState3(null);
2702
- const [stateTargetKey, setStateTargetKey] = useState3(targetKey);
2703
- const [loading, setLoading] = useState3(enabled);
2704
- const [error, setError] = useState3(null);
2705
- const [mutationError, setMutationError] = useState3(null);
2706
- const [pendingByTurn, setPendingByTurn] = useState3({});
2707
- const [acceptedSteers, setAcceptedSteers] = useState3([]);
2708
- const pendingRef = useRef3({});
2709
- const readGeneration = useRef3(0);
2710
- const targetKeyRef = useRef3(targetKey);
2711
- const snapshotRef = useRef3(null);
2712
- const transientStreakRef = useRef3(
2713
- null
2714
- );
2715
- const transientRetryTimerRef = useRef3(null);
2716
- const cancelTransientRetry = useCallback4(() => {
2717
- if (transientRetryTimerRef.current !== null) {
2718
- clearTimeout(transientRetryTimerRef.current);
2719
- transientRetryTimerRef.current = null;
2720
- }
2721
- }, []);
2722
- useLayoutEffect(() => {
2723
- if (targetKeyRef.current === targetKey) return;
2724
- targetKeyRef.current = targetKey;
2725
- readGeneration.current += 1;
2726
- snapshotRef.current = null;
2727
- pendingRef.current = {};
2728
- setStateTargetKey(targetKey);
2729
- setSnapshot(null);
2730
- setLoading(enabled);
2731
- setError(null);
2732
- transientStreakRef.current = null;
2733
- cancelTransientRetry();
2734
- setMutationError(null);
2735
- setPendingByTurn({});
2736
- setAcceptedSteers([]);
2737
- }, [cancelTransientRetry, enabled, targetKey]);
2738
- useEffect3(() => {
2739
- if (acceptedSteers.length === 0 || options.events === void 0) return;
2740
- const durablyConsumedTurnIds = new Set(
2741
- options.events.flatMap(
2742
- (event) => [
2743
- "turn.started",
2744
- "turn.superseded",
2745
- "turn.cancelled",
2746
- "turn.failed",
2747
- "turn.completed"
2748
- ].includes(event.type) && event.turnId ? [event.turnId] : []
2749
- )
2750
- );
2751
- if (durablyConsumedTurnIds.size === 0) return;
2752
- setAcceptedSteers(
2753
- (current) => current.filter((steer) => !durablyConsumedTurnIds.has(steer.turnId))
2754
- );
2755
- }, [acceptedSteers.length, options.events]);
2756
- const acceptSnapshot = useCallback4(
2757
- (ownedTargetKey, next) => {
2758
- if (targetKeyRef.current !== ownedTargetKey) return false;
2759
- const current = snapshotRef.current;
2760
- if (next && current && (next.version < current.version || next.effectiveControl.controlVersion < current.effectiveControl.controlVersion)) {
2761
- return false;
2762
- }
2763
- snapshotRef.current = next;
2764
- setStateTargetKey(ownedTargetKey);
2765
- setSnapshot(next);
2766
- return true;
2767
- },
2768
- []
2769
- );
2770
- const load = useCallback4(
2771
- async (rejectOnFailure = false, fresh = false) => {
2772
- if (!sessionId) return;
2773
- const ownedTargetKey = `${workspaceId}\0${sessionId}`;
2774
- const ticket = ++readGeneration.current;
2775
- try {
2776
- const fetched = fresh ? await client.getQueue(workspaceId, sessionId, { fresh: true }) : await client.getQueue(workspaceId, sessionId);
2777
- if (targetKeyRef.current !== ownedTargetKey) return;
2778
- transientStreakRef.current = null;
2779
- cancelTransientRetry();
2780
- const ownsLatestRead = ticket === readGeneration.current;
2781
- if (rejectOnFailure) {
2782
- const committed = acceptSnapshot(ownedTargetKey, fetched);
2783
- if (!committed && !queueSnapshotCovers(snapshotRef.current, fetched)) {
2784
- throw new TypeError("Queue reconciliation did not commit authoritative state");
2785
- }
2786
- setError(null);
2787
- if (ownsLatestRead) setLoading(false);
2788
- } else if (ownsLatestRead) {
2789
- acceptSnapshot(ownedTargetKey, fetched);
2790
- setError(null);
2791
- setLoading(false);
2792
- }
2793
- } catch (cause) {
2794
- if (targetKeyRef.current === ownedTargetKey && (ticket === readGeneration.current || rejectOnFailure)) {
2795
- if (isTransientRequestError2(cause)) {
2796
- const now = Date.now();
2797
- const streak = transientStreakRef.current ??= {
2798
- since: now,
2799
- attempts: 0,
2800
- surfaced: false
2801
- };
2802
- const step = transientReadRetryStep(streak, now, DEFAULT_TRANSIENT_READ_RETRY, cause);
2803
- if (!step.quiet) {
2804
- if (!streak.surfaced) setError(asError(cause));
2805
- streak.surfaced = true;
2806
- if (ticket === readGeneration.current) setLoading(false);
2807
- }
2808
- if (!rejectOnFailure && pageLiveRef.current) {
2809
- cancelTransientRetry();
2810
- transientRetryTimerRef.current = setTimeout(() => {
2811
- transientRetryTimerRef.current = null;
2812
- if (targetKeyRef.current === ownedTargetKey) void loadRef.current(false, fresh);
2813
- }, step.delayMs);
2814
- }
2815
- } else {
2816
- transientStreakRef.current = null;
2817
- setError(asError(cause));
2818
- if (ticket === readGeneration.current) setLoading(false);
2819
- }
2820
- }
2821
- if (rejectOnFailure) throw cause;
2822
- }
2823
- },
2824
- [client, workspaceId, sessionId, acceptSnapshot, cancelTransientRetry]
2825
- );
2826
- const loadRef = useRef3(load);
2827
- loadRef.current = load;
2828
- useEffect3(() => cancelTransientRetry, [cancelTransientRetry]);
2829
- useEffect3(() => {
2830
- if (!enabled || !pageLive) {
2831
- cancelTransientRetry();
2832
- setLoading(false);
2833
- return;
2834
- }
2835
- setLoading(true);
2836
- const pollIntervalMs = options.pollIntervalMs;
2837
- if (pollIntervalMs === void 0 || pollIntervalMs <= 0) {
2838
- void load();
2839
- return () => {
2840
- readGeneration.current += 1;
2841
- };
2842
- }
2843
- let cancelled = false;
2844
- let timer = null;
2845
- const schedule = () => {
2846
- if (cancelled) return;
2847
- timer = setTimeout(() => {
2848
- timer = null;
2849
- void load().finally(schedule);
2850
- }, pollIntervalMs);
2851
- };
2852
- void load().finally(schedule);
2853
- return () => {
2854
- cancelled = true;
2855
- if (timer !== null) clearTimeout(timer);
2856
- readGeneration.current += 1;
2857
- };
2858
- }, [cancelTransientRetry, load, enabled, pageLive, options.pollIntervalMs]);
2859
- const loadFresh = useCallback4(() => load(false, true), [load]);
2860
- useEffect3(() => {
2861
- if (enabled && workspaceControlEvent) void loadFresh();
2862
- }, [enabled, loadFresh, workspaceControlEvent]);
2863
- useEffect3(() => {
2864
- if (!sessionId || !enabled) return;
2865
- return registerSessionReconciler(sessionId, "queue", loadFresh);
2866
- }, [enabled, loadFresh, registerSessionReconciler, sessionId]);
2867
- const scheduleRefresh = useDebouncedCallback(() => void loadFresh());
2868
- const freshSnapshot = stateTargetKey === targetKey ? snapshot : null;
2869
- const freshLoading = stateTargetKey === targetKey ? loading : enabled;
2870
- useSessionEventTrigger(
2871
- client,
2872
- workspaceId,
2873
- sessionId,
2874
- isTurnQueueEvent,
2875
- scheduleRefresh,
2876
- {
2877
- enabled,
2878
- ...options.events !== void 0 ? { events: options.events } : {},
2879
- readThrough: projectionReadThrough(freshSnapshot, freshLoading),
2880
- refresh: scheduleRefresh
2881
- },
2882
- async () => await load(true, true)
2883
- );
2884
- const retainedSnapshot = useRetainedSessionView(
2885
- client,
2886
- workspaceId,
2887
- sessionId,
2888
- "queue",
2889
- freshSnapshot,
2890
- { enabled, discard: stateTargetKey === targetKey && deniesRetainedView(error) }
2891
- );
2892
- const mutate = useCallback4(
2893
- async (turnId, kind, command, failure = {}) => {
2894
- const ownedTargetKey = targetKey;
2895
- if (!sessionId || targetKeyRef.current !== ownedTargetKey || pendingRef.current[turnId]) {
2896
- return null;
2897
- }
2898
- const current = snapshotRef.current;
2899
- const turn = current?.items.find((candidate) => candidate.id === turnId);
2900
- if (!current || !turn) return null;
2901
- pendingRef.current = { ...pendingRef.current, [turnId]: kind };
2902
- setStateTargetKey(ownedTargetKey);
2903
- setPendingByTurn(pendingRef.current);
2904
- setMutationError(null);
2905
- const clientEventId = operationKey();
2906
- try {
2907
- let result;
2908
- try {
2909
- result = await command(current, turn, clientEventId);
2910
- } catch (cause) {
2911
- if (!isOutcomeUnknownError(cause)) throw cause;
2912
- result = await command(current, turn, clientEventId);
2913
- }
2914
- if (targetKeyRef.current !== ownedTargetKey) return null;
2915
- acceptSnapshot(ownedTargetKey, result.snapshot);
2916
- return result;
2917
- } catch (cause) {
2918
- if (targetKeyRef.current === ownedTargetKey) {
2919
- if (failure.quietWhenGone) {
2920
- await loadFresh();
2921
- const stillWaiting = snapshotRef.current?.items.some(
2922
- (candidate) => candidate.id === turnId
2923
- );
2924
- if (stillWaiting !== false && targetKeyRef.current === ownedTargetKey) {
2925
- setMutationError(asError(cause));
2926
- }
2927
- } else {
2928
- setMutationError(asError(cause));
2929
- await loadFresh();
2930
- }
2931
- }
2932
- return null;
2933
- } finally {
2934
- if (targetKeyRef.current === ownedTargetKey && turnId in pendingRef.current) {
2935
- const next = { ...pendingRef.current };
2936
- delete next[turnId];
2937
- pendingRef.current = next;
2938
- setPendingByTurn(next);
2939
- }
2940
- }
2941
- },
2942
- [acceptSnapshot, loadFresh, sessionId, targetKey]
2943
- );
2944
- const moveTurn = useCallback4(
2945
- async (turnId, beforeTurnId) => {
2946
- const result = await mutate(
2947
- turnId,
2948
- "move",
2949
- (current, _turn, clientEventId) => client.moveQueueItem(workspaceId, sessionId, turnId, {
2950
- clientEventId,
2951
- expectedQueueVersion: current.version,
2952
- beforeTurnId
2953
- })
2954
- );
2955
- return result !== null;
2956
- },
2957
- [client, mutate, sessionId, workspaceId]
2958
- );
2959
- const editTurn = useCallback4(
2960
- async (turnId, edit) => {
2961
- const result = await mutate(
2962
- turnId,
2963
- "edit",
2964
- (_current, turn, clientEventId) => client.editQueueItem(workspaceId, sessionId, turnId, {
2965
- clientEventId,
2966
- expectedTurnVersion: turn.version,
2967
- expectedDraftRevision: edit.expectedDraftRevision,
2968
- replaceDraft: edit.replaceDraft
2969
- })
2970
- );
2971
- return result?.draft ?? null;
2972
- },
2973
- [client, mutate, sessionId, workspaceId]
2974
- );
2975
- const recallTurn = useCallback4(
2976
- async (turnId, recall) => {
2977
- const ownedTargetKey = targetKey;
2978
- const known = snapshotRef.current?.items.some((candidate) => candidate.id === turnId);
2979
- if (known === false) return { status: "already_sent" };
2980
- const result = await mutate(
2981
- turnId,
2982
- "edit",
2983
- (_current, turn, clientEventId) => client.editQueueItem(workspaceId, sessionId, turnId, {
2984
- clientEventId,
2985
- expectedTurnVersion: turn.version,
2986
- expectedDraftRevision: recall.expectedDraftRevision,
2987
- replaceDraft: false
2988
- }),
2989
- { quietWhenGone: true }
2990
- );
2991
- if (targetKeyRef.current !== ownedTargetKey) return { status: "failed" };
2992
- if (result?.draft) return { status: "recalled", draft: result.draft };
2993
- const stillWaiting = snapshotRef.current?.items.some((candidate) => candidate.id === turnId);
2994
- return result === null && stillWaiting === false ? { status: "already_sent" } : { status: "failed" };
2995
- },
2996
- [client, mutate, sessionId, targetKey, workspaceId]
2997
- );
2998
- const steerTurn = useCallback4(
2999
- async (turnId) => {
3000
- const ownedTargetKey = targetKey;
3001
- const turn = snapshotRef.current?.items.find((candidate) => candidate.id === turnId);
3002
- if (targetKeyRef.current !== ownedTargetKey) return false;
3003
- if (!turn) {
3004
- setMutationError(new Error(t("hooks.useTurnQueue.thatQueuedPromptChangedBefore")));
3005
- await loadFresh();
3006
- return false;
3007
- }
3008
- const optimistic = {
3009
- turnId: turn.id,
3010
- triggerEventId: turn.triggerEventId,
3011
- text: turn.prompt,
3012
- annotations: turn.annotations ?? [],
3013
- resources: turn.resources,
3014
- tools: turn.tools,
3015
- occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
3016
- state: "sending"
3017
- };
3018
- setAcceptedSteers((current) => [
3019
- ...current.filter((steer) => steer.turnId !== turnId),
3020
- optimistic
3021
- ]);
3022
- const result = await mutate(
3023
- turnId,
3024
- "steer",
3025
- (current, queuedTurn, clientEventId) => client.steerQueueItem(workspaceId, sessionId, turnId, {
3026
- clientEventId,
3027
- expectedTurnVersion: queuedTurn.version,
3028
- controlEtag: current.effectiveControl.controlEtag
3029
- })
3030
- );
3031
- if (targetKeyRef.current !== ownedTargetKey) return false;
3032
- const advancedWithoutSteer = result === null && snapshotRef.current !== null && !snapshotRef.current.items.some((candidate) => candidate.id === turnId);
3033
- if (advancedWithoutSteer) {
3034
- setMutationError(null);
3035
- setAcceptedSteers((current) => current.filter((steer) => steer.turnId !== turnId));
3036
- return true;
3037
- }
3038
- const accepted = result !== null || snapshotRef.current?.items.some(
3039
- (candidate) => candidate.id === turnId && candidate.metadata.delivery === "steer"
3040
- ) === true;
3041
- setAcceptedSteers(
3042
- (current) => accepted ? current.map(
3043
- (steer) => steer.turnId === turnId ? { ...steer, state: "queued" } : steer
3044
- ) : current.filter((steer) => steer.turnId !== turnId)
3045
- );
3046
- return accepted;
3047
- },
3048
- [client, loadFresh, mutate, sessionId, targetKey, workspaceId, t]
3049
- );
3050
- const removeTurn = useCallback4(
3051
- async (turnId) => {
3052
- const result = await mutate(
3053
- turnId,
3054
- "delete",
3055
- (_current, turn, clientEventId) => client.deleteQueueItem(workspaceId, sessionId, turnId, {
3056
- clientEventId,
3057
- expectedTurnVersion: turn.version,
3058
- reason: "Deleted from the prompt queue"
3059
- })
3060
- );
3061
- return result !== null;
3062
- },
3063
- [client, mutate, sessionId, workspaceId]
3064
- );
3065
- const identityMatches = stateTargetKey === targetKey;
3066
- const visibleSnapshot = freshSnapshot ?? retainedSnapshot;
3067
- const visiblePendingByTurn = identityMatches ? pendingByTurn : EMPTY_PENDING_BY_TURN;
3068
- const mutating = useMemo3(
3069
- () => Object.keys(visiblePendingByTurn).length > 0,
3070
- [visiblePendingByTurn]
3071
- );
3072
- const mutationFor = useCallback4(
3073
- (turnId) => visiblePendingByTurn[turnId] ?? null,
3074
- [visiblePendingByTurn]
3075
- );
3076
- return {
3077
- snapshot: visibleSnapshot,
3078
- queue: visibleSnapshot?.items ?? [],
3079
- pendingInputs: visibleSnapshot?.pendingInputs ?? [],
3080
- pendingInputAttachment: visibleSnapshot?.pendingInputAttachment ?? null,
3081
- activePersonalConnections: visibleSnapshot?.activePersonalConnections ?? [],
3082
- effectiveControl: visibleSnapshot?.effectiveControl ?? null,
3083
- stoppingPreviousAttempt: visibleSnapshot?.stoppingPreviousAttempt ?? false,
3084
- loading: freshLoading && retainedSnapshot === null,
3085
- error: identityMatches ? error : null,
3086
- refresh: load,
3087
- moveTurn,
3088
- editTurn,
3089
- recallTurn,
3090
- steerTurn,
3091
- removeTurn,
3092
- pendingByTurn: visiblePendingByTurn,
3093
- mutationFor,
3094
- mutating,
3095
- mutationError: identityMatches ? mutationError : null,
3096
- clearMutationError: useCallback4(() => {
3097
- if (targetKeyRef.current === targetKey) setMutationError(null);
3098
- }, [targetKey]),
3099
- acceptedSteers: identityMatches ? acceptedSteers : []
3100
- };
3101
- }
3102
- function operationKey() {
3103
- return globalThis.crypto.randomUUID();
3104
- }
3105
- function asError(cause) {
3106
- return normalizeError(cause);
3107
- }
3108
- function isOutcomeUnknownError(cause) {
3109
- return typeof cause === "object" && cause !== null && cause.outcomeUnknown === true;
3110
- }
3111
-
3112
- // src/hooks/use-goal.ts
3113
- import {
3114
- OpenGeniApiError,
3115
- observedSessionSequence
3116
- } from "@opengeni/sdk";
3117
- import { useCallback as useCallback5, useEffect as useEffect4, useLayoutEffect as useLayoutEffect2, useRef as useRef4, useState as useState4 } from "react";
3118
- function isGoalEvent(event) {
3119
- return event.type.startsWith("goal.");
3120
- }
3121
- function isGoalRefreshEvent(event) {
3122
- const type = event.type;
3123
- return isGoalEvent(event) || type.startsWith("turn.") || type.startsWith("session.") || type.startsWith("system.update.") || type.startsWith("workspace.inference.") || type.startsWith("user.");
3124
- }
3125
- function useGoal(sessionId, options = {}) {
3126
- const { client, workspaceId } = useEmbeddedGoal(options);
3127
- const enabled = (options.enabled ?? true) && Boolean(sessionId);
3128
- const sharedEvents = options.events;
3129
- const sharedFeed = sharedEvents !== void 0;
3130
- const pageLive = usePageLiveActivity();
3131
- const [goal, setGoal] = useState4(null);
3132
- const [loading, setLoading] = useState4(enabled);
3133
- const [error, setError] = useState4(null);
3134
- const [readAbsent, setReadAbsent] = useState4(false);
3135
- const { run, mutating, mutationError, clearMutationError } = useMutationRunner();
3136
- const generation = useRef4(0);
3137
- const targetKeyRef = useRef4(null);
3138
- const goalAbsentRef = useRef4(false);
3139
- const pendingRefreshRef = useRef4("none");
3140
- const sharedEventsRef = useRef4(sharedEvents);
3141
- useLayoutEffect2(() => {
3142
- sharedEventsRef.current = sharedEvents;
3143
- }, [sharedEvents]);
3144
- const loadAbort = useRef4(null);
3145
- const scheduleRefreshRef = useRef4(() => void 0);
3146
- const retireLoads = useCallback5(() => {
3147
- generation.current += 1;
3148
- loadAbort.current?.abort();
3149
- loadAbort.current = null;
3150
- }, []);
3151
- const load = useCallback5(async () => {
3152
- if (!sessionId) {
3153
- return;
3154
- }
3155
- const ticket = ++generation.current;
3156
- pendingRefreshRef.current = "none";
3157
- loadAbort.current?.abort();
3158
- const controller = new AbortController();
3159
- loadAbort.current = controller;
3160
- let fetchedGoal = null;
3161
- try {
3162
- const fetched = typeof client.findGoal === "function" ? await client.findGoal(workspaceId, sessionId, { signal: controller.signal }) : await client.getGoal(workspaceId, sessionId, { signal: controller.signal });
3163
- fetchedGoal = fetched;
3164
- if (ticket === generation.current) {
3165
- goalAbsentRef.current = fetched === null;
3166
- setReadAbsent(fetched === null);
3167
- setGoal(fetched);
3168
- setError(null);
3169
- setLoading(false);
3170
- }
3171
- } catch (cause) {
3172
- if (ticket !== generation.current) {
3173
- return;
3174
- }
3175
- if (cause instanceof OpenGeniApiError && cause.status === 404) {
3176
- goalAbsentRef.current = true;
3177
- setReadAbsent(true);
3178
- setGoal(null);
3179
- setError(null);
3180
- } else {
3181
- setError(normalizeError(cause));
3182
- }
3183
- setLoading(false);
3184
- } finally {
3185
- if (loadAbort.current === controller) loadAbort.current = null;
3186
- }
3187
- if (ticket !== generation.current || pendingRefreshRef.current === "none") {
3188
- return;
3189
- }
3190
- const readThrough = fetchedGoal ? observedSessionSequence(fetchedGoal) : void 0;
3191
- if (readThrough !== void 0 && sharedEventsRef.current !== void 0) {
3192
- const events = sharedEventsRef.current;
3193
- const newest = events[events.length - 1];
3194
- if (!newest || newest.sequence <= readThrough) {
3195
- pendingRefreshRef.current = "none";
3196
- return;
3197
- }
3198
- }
3199
- if (goalAbsentRef.current && pendingRefreshRef.current === "refresh") {
3200
- const events = sharedEventsRef.current ?? [];
3201
- let latestGoalEvent;
3202
- for (let index = events.length - 1; index >= 0 && !latestGoalEvent; index -= 1) {
3203
- const event = events[index];
3204
- if (event && isGoalEvent(event)) latestGoalEvent = event;
3205
- }
3206
- if (!latestGoalEvent || latestGoalEvent.type === "goal.cleared") {
3207
- pendingRefreshRef.current = "none";
3208
- return;
3209
- }
3210
- pendingRefreshRef.current = "goal";
3211
- }
3212
- scheduleRefreshRef.current();
3213
- }, [client, workspaceId, sessionId]);
3214
- useEffect4(() => {
3215
- const targetKey = `${workspaceId} ${sessionId ?? ""}`;
3216
- if (targetKeyRef.current !== targetKey) {
3217
- targetKeyRef.current = targetKey;
3218
- goalAbsentRef.current = false;
3219
- pendingRefreshRef.current = "none";
3220
- setReadAbsent(false);
3221
- setGoal(null);
3222
- setError(null);
3223
- }
3224
- if (!enabled || !pageLive) {
3225
- retireLoads();
3226
- setLoading(false);
3227
- return;
3228
- }
3229
- if (sharedFeed) {
3230
- setLoading(true);
3231
- void load();
3232
- return () => {
3233
- retireLoads();
3234
- };
3235
- }
3236
- setLoading(true);
3237
- const pollIntervalMs = options.pollIntervalMs;
3238
- if (pollIntervalMs === void 0 || pollIntervalMs <= 0) {
3239
- void load();
3240
- return () => {
3241
- retireLoads();
3242
- };
3243
- }
3244
- let cancelled = false;
3245
- let timer = null;
3246
- const schedule = () => {
3247
- if (cancelled) return;
3248
- timer = setTimeout(() => {
3249
- timer = null;
3250
- void load().finally(schedule);
3251
- }, pollIntervalMs);
3252
- };
3253
- void load().finally(schedule);
3254
- return () => {
3255
- cancelled = true;
3256
- if (timer !== null) clearTimeout(timer);
3257
- retireLoads();
3258
- };
3259
- }, [
3260
- load,
3261
- enabled,
3262
- pageLive,
3263
- workspaceId,
3264
- sessionId,
3265
- options.pollIntervalMs,
3266
- retireLoads,
3267
- sharedFeed
3268
- ]);
3269
- const scheduleRefresh = useDebouncedCallback(() => {
3270
- const pending = pendingRefreshRef.current;
3271
- if (pending === "none" || loadAbort.current !== null) return;
3272
- if (pending === "refresh" && goalAbsentRef.current) {
3273
- pendingRefreshRef.current = "none";
3274
- return;
3275
- }
3276
- void load();
3277
- });
3278
- useLayoutEffect2(() => {
3279
- scheduleRefreshRef.current = scheduleRefresh;
3280
- }, [scheduleRefresh]);
3281
- const isRefreshEvent = useCallback5(
3282
- (event) => goalAbsentRef.current ? isGoalEvent(event) : isGoalRefreshEvent(event),
3283
- []
3284
- );
3285
- const refreshGoal = useCallback5(() => {
3286
- pendingRefreshRef.current = "goal";
3287
- scheduleRefresh();
3288
- }, [scheduleRefresh]);
3289
- const onRefreshEvent = useCallback5(
3290
- (event) => {
3291
- if (isGoalEvent(event)) pendingRefreshRef.current = "goal";
3292
- else if (pendingRefreshRef.current === "none") pendingRefreshRef.current = "refresh";
3293
- scheduleRefresh();
3294
- },
3295
- [scheduleRefresh]
3296
- );
3297
- useSessionEventTrigger(client, workspaceId, sessionId, isRefreshEvent, onRefreshEvent, {
3298
- enabled,
3299
- ...sharedEvents !== void 0 ? { events: sharedEvents } : {},
3300
- // The load settles events that arrive during its read itself (above).
3301
- readThrough: projectionReadThrough(goal, false),
3302
- refresh: refreshGoal
3303
- });
3304
- const retainedGoal = useRetainedSessionView(
3305
- client,
3306
- workspaceId,
3307
- sessionId,
3308
- "goal",
3309
- loading ? null : goal,
3310
- { enabled, discard: readAbsent || deniesRetainedView(error) }
3311
- );
3312
- const visibleGoal = loading ? goal ?? retainedGoal : goal;
3313
- const goalRef = useRef4(goal);
3314
- const shownRetainedRef = useRef4(null);
3315
- const readWaitersRef = useRef4([]);
3316
- useLayoutEffect2(() => {
3317
- goalRef.current = goal;
3318
- shownRetainedRef.current = loading && goal === null ? retainedGoal : null;
3319
- });
3320
- useEffect4(() => {
3321
- if (loading) return;
3322
- const waiters = readWaitersRef.current;
3323
- readWaitersRef.current = [];
3324
- for (const resolve of waiters) resolve();
3325
- }, [loading]);
3326
- useEffect4(
3327
- () => () => {
3328
- goalRef.current = null;
3329
- const waiters = readWaitersRef.current;
3330
- readWaitersRef.current = [];
3331
- for (const resolve of waiters) resolve();
3332
- },
3333
- [workspaceId, sessionId]
3334
- );
3335
- const aimedAtCurrentGoal = useCallback5(async () => {
3336
- const shown = shownRetainedRef.current;
3337
- if (!shown) return true;
3338
- await new Promise((resolve) => readWaitersRef.current.push(resolve));
3339
- const fresh = goalRef.current;
3340
- return fresh !== null && fresh.id === shown.id && fresh.objectiveRevision === shown.objectiveRevision;
3341
- }, []);
3342
- const pause = useCallback5(
3343
- async (rationale) => {
3344
- if (!sessionId || !await aimedAtCurrentGoal()) {
3345
- return null;
3346
- }
3347
- const result = await run(
3348
- () => client.updateGoal(workspaceId, sessionId, {
3349
- status: "paused",
3350
- ...rationale !== void 0 ? { rationale } : {}
3351
- })
3352
- );
3353
- if (result) {
3354
- setGoal(result);
3355
- }
3356
- return result;
3357
- },
3358
- [client, workspaceId, sessionId, run, aimedAtCurrentGoal]
3359
- );
3360
- const resume = useCallback5(async () => {
3361
- if (!sessionId || !await aimedAtCurrentGoal()) {
3362
- return null;
3363
- }
3364
- const result = await run(() => client.updateGoal(workspaceId, sessionId, { status: "active" }));
3365
- if (result) {
3366
- setGoal(result);
3367
- }
3368
- return result;
3369
- }, [client, workspaceId, sessionId, run, aimedAtCurrentGoal]);
3370
- const clearGoal = useCallback5(async () => {
3371
- if (!sessionId || !await aimedAtCurrentGoal()) {
3372
- return;
3373
- }
3374
- const ok = await run(async () => {
3375
- await client.deleteGoal(workspaceId, sessionId);
3376
- return true;
3377
- });
3378
- if (ok) {
3379
- retireLoads();
3380
- setReadAbsent(true);
3381
- setGoal(null);
3382
- setError(null);
3383
- }
3384
- }, [client, workspaceId, sessionId, run, retireLoads, aimedAtCurrentGoal]);
3385
- return {
3386
- goal: visibleGoal,
3387
- isActive: visibleGoal?.status === "active",
3388
- isPaused: visibleGoal?.status === "paused",
3389
- isCompleted: visibleGoal?.status === "completed",
3390
- loading: loading && retainedGoal === null,
3391
- error,
3392
- refresh: load,
3393
- pause,
3394
- resume,
3395
- clearGoal,
3396
- deleteGoal: clearGoal,
3397
- updating: mutating,
3398
- mutationError,
3399
- clearMutationError
3400
- };
3401
- }
3402
-
3403
- // src/hooks/use-session-control.ts
3404
- import { useCallback as useCallback6, useLayoutEffect as useLayoutEffect3, useRef as useRef5 } from "react";
3405
- function useSessionControl(sessionId, options = {}) {
3406
- const { client, workspaceId } = useEmbeddedSession(options);
3407
- const approvalTargetKey = `${workspaceId}\0${sessionId ?? ""}`;
3408
- const pendingApproval = useRef5(null);
3409
- useLayoutEffect3(() => {
3410
- if (pendingApproval.current?.targetKey !== approvalTargetKey) {
3411
- pendingApproval.current = null;
3412
- }
3413
- }, [approvalTargetKey]);
3414
- const {
3415
- run: runControl,
3416
- mutating: controlling,
3417
- mutationError: controlError,
3418
- clearMutationError: clearControlError
3419
- } = useMutationRunner(approvalTargetKey);
3420
- const {
3421
- run: runApproval,
3422
- mutating: responding,
3423
- mutationError: approvalError,
3424
- clearMutationError: clearApprovalError
3425
- } = useMutationRunner(approvalTargetKey);
3426
- const pause = useCallback6(
3427
- async (reason) => {
3428
- if (!sessionId) {
3429
- return null;
3430
- }
3431
- return await runControl(
3432
- () => client.pauseSession(workspaceId, sessionId, reason !== void 0 ? { reason } : {})
3433
- );
3434
- },
3435
- [client, workspaceId, sessionId, runControl]
3436
- );
3437
- const resume = useCallback6(
3438
- async (reason) => {
3439
- if (!sessionId) return null;
3440
- return await runControl(
3441
- () => client.resumeSession(workspaceId, sessionId, reason !== void 0 ? { reason } : {})
3442
- );
3443
- },
3444
- [client, workspaceId, sessionId, runControl]
3445
- );
3446
- const decide = useCallback6(
3447
- async (approvalId, decision, message, answer) => {
3448
- if (!sessionId) {
3449
- return null;
3450
- }
3451
- const decisionKey = JSON.stringify([approvalId, decision, message ?? null, answer ?? null]);
3452
- if (pendingApproval.current?.decisionKey !== decisionKey) {
3453
- pendingApproval.current = {
3454
- targetKey: approvalTargetKey,
3455
- decisionKey,
3456
- clientEventId: crypto.randomUUID()
3457
- };
3458
- }
3459
- const clientEventId = pendingApproval.current.clientEventId;
3460
- const accepted = await runApproval(
3461
- () => client.sendApprovalDecision(workspaceId, sessionId, {
3462
- approvalId,
3463
- decision,
3464
- ...message !== void 0 ? { message } : {},
3465
- ...answer !== void 0 ? answer : {},
3466
- clientEventId
3467
- })
3468
- );
3469
- if (accepted !== null && pendingApproval.current?.targetKey === approvalTargetKey && pendingApproval.current.clientEventId === clientEventId) {
3470
- pendingApproval.current = null;
3471
- }
3472
- return accepted;
3473
- },
3474
- [approvalTargetKey, client, workspaceId, sessionId, runApproval]
3475
- );
3476
- const approve = useCallback6(
3477
- async (approvalId, message, answer) => await decide(approvalId, "approve", message, answer),
3478
- [decide]
3479
- );
3480
- const reject = useCallback6(
3481
- async (approvalId, message) => await decide(approvalId, "reject", message),
3482
- [decide]
3483
- );
3484
- const error = approvalError ?? controlError;
3485
- const clearError = useCallback6(() => {
3486
- clearControlError();
3487
- clearApprovalError();
3488
- }, [clearControlError, clearApprovalError]);
3489
- return {
3490
- pause,
3491
- resume,
3492
- controlling,
3493
- approve,
3494
- reject,
3495
- responding,
3496
- error,
3497
- clearError
3498
- };
3499
- }
3500
-
3501
- // src/hooks/use-available-models.ts
3502
- import { useCallback as useCallback7 } from "react";
3503
- function useAvailableModels(options = {}) {
3504
- const client = useOpenGeniClient(options);
3505
- const load = useCallback7(
3506
- async (signal) => await client.getClientConfig({ signal }),
3507
- [client]
3508
- );
3509
- const state = useSharedQuery(client, ["available-models"], load, {
3510
- pollIntervalMs: options.pollIntervalMs,
3511
- enabled: options.enabled
3512
- });
3513
- return {
3514
- models: state.data?.models ?? [],
3515
- defaultModel: state.data?.defaultModel ?? null,
3516
- loading: state.loading,
3517
- error: state.error,
3518
- refresh: state.refresh
3519
- };
3520
- }
3521
- function useWorkspaceModelCatalog(options) {
3522
- const t = useOpenGeniText();
3523
- const client = useOpenGeniClient(options);
3524
- const load = useCallback7(
3525
- async (signal) => {
3526
- if (!options.workspaceId) {
3527
- return { models: [], defaultModel: null };
3528
- }
3529
- const [catalog, config] = await Promise.all([
3530
- client.getWorkspaceModelCatalog(options.workspaceId, { signal }),
3531
- // Joins the same workspace's config read already in flight (for
3532
- // example the composer's voice availability).
3533
- joinClientConfigRead(client, options.workspaceId)
3534
- ]);
3535
- return {
3536
- models: catalog.models,
3537
- defaultModel: config.defaultModel
3538
- };
3539
- },
3540
- [client, options.workspaceId]
3541
- );
3542
- const state = useSharedQuery(client, ["workspace-model-catalog", options.workspaceId], load, {
3543
- pollIntervalMs: options.pollIntervalMs,
3544
- enabled: options.enabled !== false && Boolean(options.workspaceId)
3545
- });
3546
- const rows = sortPickerRows(projectPickerRows(t, state.data?.models ?? []));
3547
- return {
3548
- models: state.data?.models ?? [],
3549
- rows,
3550
- defaultModel: state.data?.defaultModel ?? null,
3551
- loading: state.loading,
3552
- error: state.error,
3553
- refresh: state.refresh
3554
- };
3555
- }
3556
-
3557
- // src/hooks/use-human-input.ts
3558
- import { useCallback as useCallback8, useEffect as useEffect5, useRef as useRef6, useState as useState5 } from "react";
3559
- function isHumanInputEvent(event) {
3560
- return event.type === "session.humanInput.requested" || event.type === "user.humanInputResponse" || event.type === "turn.completed" || event.type === "turn.failed" || event.type === "turn.cancelled";
3561
- }
3562
- function useHumanInputRequests(sessionId, options = {}) {
3563
- const { client, workspaceId, registerSessionReconciler } = useEmbeddedHumanInputSession(options);
3564
- const enabled = (options.enabled ?? true) && Boolean(sessionId);
3565
- const load = useCallback8(async () => {
3566
- if (!sessionId) return [];
3567
- const readStartedAt = Date.now();
3568
- const requests = await client.listHumanInputRequests(workspaceId, sessionId, {
3569
- status: "pending"
3570
- });
3571
- const now2 = Date.now();
3572
- pruneHumanInputDrafts(
3573
- workspaceId,
3574
- sessionId,
3575
- requests.filter((request) => isActionableHumanInputRequest(request, now2)).map((request) => request.id),
3576
- readStartedAt
3577
- );
3578
- return requests;
3579
- }, [client, sessionId, workspaceId]);
3580
- const state = usePolledValue(load, {
3581
- enabled,
3582
- pollIntervalMs: options.pollIntervalMs
3583
- });
3584
- const loadedRequests = state.data;
3585
- const refreshRequests = state.refresh;
3586
- const readDenied = enabled && Boolean(sessionId) && deniesRetainedView(state.error);
3587
- useEffect5(() => {
3588
- if (readDenied && sessionId) forgetSessionHumanInputDrafts(workspaceId, sessionId);
3589
- }, [readDenied, sessionId, workspaceId]);
3590
- const mutation = useMutationRunner(`${workspaceId}\0${sessionId ?? ""}`);
3591
- const [respondingRequestId, setRespondingRequestId] = useState5(null);
3592
- const [deadlineVersion, setDeadlineVersion] = useState5(0);
3593
- const respondingRequestRef = useRef6(null);
3594
- useEffect5(() => {
3595
- respondingRequestRef.current = null;
3596
- setRespondingRequestId(null);
3597
- }, [sessionId, workspaceId]);
3598
- useEffect5(() => {
3599
- if (!sessionId || !enabled) return;
3600
- return registerSessionReconciler(sessionId, "human-input", state.refresh);
3601
- }, [enabled, registerSessionReconciler, sessionId, state.refresh]);
3602
- const scheduleRefresh = useDebouncedCallback(() => void state.refresh());
3603
- useSessionEventTrigger(client, workspaceId, sessionId, isHumanInputEvent, scheduleRefresh, {
3604
- enabled,
3605
- ...options.events !== void 0 ? { events: options.events } : {},
3606
- readThrough: projectionReadThrough(state.data, state.loading),
3607
- refresh: scheduleRefresh
3608
- });
3609
- const retainedRequests = useRetainedSessionView(
3610
- client,
3611
- workspaceId,
3612
- sessionId,
3613
- "human-input",
3614
- state.data,
3615
- { enabled, discard: deniesRetainedView(state.error) }
3616
- );
3617
- useEffect5(() => {
3618
- const now2 = Date.now();
3619
- const nextDeadline = (loadedRequests ?? []).reduce((next, request) => {
3620
- if (request.status !== "pending" || !request.expiresAt) return next;
3621
- const deadline = Date.parse(request.expiresAt);
3622
- if (!Number.isFinite(deadline) || deadline <= now2) return next;
3623
- return next === null ? deadline : Math.min(next, deadline);
3624
- }, null);
3625
- if (nextDeadline === null) return;
3626
- const timer = globalThis.setTimeout(
3627
- () => {
3628
- setDeadlineVersion((current) => current + 1);
3629
- void refreshRequests();
3630
- },
3631
- Math.min(2147483647, Math.max(0, nextDeadline - now2 + 1))
3632
- );
3633
- return () => globalThis.clearTimeout(timer);
3634
- }, [loadedRequests, refreshRequests]);
3635
- const respond = useCallback8(
3636
- async (requestId, response) => {
3637
- if (!sessionId || respondingRequestRef.current !== null) return null;
3638
- respondingRequestRef.current = requestId;
3639
- setRespondingRequestId(requestId);
3640
- try {
3641
- const event = await mutation.run(
3642
- () => client.submitHumanInputResponse(workspaceId, sessionId, requestId, response, {
3643
- clientEventId: globalThis.crypto.randomUUID()
3644
- })
3645
- );
3646
- if (event) await state.refresh();
3647
- return event;
3648
- } finally {
3649
- if (respondingRequestRef.current === requestId) {
3650
- respondingRequestRef.current = null;
3651
- setRespondingRequestId(null);
3652
- }
3653
- }
3654
- },
3655
- [client, mutation, sessionId, state, workspaceId]
3656
- );
3657
- const now = Date.now();
3658
- void deadlineVersion;
3659
- return {
3660
- requests: [...state.data ?? retainedRequests ?? []].filter((request) => isActionableHumanInputRequest(request, now)).sort(
3661
- (left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id)
3662
- ),
3663
- loading: state.loading && retainedRequests === null,
3664
- error: state.error,
3665
- refresh: state.refresh,
3666
- respond,
3667
- respondingRequestId,
3668
- mutationError: mutation.mutationError,
3669
- clearMutationError: mutation.clearMutationError
3670
- };
3671
- }
3672
-
3673
- // src/conversation-timeline.ts
3674
- function conversationTimeline(items, queue, composer) {
3675
- const queued = new Set(
3676
- queue.queue.filter((turn) => turn.metadata.delivery !== "steer").map((turn) => turn.triggerEventId)
3677
- );
3678
- const pending = composer.optimisticMessages ?? [];
3679
- const pendingQueue = new Set(
3680
- pending.filter(
3681
- (message) => message.destination === "queue" && !(message.turnId && message.appliedQueueVersion != null && queue.snapshot && queue.snapshot.version >= message.appliedQueueVersion && !queue.queue.some((turn) => turn.id === message.turnId))
3682
- ).map((message) => `user-message:${message.clientEventId}`)
3683
- );
3684
- const visible = items.filter(
3685
- (item) => item.kind !== "user-message" || !queued.has(item.id) && !pendingQueue.has(item.reconciliationKey ?? "")
3686
- );
3687
- const keys = new Set(
3688
- visible.flatMap((item) => item.kind === "user-message" ? [item.reconciliationKey] : [])
3689
- );
3690
- const optimistic = pending.filter(
3691
- (message) => (message.destination === "chat" || message.state === "failed") && !keys.has(`user-message:${message.clientEventId}`) && !queue.queue.some((turn) => turn.id === message.turnId)
3692
- ).map((message) => ({
3693
- kind: "user-message",
3694
- id: `optimistic:${message.clientEventId}`,
3695
- reconciliationKey: `user-message:${message.clientEventId}`,
3696
- text: message.text,
3697
- annotations: message.annotations.map((annotation, ordinal) => ({ ...annotation, ordinal })),
3698
- resources: message.resources,
3699
- tools: [],
3700
- occurredAt: message.occurredAt,
3701
- delivery: {
3702
- state: message.state,
3703
- ...message.error ? { error: message.error } : {},
3704
- ...message.state === "failed" ? {
3705
- ...message.retryable !== false && composer.retryOptimisticMessage ? { onRetry: () => composer.retryOptimisticMessage?.(message.clientEventId) } : {},
3706
- ...message.retryable === false && composer.restoreOptimisticMessage ? { onEdit: () => composer.restoreOptimisticMessage?.(message.clientEventId) } : {},
3707
- onRemove: () => composer.removeOptimisticMessage?.(message.clientEventId)
3708
- } : {}
3709
- }
3710
- }));
3711
- const failed = optimistic.filter((message) => message.delivery?.state === "failed");
3712
- const unsent = optimistic.filter((message) => message.delivery?.state !== "failed");
3713
- const ids = new Set(visible.map((item) => item.id));
3714
- const steers = (queue.acceptedSteers ?? []).filter((steer) => !ids.has(steer.triggerEventId)).map((steer) => ({
3715
- kind: "user-message",
3716
- id: steer.triggerEventId,
3717
- text: steer.text,
3718
- annotations: steer.annotations,
3719
- resources: steer.resources,
3720
- tools: steer.tools,
3721
- occurredAt: steer.occurredAt,
3722
- delivery: { state: steer.state }
3723
- }));
3724
- return [...placeFailedSends(visible, failed), ...unsent, ...steers];
3725
- }
3726
- function placeFailedSends(items, failed) {
3727
- if (failed.length === 0) return items;
3728
- const before = /* @__PURE__ */ new Map();
3729
- const last = [];
3730
- for (const message of failed) {
3731
- const sentAt = Date.parse(message.occurredAt);
3732
- const newer = items.findIndex(
3733
- (item) => item.kind === "user-message" && Date.parse(item.occurredAt) > sentAt
3734
- );
3735
- if (newer === -1) {
3736
- last.push(message);
3737
- } else {
3738
- before.set(newer, [...before.get(newer) ?? [], message]);
3739
- }
3740
- }
3741
- return [...items.flatMap((item, index) => [...before.get(index) ?? [], item]), ...last];
3742
- }
3743
-
3744
- // src/lib/session-startup-timeline.tsx
3745
- import { useRef as useRef7 } from "react";
3746
- function currentEvents(events) {
3747
- return events.filter(
3748
- (event) => !event.duplicateOfEventId && (!event.turnAssociation || event.turnAssociation === "current")
3749
- ).sort((a, b) => a.sequence - b.sequence);
3750
- }
3751
- function payloadOf(event) {
3752
- return event.payload && typeof event.payload === "object" ? event.payload : {};
3753
- }
3754
- function sessionStartupTimeline(items, input) {
3755
- const { session, optimisticMessages, hasNewer } = input;
3756
- if (hasNewer || session.effectiveControl.state !== "active" || !["idle", "queued", "running"].includes(session.status) || session.status === "idle" && session.inputWait)
3757
- return items;
3758
- const claimed = /* @__PURE__ */ new Set();
3759
- const pending = /* @__PURE__ */ new Map();
3760
- let queueVersion = session.queueVersion;
3761
- let newerProgress = false;
3762
- let observedActiveTurn = null;
3763
- let previousTurnEndedAt = null;
3764
- for (const event of currentEvents(input.events)) {
3765
- const payload = payloadOf(event);
3766
- if (event.turnId && ["turn.completed", "turn.failed", "turn.cancelled", "turn.superseded"].includes(event.type))
3767
- previousTurnEndedAt = event.occurredAt;
3768
- if (event.sequence > session.lastSequence && ([
3769
- "turn.started",
3770
- "turn.completed",
3771
- "turn.failed",
3772
- "turn.cancelled",
3773
- "turn.superseded"
3774
- ].includes(event.type) || event.type === "session.status.changed" && payload.status !== "queued" || event.type === "session.queue.changed" && ["edit", "delete"].includes(String(payload.operation))))
3775
- newerProgress = true;
3776
- if (event.type === "session.queue.changed" && typeof payload.queueVersion === "number")
3777
- queueVersion = Math.max(queueVersion, payload.queueVersion);
3778
- const turnId2 = event.turnId ?? (typeof payload.turnId === "string" ? payload.turnId : null);
3779
- if (!turnId2) continue;
3780
- if (event.sequence > session.lastSequence) {
3781
- if (event.type === "turn.started") observedActiveTurn = turnId2;
3782
- else if (observedActiveTurn === turnId2 && ["turn.completed", "turn.failed", "turn.cancelled", "turn.superseded"].includes(event.type))
3783
- observedActiveTurn = null;
3784
- }
3785
- if ([
3786
- "turn.started",
3787
- "turn.completed",
3788
- "turn.failed",
3789
- "turn.cancelled",
3790
- "turn.superseded"
3791
- ].includes(event.type) || event.type === "session.queue.changed" && ["edit", "delete"].includes(String(payload.operation)))
3792
- claimed.add(turnId2);
3793
- if ((event.type === "turn.queued" || event.type === "user.message") && payload.routing === "accepted_for_execution" && (session.status !== "idle" || event.sequence > session.lastSequence))
3794
- pending.set(turnId2, event.occurredAt);
3795
- }
3796
- for (const message of optimisticMessages ?? []) {
3797
- if (message.state === "queued" && message.destination === "chat" && message.delivery === "send" && message.turnId && !pending.has(message.turnId) && (session.status !== "idle" || message.appliedQueueVersion != null && message.appliedQueueVersion > session.queueVersion))
3798
- pending.set(message.turnId, message.occurredAt);
3799
- }
3800
- const head = input.queue && input.queue.version >= queueVersion ? input.queue.items[0] : null;
3801
- if (session.status === "queued" && !session.activeTurnId && head && !pending.has(head.id))
3802
- pending.set(
3803
- head.id,
3804
- previousTurnEndedAt && previousTurnEndedAt > head.createdAt ? previousTurnEndedAt : head.createdAt
3805
- );
3806
- const candidate = [...pending].find(
3807
- ([turnId2]) => !claimed.has(turnId2) && (!session.activeTurnId || session.activeTurnId === turnId2) && (!observedActiveTurn || observedActiveTurn === turnId2) && !items.some((item) => "turnId" in item && item.turnId === turnId2)
3808
- );
3809
- const fallback = !candidate && !newerProgress && session.status === "queued" && !session.activeTurnId && input.fallbackStartedAt;
3810
- if (!candidate && !fallback) return items;
3811
- const [turnId, startedAt] = candidate ?? [
3812
- `pending-startup:${session.id}`,
3813
- input.fallbackStartedAt
3814
- ];
3815
- return [
3816
- ...items,
3817
- {
3818
- kind: "startup-phase",
3819
- id: `${turnId}-queue`,
3820
- turnId,
3821
- phase: "queue",
3822
- status: "running",
3823
- startedAt,
3824
- occurredAt: startedAt,
3825
- completedAt: null,
3826
- durationMs: null,
3827
- outcome: null,
3828
- ...session.activeTurnId ? {} : { dispatchWait: session.status === "queued" ? session.dispatchWait ?? null : null }
3829
- }
3830
- ];
3831
- }
3832
- var PENDING_SCOPE = "pending-prompt";
3833
- var PENDING_PROMPT_STARTUP_ID = "pending-prompt-startup";
3834
- function pendingPromptItems(prompt) {
3835
- return [
3836
- {
3837
- kind: "user-message",
3838
- id: "pending-prompt-message",
3839
- text: prompt.text,
3840
- resources: prompt.resources ?? [],
3841
- tools: [],
3842
- occurredAt: prompt.sentAt
3843
- },
3844
- {
3845
- kind: "startup-phase",
3846
- id: PENDING_PROMPT_STARTUP_ID,
3847
- turnId: PENDING_SCOPE,
3848
- phase: "queue",
3849
- status: "running",
3850
- startedAt: prompt.sentAt,
3851
- occurredAt: prompt.sentAt,
3852
- completedAt: null,
3853
- durationMs: null,
3854
- outcome: null
3855
- }
3856
- ];
3857
- }
3858
- function useSessionStartupTimeline(items, input) {
3859
- const startup = useSessionStartupState(input.session);
3860
- const bridgeRef = useRef7(null);
3861
- const { pendingPrompt } = input;
3862
- if (pendingPrompt && (!input.session || input.historyReady === false)) {
3863
- bridgeRef.current = {
3864
- scope: PENDING_SCOPE,
3865
- id: PENDING_PROMPT_STARTUP_ID,
3866
- turnId: null,
3867
- since: pendingPrompt.sentAt,
3868
- sequence: 0
3869
- };
3870
- return [...items, ...pendingPromptItems(pendingPrompt)];
3871
- }
3872
- if (!input.session) {
3873
- bridgeRef.current = null;
3874
- return items;
3875
- }
3876
- const scope = `${input.session.workspaceId}:${input.session.id}`;
3877
- if (bridgeRef.current?.scope === PENDING_SCOPE)
3878
- bridgeRef.current = { ...bridgeRef.current, scope };
3879
- if (bridgeRef.current?.scope !== scope || input.hasNewer || input.session.effectiveControl.state !== "active" || !["queued", "running", "idle"].includes(input.session.status))
3880
- bridgeRef.current = null;
3881
- const boundTurn = bridgeRef.current?.turnId;
3882
- const settled = boundTurn && currentEvents(input.events).find(
3883
- (event) => event.turnId === boundTurn && ["turn.completed", "turn.failed", "turn.cancelled", "turn.superseded"].includes(event.type)
3884
- );
3885
- let fallbackStartedAt = bridgeRef.current?.turnId === null ? bridgeRef.current.since : startup?.startedAt;
3886
- if (settled) {
3887
- bridgeRef.current = null;
3888
- fallbackStartedAt = input.session.status === "queued" && input.session.lastSequence >= settled.sequence ? input.session.updatedAt : void 0;
3889
- }
3890
- const projected = sessionStartupTimeline(items, {
3891
- ...input,
3892
- session: input.session,
3893
- fallbackStartedAt
3894
- });
3895
- if (projected !== items) {
3896
- const phase2 = projected.at(-1);
3897
- if (phase2.kind !== "startup-phase") return projected;
3898
- const turnId2 = phase2.turnId === `pending-startup:${input.session.id}` ? null : phase2.turnId;
3899
- let bridge2 = bridgeRef.current;
3900
- if (!bridge2 || bridge2.turnId && turnId2 && bridge2.turnId !== turnId2) {
3901
- bridge2 = {
3902
- scope,
3903
- id: phase2.id,
3904
- turnId: turnId2,
3905
- since: phase2.startedAt,
3906
- sequence: input.session.lastSequence
3907
- };
3908
- } else
3909
- bridge2 = {
3910
- ...bridge2,
3911
- turnId: turnId2 ?? bridge2.turnId,
3912
- since: bridge2.since < phase2.startedAt ? bridge2.since : phase2.startedAt
3913
- };
3914
- bridgeRef.current = bridge2;
3915
- return [
3916
- ...projected.slice(0, -1),
3917
- { ...phase2, id: bridge2.id, startedAt: bridge2.since, occurredAt: bridge2.since }
3918
- ];
3919
- }
3920
- const bridge = bridgeRef.current;
3921
- if (!bridge) return items;
3922
- if (input.session.status === "idle") {
3923
- bridgeRef.current = null;
3924
- return items;
3925
- }
3926
- const started = currentEvents(input.events).find(
3927
- (event) => event.type === "turn.started" && (bridge.turnId ? event.turnId === bridge.turnId : event.sequence > bridge.sequence)
3928
- );
3929
- const turnId = bridge.turnId ?? started?.turnId ?? input.session.activeTurnId;
3930
- const phase = items.find((item) => item.kind === "startup-phase" && item.turnId === turnId);
3931
- if (phase?.kind === "startup-phase") {
3932
- bridgeRef.current = { ...bridge, turnId };
3933
- return items.map(
3934
- (item) => item === phase ? {
3935
- ...phase,
3936
- id: bridge.id,
3937
- loadingStartedAt: bridge.since < phase.startedAt ? bridge.since : phase.startedAt
3938
- } : item
3939
- );
3940
- }
3941
- if (turnId && (started || input.session.activeTurnId === turnId)) {
3942
- bridgeRef.current = { ...bridge, turnId };
3943
- return [
3944
- ...items,
3945
- {
3946
- kind: "startup-phase",
3947
- id: bridge.id,
3948
- turnId,
3949
- phase: "queue",
3950
- status: "complete",
3951
- startedAt: bridge.since,
3952
- occurredAt: bridge.since,
3953
- completedAt: started?.occurredAt ?? input.session.updatedAt,
3954
- durationMs: null,
3955
- outcome: null
3956
- }
3957
- ];
3958
- }
3959
- if (turnId) bridgeRef.current = null;
3960
- return items;
3961
- }
3962
-
3963
- // src/hooks/use-session-conversation.ts
3964
- import { useLayoutEffect as useLayoutEffect4, useMemo as useMemo4, useRef as useRef8, useState as useState6 } from "react";
3965
- function useSessionConversation(sessionId, options = {}) {
3966
- const [initialPrompt] = useState6(() => options.pendingPrompt ?? null);
3967
- const context = useOpenGeni(options);
3968
- const scope = { client: context.client, workspaceId: context.workspaceId };
3969
- const config = useClientConfigFlags(context.client);
3970
- const showModelPicker = options.modelPicker ?? config.modelSelection;
3971
- const catalog = useWorkspaceModelCatalog({ ...scope, enabled: showModelPicker });
3972
- const feed = useSessionEvents(sessionId, scope);
3973
- const pendingPrompt = usePendingPrompt(initialPrompt, sessionId, feed.initialHistoryReady);
3974
- const eventOptions = { ...scope, events: feed.events };
3975
- const detail = useSession(sessionId, eventOptions);
3976
- const queue = useTurnQueue(sessionId, eventOptions);
3977
- const human = useHumanInputRequests(sessionId, eventOptions);
3978
- const control = useSessionControl(sessionId, scope);
3979
- const approvals = useMemo4(() => projectPendingApprovals(feed.events), [feed.events]);
3980
- const files = useFileAttachments(scope);
3981
- const clearFiles = files.clear;
3982
- const attachmentSession = useRef8(sessionId);
3983
- useLayoutEffect4(() => {
3984
- if (attachmentSession.current === sessionId) return;
3985
- const created = attachmentSession.current === null;
3986
- attachmentSession.current = sessionId;
3987
- if (created) return;
3988
- clearFiles();
3989
- }, [clearFiles, sessionId]);
3990
- const uploadsEnabled = (options.attachments ?? true) && config.uploads;
3991
- const status = feed.sessionStatus ?? detail.session?.status;
3992
- const terminal = status === "cancelled";
3993
- const importedArchive = detail.session?.importedArchive?.readOnly === true;
3994
- const host = options.composerOptions;
3995
- const resolveExtras = () => typeof host?.sendExtras === "function" ? host.sendExtras() : host?.sendExtras;
3996
- const releaseSentFiles = (input) => files.removeReadyFiles(
3997
- (input.resources ?? []).flatMap(
3998
- (resource) => resource.kind === "file" ? [resource.fileId] : []
3999
- )
4000
- );
4001
- const composer = useComposer(sessionId, {
4002
- ...eventOptions,
4003
- initialDraft: host?.initialDraft,
4004
- busySend: host?.busySend,
4005
- offerQueue: host?.offerQueue,
4006
- effectiveControl: queue.effectiveControl ?? detail.session?.effectiveControl,
4007
- // As in the console and the native screen: a turn that is still current
4008
- // (running or recovering) means a Send waits. A turn parked on provider
4009
- // capacity does not: the Send replaces it and starts right away.
4010
- sendDestination: () => promptSendDestination({
4011
- status,
4012
- activeTurnId: detail.session?.activeTurnId,
4013
- queuedPrompts: queue.queue.length,
4014
- admissionBlock: detail.session?.admissionBlock
4015
- }),
4016
- sendExtras: () => {
4017
- const extras = resolveExtras();
4018
- return {
4019
- ...extras,
4020
- resources: [...extras?.resources ?? [], ...uploadsEnabled ? files.readyResources : []]
4021
- };
4022
- },
4023
- sendBlocked: () => sessionId === null || terminal || importedArchive || uploadsEnabled && files.hasUnresolved || host?.sendBlocked?.() === true,
4024
- onSubmitted: (text, input) => {
4025
- releaseSentFiles(input);
4026
- return host?.onSubmitted?.(text, input);
4027
- },
4028
- onSent: (text, input) => {
4029
- releaseSentFiles(input);
4030
- return host?.onSent?.(text, input);
4031
- },
4032
- onDeliveryError: host?.onDeliveryError
4033
- });
4034
- const conversation = useMemo4(
4035
- () => conversationTimeline(feed.timeline, queue, composer),
4036
- [feed.timeline, queue, composer]
4037
- );
4038
- const session = detail.session;
4039
- const sessionControl = session?.effectiveControl;
4040
- const timeline = useSessionStartupTimeline(conversation, {
4041
- session: session && sessionControl ? {
4042
- ...session,
4043
- effectiveControl: admissionRecheckControl(
4044
- sessionControl,
4045
- queue.effectiveControl,
4046
- composer.effectiveControl
4047
- )
4048
- } : null,
4049
- events: feed.events,
4050
- optimisticMessages: composer.optimisticMessages,
4051
- hasNewer: feed.hasNewer,
4052
- queue: queue.snapshot,
4053
- pendingPrompt,
4054
- historyReady: sessionId !== null && feed.initialHistoryReady
4055
- });
4056
- const error = detail.error ?? feed.error ?? human.error;
4057
- const loadFailed = Boolean(feed.error) && !feed.initialHistoryReady;
4058
- const retry = async () => {
4059
- await Promise.all([
4060
- ...detail.error ? [detail.refresh()] : [],
4061
- ...human.error ? [human.refresh()] : [],
4062
- ...feed.error ? [feed.jumpToLatest()] : []
4063
- ]);
4064
- };
4065
- return {
4066
- ...scope,
4067
- sessionId,
4068
- config,
4069
- catalog,
4070
- showModelPicker,
4071
- feed,
4072
- detail,
4073
- queue,
4074
- human,
4075
- control,
4076
- approvals,
4077
- files,
4078
- uploadsEnabled,
4079
- composer,
4080
- /** The same live application context for text and durable voice messages. */
4081
- getModelContext: () => resolveExtras()?.modelContext,
4082
- timeline,
4083
- status,
4084
- terminal,
4085
- importedArchive,
4086
- running: sessionTurnKeepsRunControl(status),
4087
- error,
4088
- loadFailed,
4089
- retry
4090
- };
4091
- }
4092
- function usePendingPrompt(prompt, sessionId, historyReady) {
4093
- const owner = useRef8({
4094
- sessionId,
4095
- retired: prompt === null
4096
- });
4097
- const current = owner.current;
4098
- if (!current.retired && current.sessionId !== sessionId) {
4099
- if (current.sessionId === null) current.sessionId = sessionId;
4100
- else current.retired = true;
4101
- }
4102
- if (!current.retired && sessionId !== null && historyReady) current.retired = true;
4103
- return current.retired ? null : prompt;
4104
- }
4105
-
4106
- // src/hooks/use-session-read-acknowledgement.ts
4107
- import { useEffect as useEffect6, useMemo as useMemo5, useRef as useRef9 } from "react";
4108
- var SESSION_READ_ACKNOWLEDGEMENT_RETRY_MS = 1e3;
4109
- function isPermanentRejection(error) {
4110
- const status = error && typeof error === "object" ? error.status : void 0;
4111
- return typeof status === "number" && status >= 400 && status < 500 && status !== 408 && status !== 429;
4112
- }
4113
- function useSessionReadAcknowledgement(input) {
4114
- const { client, workspaceId, sessionId, events, active } = input;
4115
- const session = input.session && (input.session.id ?? sessionId) === sessionId ? input.session : null;
4116
- const attentionThrough = useMemo5(() => sessionAttentionReadThroughSequence(events), [events]);
4117
- const { readThrough, unread } = readAcknowledgementFrontier(session, attentionThrough);
4118
- const hasSession = session !== null;
4119
- const receipt = useRef9(null);
4120
- const refused = useRef9(/* @__PURE__ */ new Set());
4121
- const retryTimer = useRef9(null);
4122
- useEffect6(
4123
- () => () => {
4124
- if (retryTimer.current !== null) clearTimeout(retryTimer.current);
4125
- retryTimer.current = null;
4126
- receipt.current = null;
4127
- },
4128
- []
4129
- );
4130
- useEffect6(() => {
4131
- if (!active || !hasSession || !unread || readThrough <= 0) return;
4132
- if (!workspaceId || !sessionId || typeof client.updateSessionAttention !== "function") return;
4133
- const scope = `${workspaceId}:${sessionId}`;
4134
- if (refused.current.has(scope)) return;
4135
- const key = `${scope}:${readThrough}`;
4136
- if (receipt.current === key) return;
4137
- receipt.current = key;
4138
- if (retryTimer.current !== null) clearTimeout(retryTimer.current);
4139
- retryTimer.current = null;
4140
- const attempt = (retried) => {
4141
- void Promise.resolve().then(
4142
- () => client.updateSessionAttention(workspaceId, sessionId, {
4143
- unread: false,
4144
- acknowledgedThroughSequence: readThrough
4145
- })
4146
- ).catch((error) => {
4147
- if (receipt.current !== key) return;
4148
- if (isPermanentRejection(error)) {
4149
- refused.current.add(scope);
4150
- return;
4151
- }
4152
- if (!retried) {
4153
- retryTimer.current = setTimeout(() => {
4154
- retryTimer.current = null;
4155
- if (receipt.current === key) attempt(true);
4156
- }, SESSION_READ_ACKNOWLEDGEMENT_RETRY_MS);
4157
- return;
4158
- }
4159
- receipt.current = null;
4160
- });
4161
- };
4162
- attempt(false);
4163
- }, [active, client, hasSession, readThrough, sessionId, unread, workspaceId]);
4164
- }
4165
-
4166
- // src/hooks/use-new-conversation.ts
4167
- import {
4168
- OpenGeniApiError as OpenGeniApiError2
4169
- } from "@opengeni/sdk";
4170
- import { useLayoutEffect as useLayoutEffect5, useMemo as useMemo6, useRef as useRef10, useState as useState7 } from "react";
4171
- var NOOP_ASYNC = async () => {
4172
- };
4173
- function useNewConversation(options = {}) {
4174
- const t = useOpenGeniText();
4175
- const context = useOpenGeni(options);
4176
- const scope = { client: context.client, workspaceId: context.workspaceId };
4177
- const config = useClientConfigFlags(context.client);
4178
- const showModelPicker = options.modelPicker ?? config.modelSelection;
4179
- const catalog = useWorkspaceModelCatalog({ ...scope, enabled: showModelPicker });
4180
- const files = useFileAttachments(scope);
4181
- const uploadsEnabled = (options.attachments ?? true) && config.uploads;
4182
- const available = options.enabled !== false && (options.createSession !== void 0 || config.sessionCreation);
4183
- const [text, setText] = useState7("");
4184
- const [choice, setChoice] = useState7({});
4185
- const [sending, setSending] = useState7(false);
4186
- const [error, setError] = useState7(null);
4187
- const [pending, setPending] = useState7(null);
4188
- const [completion, setCompletion] = useState7(null);
4189
- const textRef = useRef10(text);
4190
- const textRevision = useRef10(0);
4191
- const choiceRef = useRef10(choice);
4192
- const filesRef = useRef10(files);
4193
- filesRef.current = files;
4194
- const pendingRef = useRef10(null);
4195
- const completionRef = useRef10(null);
4196
- const inFlight = useRef10(false);
4197
- const lifetime = useRef10({ mounted: true, generation: 0 }).current;
4198
- const identity = useMemo6(
4199
- () => ({
4200
- client: context.client,
4201
- workspaceId: context.workspaceId,
4202
- scopeKey: options.scopeKey
4203
- }),
4204
- [context.client, context.workspaceId, options.scopeKey]
4205
- );
4206
- const committedIdentity = useRef10(identity);
4207
- useLayoutEffect5(() => {
4208
- lifetime.mounted = true;
4209
- return () => {
4210
- lifetime.mounted = false;
4211
- lifetime.generation++;
4212
- };
4213
- }, [lifetime]);
4214
- useLayoutEffect5(() => {
4215
- if (committedIdentity.current === identity) return;
4216
- committedIdentity.current = identity;
4217
- lifetime.generation++;
4218
- inFlight.current = false;
4219
- pendingRef.current = null;
4220
- completionRef.current = null;
4221
- textRef.current = "";
4222
- textRevision.current = 0;
4223
- choiceRef.current = {};
4224
- setText("");
4225
- setChoice({});
4226
- setSending(false);
4227
- setError(null);
4228
- setPending(null);
4229
- setCompletion(null);
4230
- filesRef.current.clear();
4231
- }, [identity, lifetime]);
4232
- const ownsScope = () => lifetime.mounted && committedIdentity.current === identity;
4233
- const updateText = (value) => {
4234
- if (!ownsScope()) return;
4235
- if (value !== textRef.current) textRevision.current++;
4236
- textRef.current = value;
4237
- setText(value);
4238
- };
4239
- const updateChoice = (patch) => {
4240
- if (!ownsScope()) return;
4241
- const next = { ...choiceRef.current, ...patch };
4242
- const model = catalog.models.find((row) => row.id === (next.model ?? catalog.defaultModel));
4243
- if (model) {
4244
- if (next.reasoningEffort)
4245
- next.reasoningEffort = coerceReasoningEffortForModel(model, next.reasoningEffort);
4246
- if (next.latencyMode && !runnableLatencyModesForModel(model).includes(next.latencyMode))
4247
- next.latencyMode = "standard";
4248
- }
4249
- choiceRef.current = next;
4250
- setChoice(choiceRef.current);
4251
- };
4252
- const effectivePolicy = () => {
4253
- const model = choiceRef.current.model ?? catalog.defaultModel;
4254
- const definition = catalog.models.find((row) => row.id === model);
4255
- const effort = choiceRef.current.reasoningEffort ?? (definition ? defaultEffortForModel(definition) : config.defaultReasoningEffort ?? "medium");
4256
- return showModelPicker && model ? {
4257
- model,
4258
- reasoningEffort: definition ? coerceReasoningEffortForModel(definition, effort) : effort,
4259
- latencyMode: choiceRef.current.latencyMode ?? "standard"
4260
- } : void 0;
4261
- };
4262
- const create = options.createSession ?? (async (initialMessage, idempotencyKey, input) => {
4263
- const creator = context.client.createSession;
4264
- if (typeof creator !== "function")
4265
- throw new Error(t("hooks.useNewConversation.newChatsAreNotEnabled"));
4266
- const created = await creator.call(context.client, context.workspaceId, {
4267
- ...input.startMode === "realtime" ? {} : { initialMessage },
4268
- idempotencyKey,
4269
- ...input
4270
- });
4271
- return created.id;
4272
- });
4273
- const finishCreation = (accepted) => {
4274
- if (!lifetime.mounted || lifetime.generation !== accepted.generation) return;
4275
- const { attempt, sessionId } = accepted;
4276
- const sentFiles = new Set(attempt.options.resources?.map((resource) => resource.fileId) ?? []);
4277
- const policyChanged = ["model", "reasoningEffort", "latencyMode"].some(
4278
- (field) => choiceRef.current[field] !== attempt.options[field]
4279
- );
4280
- const draft = {
4281
- text: attempt.clearDraft && textRevision.current === attempt.textRevision ? "" : textRef.current,
4282
- resources: filesRef.current.readyResources.filter(
4283
- (resource) => !sentFiles.has(resource.fileId)
4284
- ),
4285
- // Unchanged choices are already part of the created session. Do not
4286
- // replace server-owned defaults with a browser's catalog estimate.
4287
- ...policyChanged ? { policy: effectivePolicy() } : {}
4288
- };
4289
- pendingRef.current = null;
4290
- completionRef.current = null;
4291
- setPending(null);
4292
- setCompletion(null);
4293
- updateText(draft.text);
4294
- filesRef.current.removeReadyFiles(sentFiles);
4295
- notifyObserver(options.onCreated, {
4296
- sessionId,
4297
- initialMessage: attempt.initialMessage,
4298
- sentAt: attempt.sentAt,
4299
- draft,
4300
- ...attempt.realtimeModel ? { realtimeModel: attempt.realtimeModel } : {}
4301
- });
4302
- };
4303
- const finishRef = useRef10(finishCreation);
4304
- finishRef.current = finishCreation;
4305
- useLayoutEffect5(() => {
4306
- if (completion && !files.hasUnresolved) finishRef.current(completion);
4307
- }, [completion, files.hasUnresolved]);
4308
- const deliver = async (attempt) => {
4309
- if (!ownsScope() || inFlight.current || completionRef.current || !available) return false;
4310
- const ownedGeneration = lifetime.generation;
4311
- inFlight.current = true;
4312
- pendingRef.current = attempt;
4313
- setSending(true);
4314
- setError(null);
4315
- setPending(null);
4316
- try {
4317
- const sessionId = await attempt.create(
4318
- attempt.initialMessage,
4319
- attempt.key,
4320
- structuredClone(attempt.options)
4321
- );
4322
- if (!lifetime.mounted || lifetime.generation !== ownedGeneration) return true;
4323
- const accepted = { sessionId, attempt, generation: ownedGeneration };
4324
- completionRef.current = accepted;
4325
- if (filesRef.current.hasUnresolved) setCompletion(accepted);
4326
- else finishCreation(accepted);
4327
- return true;
4328
- } catch (cause) {
4329
- if (!lifetime.mounted || lifetime.generation !== ownedGeneration) return false;
4330
- setError({ cause });
4331
- if (cause instanceof OpenGeniApiError2 && cause.outcomeUnknown === false) {
4332
- pendingRef.current = null;
4333
- } else {
4334
- setPending(attempt);
4335
- }
4336
- return false;
4337
- } finally {
4338
- if (lifetime.mounted && lifetime.generation === ownedGeneration) {
4339
- inFlight.current = false;
4340
- setSending(false);
4341
- }
4342
- }
4343
- };
4344
- const submit = async (explicit) => {
4345
- if (!ownsScope() || !available || inFlight.current || pendingRef.current || uploadsEnabled && filesRef.current.hasUnresolved)
4346
- return false;
4347
- const resources = uploadsEnabled ? filesRef.current.readyResources : [];
4348
- const draftText = explicit ?? textRef.current;
4349
- const initialMessage = draftText.trim() || (resources.length > 0 ? FILE_ONLY_MESSAGE_TEXT(t) : "");
4350
- if (!initialMessage) return false;
4351
- return deliver({
4352
- key: crypto.randomUUID(),
4353
- initialMessage,
4354
- sentAt: (/* @__PURE__ */ new Date()).toISOString(),
4355
- textRevision: textRevision.current,
4356
- clearDraft: explicit === void 0,
4357
- create,
4358
- options: {
4359
- ...resources.length ? { resources: structuredClone(resources) } : {},
4360
- ...showModelPicker ? { ...choiceRef.current } : {}
4361
- }
4362
- });
4363
- };
4364
- const startRealtime = async (model) => {
4365
- if (!ownsScope() || !available || inFlight.current || pendingRef.current || !config.realtimeVoice || !(options.realtimeVoice ?? config.realtimeVoiceOffered))
4366
- return false;
4367
- if (filesRef.current.hasUnresolved) return false;
4368
- return deliver({
4369
- key: crypto.randomUUID(),
4370
- initialMessage: "",
4371
- sentAt: (/* @__PURE__ */ new Date()).toISOString(),
4372
- textRevision: textRevision.current,
4373
- clearDraft: false,
4374
- create,
4375
- options: { ...showModelPicker ? { ...choiceRef.current } : {}, startMode: "realtime" },
4376
- realtimeModel: model
4377
- });
4378
- };
4379
- const composer = {
4380
- value: text,
4381
- setValue: updateText,
4382
- hasDraftContent: () => textRef.current.length > 0 || filesRef.current.attachments.length > 0,
4383
- send: submit,
4384
- steer: submit,
4385
- // Nothing runs before the conversation exists: Send just sends.
4386
- working: false,
4387
- sending,
4388
- canSend: available && !sending && !pending && !completion && (text.trim().length > 0 || uploadsEnabled && files.readyResources.length > 0) && !(uploadsEnabled && files.hasUnresolved),
4389
- pause: NOOP_ASYNC,
4390
- pausing: false,
4391
- resume: NOOP_ASYNC,
4392
- resumeScope: NOOP_ASYNC,
4393
- resuming: false,
4394
- draft: null,
4395
- draftRevision: 0,
4396
- draftLoading: false,
4397
- draftSaving: false,
4398
- draftConflict: null,
4399
- policy: effectivePolicy() ?? null,
4400
- setModel: (model) => updateChoice({ model }),
4401
- setReasoningEffort: (reasoningEffort) => updateChoice({ reasoningEffort }),
4402
- setLatencyMode: (latencyMode) => updateChoice({ latencyMode }),
4403
- draftPersistence: "disabled",
4404
- applyDraft: () => {
4405
- },
4406
- reloadDraft: NOOP_ASYNC,
4407
- resolveDraftConflict: NOOP_ASYNC,
4408
- restoredResources: [],
4409
- removeRestoredResource: () => {
4410
- },
4411
- error: null,
4412
- clearError: () => {
4413
- if (ownsScope()) setError(null);
4414
- }
4415
- };
4416
- return {
4417
- ...scope,
4418
- config,
4419
- files,
4420
- uploadsEnabled,
4421
- available,
4422
- showModelPicker,
4423
- catalog,
4424
- composer,
4425
- realtimeVoiceEnabled: config.realtimeVoice && (options.realtimeVoice ?? config.realtimeVoiceOffered),
4426
- error,
4427
- finishingUploads: completion !== null,
4428
- pending: pending ? { idempotencyKey: pending.key, realtimeModel: pending.realtimeModel } : null,
4429
- retry: () => pendingRef.current ? deliver(pendingRef.current) : Promise.resolve(false),
4430
- startRealtime
4431
- };
4432
- }
4433
-
4434
- export {
4435
- isTitleEvent,
4436
- useSession,
4437
- invokeOlderHistoryLoaderWithReceiptCapture,
4438
- createOlderHistoryLoadReceipt,
4439
- useTurnlessOutputGap,
4440
- SESSION_EVENT_BROWSER_MAX_BYTES,
4441
- SESSION_EVENT_BROWSER_MAX_COUNT,
4442
- SESSION_EVENT_BROWSER_PENDING_MAX_BYTES,
4443
- SESSION_EVENT_BROWSER_PENDING_MAX_COUNT,
4444
- useSessionEvents,
4445
- boundBrowserSessionEventWindow,
4446
- isTurnQueueEvent,
4447
- useTurnQueue,
4448
- isGoalEvent,
4449
- useGoal,
4450
- useSessionControl,
4451
- useAvailableModels,
4452
- useWorkspaceModelCatalog,
4453
- isHumanInputEvent,
4454
- useHumanInputRequests,
4455
- conversationTimeline,
4456
- useSessionStartupTimeline,
4457
- useSessionConversation,
4458
- useSessionReadAcknowledgement,
4459
- useNewConversation
4460
- };
4461
- //# sourceMappingURL=chunk-SWIHWCTW.js.map