@opengeni/react 4.2.1-canary.39642758903001 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (693) hide show
  1. package/dist/app/app-state.js +27 -27
  2. package/dist/app/components/Composer.js +27 -26
  3. package/dist/app/components/agent/agent-capability-picker.js +5 -5
  4. package/dist/app/components/artifacts/artifact-library.js +19 -19
  5. package/dist/app/components/artifacts/chat-interactive-block.js +16 -16
  6. package/dist/app/components/artifacts/inline-chat-image.js +31 -30
  7. package/dist/app/components/artifacts/retained-file-preview.js +35 -34
  8. package/dist/app/components/artifacts/retained-text-preview.js +5 -5
  9. package/dist/app/components/artifacts/site-audience.js +5 -5
  10. package/dist/app/components/artifacts/site-conversations.js +24 -22
  11. package/dist/app/components/artifacts/site-data.js +20 -20
  12. package/dist/app/components/artifacts/site-publishing.js +39 -39
  13. package/dist/app/components/artifacts/site-settings.js +48 -48
  14. package/dist/app/components/billing-class-mark.js +5 -5
  15. package/dist/app/components/capabilities/capability-detail-sheet.js +9 -9
  16. package/dist/app/components/capabilities/capability-logo-source.js +13 -12
  17. package/dist/app/components/capabilities/connection-account-picker.js +2 -2
  18. package/dist/app/components/capabilities/connector-tool-permissions.js +5 -5
  19. package/dist/app/components/capabilities/native-connect-setup.js +14 -13
  20. package/dist/app/components/capabilities/native-connect-setup.js.map +1 -1
  21. package/dist/app/components/capabilities/perform-capability-action.js +3 -3
  22. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +15 -14
  23. package/dist/app/components/capabilities/session-capability-card.js +78 -77
  24. package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
  25. package/dist/app/components/capabilities/session-custom-mcp-card.js +20 -19
  26. package/dist/app/components/capabilities/session-github-card.js +25 -24
  27. package/dist/app/components/capabilities/session-machine-card.js +38 -38
  28. package/dist/app/components/capabilities/use-capabilities-catalog.js +3 -3
  29. package/dist/app/components/capabilities/use-connection-accounts.js +1 -1
  30. package/dist/app/components/command-menu/chat-switcher.d.ts +12 -0
  31. package/dist/app/components/command-menu/chat-switcher.js +142 -0
  32. package/dist/app/components/command-menu/chat-switcher.js.map +1 -0
  33. package/dist/app/components/command-menu/command-menu.d.ts +15 -0
  34. package/dist/app/components/command-menu/command-menu.js +812 -0
  35. package/dist/app/components/command-menu/command-menu.js.map +1 -0
  36. package/dist/app/components/command-menu/keycaps.d.ts +21 -0
  37. package/dist/app/components/command-menu/keycaps.js +12 -0
  38. package/dist/app/components/command-menu/shortcut-sheet.d.ts +12 -0
  39. package/dist/app/components/command-menu/shortcut-sheet.js +150 -0
  40. package/dist/app/components/command-menu/shortcut-sheet.js.map +1 -0
  41. package/dist/app/components/composer-capabilities-menu-body.js +3 -3
  42. package/dist/app/components/composer-mobile-plus-panel.js +21 -21
  43. package/dist/app/components/composer-mobile-plus.js +3 -3
  44. package/dist/app/components/credit-required-gate.js +1 -1
  45. package/dist/app/components/credit-required-prompt.js +16 -16
  46. package/dist/app/components/credits/coupon-redeem.js +2 -2
  47. package/dist/app/components/credits/credit-refusal-notice.d.ts +18 -0
  48. package/dist/app/components/credits/credit-refusal-notice.js +17 -0
  49. package/dist/app/components/cross-slot-deep-link-recovery.js +1 -1
  50. package/dist/app/components/desktop/app-shots.js +6 -6
  51. package/dist/app/components/desktop/this-computer.js +4 -4
  52. package/dist/app/components/feedback.js +5 -5
  53. package/dist/app/components/follow-up-repository-menu-body.js +7 -7
  54. package/dist/app/components/follow-up-repository-picker.js +3 -3
  55. package/dist/app/components/github-app-connect-launcher.js +1 -1
  56. package/dist/app/components/knowledge/agent-learning-settings.js +6 -6
  57. package/dist/app/components/machines/connect-machine-dialog.js +18 -18
  58. package/dist/app/components/manual-repository-editor.js +2 -2
  59. package/dist/app/components/markdown.js +10 -9
  60. package/dist/app/components/message-context-pills.js +2 -2
  61. package/dist/app/components/models/models-ui.js +10 -10
  62. package/dist/app/components/pickers.js +10 -10
  63. package/dist/app/components/rail/rail-context.d.ts +6 -0
  64. package/dist/app/components/rail/rail-context.js +3 -3
  65. package/dist/app/components/rail/rail-sections.js +61 -55
  66. package/dist/app/components/rail/session-browse-order-controls.js +2 -2
  67. package/dist/app/components/rail/session-header.js +50 -36
  68. package/dist/app/components/rail/session-list.js +59 -52
  69. package/dist/app/components/rail/session-row-hover-details.js +25 -23
  70. package/dist/app/components/rail/session-shell.js +96 -91
  71. package/dist/app/components/repository-picker.js +7 -7
  72. package/dist/app/components/secrets/session-secrets-panel.js +4 -4
  73. package/dist/app/components/session/agent-configuration-panel.js +34 -34
  74. package/dist/app/components/session/banners.js +12 -11
  75. package/dist/app/components/session/codex-account-indicator.js +12 -12
  76. package/dist/app/components/session/composer-menu-radio.js +2 -2
  77. package/dist/app/components/session/conversation-find.js +1 -1
  78. package/dist/app/components/session/editable-artifacts-workspace.js +45 -45
  79. package/dist/app/components/session/failed-session-banner.js +12 -12
  80. package/dist/app/components/session/human-input.js +48 -47
  81. package/dist/app/components/session/inspector.js +80 -79
  82. package/dist/app/components/session/inspector.js.map +1 -1
  83. package/dist/app/components/session/message-actions.js +5 -5
  84. package/dist/app/components/session/message-resource-attachments.js +21 -20
  85. package/dist/app/components/session/message-resource-attachments.js.map +1 -1
  86. package/dist/app/components/session/model-account-indicator.js +11 -11
  87. package/dist/app/components/session/model-context-inspector.js +2 -2
  88. package/dist/app/components/session/model-recovery-notice.js +3 -3
  89. package/dist/app/components/session/new-session-settings-menu.js +13 -13
  90. package/dist/app/components/session/sandbox-switcher.js +16 -16
  91. package/dist/app/components/session/sandbox-workspace.js +68 -67
  92. package/dist/app/components/session/search-markdown-highlight.js +11 -10
  93. package/dist/app/components/session/search-results-view.js +12 -11
  94. package/dist/app/components/session/session-admin-access.js +11 -11
  95. package/dist/app/components/session/session-retention.js +4 -4
  96. package/dist/app/components/session/session-search-dialog.d.ts +5 -0
  97. package/dist/app/components/session/session-search-dialog.js +22 -12
  98. package/dist/app/components/session/session-search-dialog.js.map +1 -1
  99. package/dist/app/components/session/session-skill-reviews.js +3 -3
  100. package/dist/app/components/session/session-tenancy-control.js +25 -25
  101. package/dist/app/components/session/session-usage-limit-section.js +9 -9
  102. package/dist/app/components/session/session-wait-status.js +11 -9
  103. package/dist/app/components/session/session-wait-status.js.map +1 -1
  104. package/dist/app/components/session/subagents.js +17 -15
  105. package/dist/app/components/session/subscription-account-menu.js +2 -2
  106. package/dist/app/components/session-connectors-menu-body.js +6 -6
  107. package/dist/app/components/settings/row-select.js +1 -1
  108. package/dist/app/components/transcription-settings.js +2 -2
  109. package/dist/app/components/ui/destructive-confirm.js +8 -8
  110. package/dist/app/components/usage/usage-entry.js +6 -6
  111. package/dist/app/components/workspace-composer-plus.js +22 -21
  112. package/dist/app/embed/session-app.js +264 -258
  113. package/dist/app/lib/actions/actions-provider.d.ts +30 -0
  114. package/dist/app/lib/actions/actions-provider.js +32 -0
  115. package/dist/app/lib/actions/chat-directory.d.ts +30 -0
  116. package/dist/app/lib/actions/chat-operations.d.ts +11 -0
  117. package/dist/app/lib/actions/chat-switcher.d.ts +31 -0
  118. package/dist/app/lib/actions/chords.d.ts +40 -0
  119. package/dist/app/lib/actions/events.d.ts +6 -0
  120. package/dist/app/lib/actions/rank.d.ts +17 -0
  121. package/dist/app/lib/actions/registry.d.ts +71 -0
  122. package/dist/app/lib/codex-usage-query.js +3 -3
  123. package/dist/app/lib/composer-connectors.js +14 -13
  124. package/dist/app/lib/console-text.js +2 -2
  125. package/dist/app/lib/credit-coverage.d.ts +21 -0
  126. package/dist/app/lib/credit-coverage.js +15 -0
  127. package/dist/app/lib/deployment-free-model.js +2 -2
  128. package/dist/app/lib/events.js +19 -18
  129. package/dist/app/lib/failed-session-copy.js +5 -5
  130. package/dist/app/lib/free-credit-gap.d.ts +9 -0
  131. package/dist/app/lib/free-credit-gap.js +4 -2
  132. package/dist/app/lib/integration-connect-analytics.d.ts +1 -1
  133. package/dist/app/lib/integration-connect-analytics.js +1 -1
  134. package/dist/app/lib/integration-connect-redirect.js +1 -1
  135. package/dist/app/lib/model-access-onboarding.js +4 -4
  136. package/dist/app/lib/model-policy.js +1 -1
  137. package/dist/app/lib/models-route.d.ts +6 -2
  138. package/dist/app/lib/models-route.js +6 -3
  139. package/dist/app/lib/models-route.js.map +1 -1
  140. package/dist/app/lib/move-chat-to-machine.js +3 -3
  141. package/dist/app/lib/session-branch-cache.js +15 -13
  142. package/dist/app/lib/session-create.js +2 -2
  143. package/dist/app/lib/session-group-pagination.js +15 -13
  144. package/dist/app/lib/session-hover-facts.js +16 -14
  145. package/dist/app/lib/session-model.js +3 -3
  146. package/dist/app/lib/session-rail.js +11 -9
  147. package/dist/app/lib/session-rename.js +3 -3
  148. package/dist/app/lib/session-search-route.d.ts +1 -1
  149. package/dist/app/lib/session-search-route.js +1 -1
  150. package/dist/app/lib/session-ui-features.d.ts +11 -3
  151. package/dist/app/lib/session-ui-features.js +1 -1
  152. package/dist/app/lib/sessions-group.js +15 -13
  153. package/dist/app/lib/turn-failure-analytics.js +7 -7
  154. package/dist/app/lib/unavailable-session-model.js +2 -2
  155. package/dist/app/lib/use-duplicate-site.js +2 -2
  156. package/dist/app/lib/use-follow-up-repositories.js +3 -3
  157. package/dist/app/lib/use-workspace-machines.js +8 -8
  158. package/dist/app/lib/use-workspace-model-catalog.js +6 -6
  159. package/dist/app/lib/use-workspace-rigs.js +4 -4
  160. package/dist/app/lib/workspace-navigation-preference.js +5 -5
  161. package/dist/app/lib/workspace-scope-context.js +4 -4
  162. package/dist/app/routes/artifacts.js +124 -122
  163. package/dist/app/routes/artifacts.js.map +1 -1
  164. package/dist/app/routes/retained-artifact.js +69 -68
  165. package/dist/app/routes/retained-artifact.js.map +1 -1
  166. package/dist/app/routes/session-unavailable.js +3 -3
  167. package/dist/app/routes/session.js +168 -166
  168. package/dist/app/routes/sessions-index-hydration.js +3 -3
  169. package/dist/app/routes/sessions-index.js +122 -116
  170. package/dist/artifacts-document.js +4 -4
  171. package/dist/artifacts-presentation.js +4 -4
  172. package/dist/artifacts-spreadsheet.js +4 -4
  173. package/dist/artifacts.js +39 -39
  174. package/dist/{browser-viewer-ZRFZX3VN.js → browser-viewer-HPUMK7UP.js} +7 -7
  175. package/dist/{chat-interactive-block-HUMYWVCK.js → chat-interactive-block-22PPECCT.js} +6 -6
  176. package/dist/{chunk-GVIQ7H62.js → chunk-2LUBBDZV.js} +5 -5
  177. package/dist/{chunk-SWWYYGQO.js → chunk-325C2TCI.js} +5 -2
  178. package/dist/chunk-325C2TCI.js.map +1 -0
  179. package/dist/{chunk-XMMVIY7B.js → chunk-3CCJWHQY.js} +2 -2
  180. package/dist/{chunk-XS2FZ6DX.js → chunk-3F5ZPIWI.js} +2 -2
  181. package/dist/{chunk-72US6QNB.js → chunk-3J2YZRY5.js} +2 -2
  182. package/dist/{chunk-D4YQF4E3.js → chunk-3SMJ2BIQ.js} +2 -2
  183. package/dist/{chunk-TBJINQXA.js → chunk-3WCYK36X.js} +17 -17
  184. package/dist/{chunk-WPCF34V6.js → chunk-3WG3CRL7.js} +14 -14
  185. package/dist/{chunk-JI5BYQKO.js → chunk-3X46PNBX.js} +14 -14
  186. package/dist/{chunk-UO36FC3S.js → chunk-46I7MMAL.js} +6 -2
  187. package/dist/chunk-46I7MMAL.js.map +1 -0
  188. package/dist/{chunk-PBK44WJC.js → chunk-4GJ37O6G.js} +2 -2
  189. package/dist/chunk-4IWBQUQU.js +152 -0
  190. package/dist/chunk-4IWBQUQU.js.map +1 -0
  191. package/dist/{chunk-LEXPBQ56.js → chunk-4SKJX3C4.js} +6 -6
  192. package/dist/{chunk-ZA6YD2LW.js → chunk-57SYK776.js} +2 -2
  193. package/dist/{chunk-22LBKJDE.js → chunk-5DIAN5GQ.js} +12 -12
  194. package/dist/{chunk-LJ3TDK2L.js → chunk-5FA455GR.js} +4 -4
  195. package/dist/{chunk-N2BEUKXT.js → chunk-5FBZDEHE.js} +228 -228
  196. package/dist/chunk-5FBZDEHE.js.map +1 -0
  197. package/dist/{chunk-YPR5INHV.js → chunk-5X3E2Z3D.js} +4 -4
  198. package/dist/{chunk-OXNWZTEU.js → chunk-5ZJCL6X4.js} +5 -5
  199. package/dist/{chunk-62OAZ4LO.js → chunk-6C5GQQMC.js} +12 -12
  200. package/dist/{chunk-VGITH57T.js → chunk-6ERTXDZM.js} +4 -4
  201. package/dist/{chunk-ZQ7XQZCF.js → chunk-6FX73Y4I.js} +8 -8
  202. package/dist/{chunk-QZO2KK2F.js → chunk-6P44NG6Y.js} +2 -2
  203. package/dist/{chunk-N2DDJLTM.js → chunk-6T7Y33JA.js} +3 -3
  204. package/dist/{chunk-RBAGC2MJ.js → chunk-75VE5QUS.js} +22 -22
  205. package/dist/{chunk-MRXOGI3O.js → chunk-77CUDSHG.js} +9 -9
  206. package/dist/{chunk-F2GXK2Z6.js → chunk-7G446JFO.js} +431 -348
  207. package/dist/chunk-7G446JFO.js.map +1 -0
  208. package/dist/{chunk-GZ65XQR5.js → chunk-7T7FHSGS.js} +3 -3
  209. package/dist/{chunk-YGAH34CD.js → chunk-A3S26JSP.js} +8 -8
  210. package/dist/{chunk-GYPAO6RS.js → chunk-A664GSDM.js} +8 -8
  211. package/dist/{chunk-JSZSNMDR.js → chunk-ASUYLXKO.js} +2 -2
  212. package/dist/{chunk-RTK7SUPL.js → chunk-AUUJLVA3.js} +7 -7
  213. package/dist/{chunk-OOTBYSCA.js → chunk-BBWKPNJB.js} +5 -5
  214. package/dist/{chunk-BGZIMIUU.js → chunk-BCUYWOQU.js} +2 -2
  215. package/dist/{chunk-EKN4N4LS.js → chunk-BDFMNJZJ.js} +2 -2
  216. package/dist/{chunk-YZKGOWCC.js → chunk-BIDXQAGO.js} +2 -2
  217. package/dist/{chunk-Q2UUANHF.js → chunk-BIKAJ4DY.js} +5 -5
  218. package/dist/{chunk-5IQBF2X3.js → chunk-BJPJ2OUX.js} +3 -3
  219. package/dist/{chunk-EY2EMHZW.js → chunk-BPM2OTYK.js} +8 -8
  220. package/dist/{chunk-MT4TBRQB.js → chunk-BSWS2RUZ.js} +2 -2
  221. package/dist/{chunk-T7YD3VGK.js → chunk-C52MNKXU.js} +12 -12
  222. package/dist/{chunk-THNW33K7.js → chunk-CEUDV4OA.js} +18 -18
  223. package/dist/{chunk-GRLPRM56.js → chunk-CFEFYPNR.js} +8 -2
  224. package/dist/chunk-CFEFYPNR.js.map +1 -0
  225. package/dist/{chunk-LHGIS6SZ.js → chunk-CVK74BH7.js} +2 -2
  226. package/dist/{chunk-DFO2UCYG.js → chunk-CW5I65ZX.js} +11 -11
  227. package/dist/chunk-DKNTQDVL.js +86 -0
  228. package/dist/chunk-DKNTQDVL.js.map +1 -0
  229. package/dist/{chunk-SKRLKQEG.js → chunk-DOSC2HRQ.js} +79 -79
  230. package/dist/{chunk-KVB6XDLP.js → chunk-DPJ2CWVN.js} +2 -2
  231. package/dist/{chunk-4J6V4DH7.js → chunk-DXMRO2MU.js} +3 -3
  232. package/dist/{chunk-42I4O4WQ.js → chunk-EE55IDDR.js} +26 -26
  233. package/dist/{chunk-2RA6XABP.js → chunk-EEERTLFF.js} +12 -12
  234. package/dist/{chunk-PTOTKUKO.js → chunk-EEO744XR.js} +8 -8
  235. package/dist/{chunk-LD3HVI2J.js → chunk-EMFGBAQL.js} +6 -6
  236. package/dist/{chunk-FQGUK4ST.js → chunk-ENPJKVMN.js} +38 -38
  237. package/dist/{chunk-HDHK3SXK.js → chunk-EU6RLHMP.js} +4 -4
  238. package/dist/{chunk-G7VLL3PG.js → chunk-F2YABPRJ.js} +13 -4
  239. package/dist/chunk-F2YABPRJ.js.map +1 -0
  240. package/dist/{chunk-MRUWRQBX.js → chunk-FET6XHGS.js} +2 -2
  241. package/dist/{chunk-M6KUY3YH.js → chunk-FIICQA55.js} +2 -2
  242. package/dist/{chunk-NLWLCYCT.js → chunk-FTZXCPE3.js} +19 -19
  243. package/dist/{chunk-FN2KA3MJ.js → chunk-FUS76DO4.js} +3 -3
  244. package/dist/{chunk-AM4IIPWI.js → chunk-G7N5NPRJ.js} +2 -2
  245. package/dist/{chunk-CCQ7YKOD.js → chunk-GBYZ6653.js} +2 -2
  246. package/dist/{chunk-SOOWLNC5.js → chunk-GJUPLSC5.js} +330 -109
  247. package/dist/chunk-GJUPLSC5.js.map +1 -0
  248. package/dist/{chunk-YKKVIJVX.js → chunk-GQDSC6QZ.js} +5 -5
  249. package/dist/chunk-GQGNRL2L.js +53 -0
  250. package/dist/chunk-GQGNRL2L.js.map +1 -0
  251. package/dist/{chunk-5X6JP75Q.js → chunk-GRSODLVO.js} +4 -4
  252. package/dist/{chunk-73YP3R5X.js → chunk-GSESCQFY.js} +4 -4
  253. package/dist/{chunk-KWB5U3ZT.js → chunk-GWRW4N3T.js} +199 -137
  254. package/dist/chunk-GWRW4N3T.js.map +1 -0
  255. package/dist/{chunk-RTR7RNG4.js → chunk-GYRU4PNM.js} +9 -7
  256. package/dist/{chunk-RTR7RNG4.js.map → chunk-GYRU4PNM.js.map} +1 -1
  257. package/dist/{chunk-MZLEBFUZ.js → chunk-GZD6VBIK.js} +3 -3
  258. package/dist/{chunk-IZR2QRFF.js → chunk-H3HH5AHS.js} +4 -4
  259. package/dist/{chunk-DN3TKURW.js → chunk-H3LIIAGE.js} +4 -54
  260. package/dist/chunk-H3LIIAGE.js.map +1 -0
  261. package/dist/{chunk-NPLEQMNM.js → chunk-H5GWAG4I.js} +7 -5
  262. package/dist/{chunk-NPLEQMNM.js.map → chunk-H5GWAG4I.js.map} +1 -1
  263. package/dist/{chunk-OJPUVUB6.js → chunk-HAOZCLLA.js} +3 -3
  264. package/dist/{chunk-ZBHDGAYL.js → chunk-HEFE4OZJ.js} +2 -2
  265. package/dist/{chunk-WTG34JVA.js → chunk-HI75UTI6.js} +2 -2
  266. package/dist/{chunk-OMBIG3NC.js → chunk-HM633ROV.js} +14 -14
  267. package/dist/{chunk-WDFZWSKD.js → chunk-HRIP4M6H.js} +3 -3
  268. package/dist/{chunk-A2BCW6CQ.js → chunk-HU2DRFFI.js} +3 -3
  269. package/dist/{chunk-PO35PBAB.js → chunk-HVH7FFJH.js} +2 -2
  270. package/dist/{chunk-EG7KNUF7.js → chunk-HYTXTKST.js} +18 -18
  271. package/dist/{chunk-TFHG75A4.js → chunk-I4XMDFUJ.js} +7 -7
  272. package/dist/{chunk-IZHVZZQA.js → chunk-ICAUYWSL.js} +9 -9
  273. package/dist/{chunk-ZSERYHHT.js → chunk-IDMXEPHL.js} +150 -150
  274. package/dist/chunk-IDMXEPHL.js.map +1 -0
  275. package/dist/{chunk-DCLPWYP3.js → chunk-IEVPJ3G6.js} +2 -2
  276. package/dist/{chunk-EVWZHDSF.js → chunk-IKH3VTA4.js} +2 -2
  277. package/dist/{chunk-L5UCO2UV.js → chunk-ILBSBZGC.js} +13 -4
  278. package/dist/chunk-ILBSBZGC.js.map +1 -0
  279. package/dist/{chunk-IO6K6UYJ.js → chunk-IQ64BNAG.js} +4 -2
  280. package/dist/chunk-IQ64BNAG.js.map +1 -0
  281. package/dist/{chunk-TYHLEFD2.js → chunk-IZJNMRIR.js} +9 -9
  282. package/dist/{chunk-D2SR3TEB.js → chunk-J243WGUA.js} +2 -2
  283. package/dist/{chunk-QGSGIYE3.js → chunk-J2C6LB6W.js} +4 -4
  284. package/dist/{chunk-MT6TRTXF.js → chunk-J5MEDX7C.js} +9 -9
  285. package/dist/{chunk-6QHUKBJP.js → chunk-J7SKOO44.js} +2 -2
  286. package/dist/{chunk-W2QK7PYS.js → chunk-JAAST75A.js} +11 -11
  287. package/dist/{chunk-NQCMS4AJ.js → chunk-JQCGPTZ6.js} +9 -9
  288. package/dist/chunk-JRJUSKDY.js +832 -0
  289. package/dist/chunk-JRJUSKDY.js.map +1 -0
  290. package/dist/{chunk-CMUXJHGH.js → chunk-JRSCWQMC.js} +9 -9
  291. package/dist/{chunk-Q4OHNGGB.js → chunk-JRXHSVD5.js} +4 -4
  292. package/dist/{chunk-SD2K5ZN5.js → chunk-JXYLDT6X.js} +4 -4
  293. package/dist/{chunk-S3M5WCZW.js → chunk-KA4LV7G6.js} +35 -50
  294. package/dist/chunk-KA4LV7G6.js.map +1 -0
  295. package/dist/{chunk-IXX6ZOL2.js → chunk-KGTMHEAP.js} +7 -7
  296. package/dist/{chunk-22OBGVEJ.js → chunk-KOXVGPW4.js} +3 -3
  297. package/dist/{chunk-NOZ5CGZE.js → chunk-L5GPPMUB.js} +2 -2
  298. package/dist/{chunk-KIHYJM5F.js → chunk-LXJT4WAW.js} +58 -58
  299. package/dist/{chunk-KIHYJM5F.js.map → chunk-LXJT4WAW.js.map} +1 -1
  300. package/dist/{chunk-4FOOHMTU.js → chunk-LY6727IF.js} +1 -1
  301. package/dist/{chunk-PT7MTXRE.js → chunk-MAOCN7J6.js} +2 -2
  302. package/dist/{chunk-4K2JSJNX.js → chunk-MB5LZVDO.js} +2 -2
  303. package/dist/chunk-MF464AKA.js +139 -0
  304. package/dist/chunk-MF464AKA.js.map +1 -0
  305. package/dist/{chunk-UYSZKDQY.js → chunk-MK54JLE4.js} +1 -1
  306. package/dist/chunk-MK54JLE4.js.map +1 -0
  307. package/dist/{chunk-5LES64PP.js → chunk-MKOQAVOE.js} +21 -21
  308. package/dist/{chunk-BMV2SNYX.js → chunk-MUPWNSEJ.js} +18 -18
  309. package/dist/{chunk-Y5TRG22C.js → chunk-NRXIECWC.js} +2 -2
  310. package/dist/{chunk-GOE7G5JX.js → chunk-NWSAF6P5.js} +2 -2
  311. package/dist/chunk-OB3YGXHQ.js +158 -0
  312. package/dist/chunk-OB3YGXHQ.js.map +1 -0
  313. package/dist/{chunk-DUM363VS.js → chunk-OFZQJNF6.js} +5 -5
  314. package/dist/{chunk-CKN5QPEL.js → chunk-OMF7POEY.js} +2 -2
  315. package/dist/{chunk-MVXKO2BD.js → chunk-OXD6ET34.js} +1 -1
  316. package/dist/{chunk-47JUEVME.js → chunk-PALX6HWV.js} +21 -21
  317. package/dist/{chunk-B6OGSG7I.js → chunk-PE3BLBDT.js} +3 -3
  318. package/dist/{chunk-RVISSNVE.js → chunk-PMZKJOG6.js} +15 -15
  319. package/dist/{chunk-CESAMXWX.js → chunk-PQUTMG3S.js} +2 -2
  320. package/dist/{chunk-7VFCOKPG.js → chunk-PWBGODZU.js} +3 -3
  321. package/dist/{chunk-MOPAXD2H.js → chunk-QCADUTYX.js} +2 -2
  322. package/dist/{chunk-CT5FBO7E.js → chunk-RPOUJI25.js} +1 -1
  323. package/dist/{chunk-VE3FKXJ7.js → chunk-RUSXEE7X.js} +35 -32
  324. package/dist/chunk-RUSXEE7X.js.map +1 -0
  325. package/dist/{chunk-WKHYOS72.js → chunk-RW4GFE56.js} +3 -3
  326. package/dist/{chunk-FH4GO7HO.js → chunk-RYLVVDR7.js} +1 -1
  327. package/dist/{chunk-QZRDCFHI.js → chunk-S66SBBFQ.js} +5 -5
  328. package/dist/{chunk-CQJFIPAH.js → chunk-S7TNV2I7.js} +14 -14
  329. package/dist/{chunk-ZBQSIGGR.js → chunk-SC773IMJ.js} +13 -13
  330. package/dist/{chunk-RZV7SXED.js → chunk-SF3M27AN.js} +37 -12
  331. package/dist/chunk-SF3M27AN.js.map +1 -0
  332. package/dist/{chunk-FBJ2HK7A.js → chunk-SGPJ3YS2.js} +20 -20
  333. package/dist/{chunk-A2EWJQXX.js → chunk-SM5QX6UK.js} +4 -4
  334. package/dist/chunk-SWCLN6JE.js +40 -0
  335. package/dist/chunk-SWCLN6JE.js.map +1 -0
  336. package/dist/{chunk-OS3EQOIS.js → chunk-T4F5TW2X.js} +29 -24
  337. package/dist/chunk-T4F5TW2X.js.map +1 -0
  338. package/dist/{chunk-RKZWCTXV.js → chunk-TAEKDMEF.js} +2 -2
  339. package/dist/{chunk-6AVCAUGL.js → chunk-TASEV25T.js} +3 -3
  340. package/dist/{chunk-3XOISKZC.js → chunk-TLGDPMUX.js} +6 -6
  341. package/dist/{chunk-MOF3XSUM.js → chunk-TREHTIBD.js} +3 -2
  342. package/dist/chunk-TREHTIBD.js.map +1 -0
  343. package/dist/{chunk-HUQHJSPV.js → chunk-TTPXGD5S.js} +68 -33
  344. package/dist/chunk-TTPXGD5S.js.map +1 -0
  345. package/dist/{chunk-NFCYIZHX.js → chunk-TXIIBNCA.js} +7 -3
  346. package/dist/{chunk-NFCYIZHX.js.map → chunk-TXIIBNCA.js.map} +1 -1
  347. package/dist/{chunk-5IUW34PG.js → chunk-TY3QYPJ6.js} +7 -7
  348. package/dist/{chunk-VQFR4EU4.js → chunk-U3JK5VJV.js} +2 -2
  349. package/dist/{chunk-2AWMJO54.js → chunk-U42P3RMZ.js} +5 -5
  350. package/dist/{chunk-2RIUMV7S.js → chunk-UBIJBLUK.js} +234 -234
  351. package/dist/chunk-UBIJBLUK.js.map +1 -0
  352. package/dist/{chunk-GUU75DES.js → chunk-UEJTOPLW.js} +8 -8
  353. package/dist/{chunk-QWCTYLMD.js → chunk-URDONAEJ.js} +240 -204
  354. package/dist/chunk-URDONAEJ.js.map +1 -0
  355. package/dist/{chunk-OZOEWLGR.js → chunk-UT6JAORE.js} +4 -4
  356. package/dist/{chunk-5TELOQA6.js → chunk-UTHPUINA.js} +3 -3
  357. package/dist/{chunk-SOV7DTTU.js → chunk-V6HZ2HJZ.js} +67 -67
  358. package/dist/{chunk-SOV7DTTU.js.map → chunk-V6HZ2HJZ.js.map} +1 -1
  359. package/dist/{chunk-26RQ6JBR.js → chunk-VBVCNH6D.js} +5 -5
  360. package/dist/{chunk-P646DND6.js → chunk-VCMQPCME.js} +2 -2
  361. package/dist/{chunk-LV7FMIMM.js → chunk-VGUHAHHV.js} +2 -2
  362. package/dist/{chunk-GYVXARCY.js → chunk-VIBPFVU4.js} +41 -41
  363. package/dist/{chunk-KHPOKZ6Z.js → chunk-VMAC66JX.js} +6 -6
  364. package/dist/{chunk-SHKRS6I5.js → chunk-VRPNETPK.js} +3 -3
  365. package/dist/{chunk-6U4J6RVS.js → chunk-WCHW4XN7.js} +14 -14
  366. package/dist/{chunk-CJH6QUQJ.js → chunk-WD3UXNJV.js} +3 -3
  367. package/dist/{chunk-H5EVWF6L.js → chunk-WR67FJMX.js} +4 -4
  368. package/dist/{chunk-XLIJ36RG.js → chunk-WRMQ7EX4.js} +5 -5
  369. package/dist/{chunk-VVFWOBAM.js → chunk-WTJUKYB2.js} +15 -16
  370. package/dist/chunk-WTJUKYB2.js.map +1 -0
  371. package/dist/{chunk-7KLCFJ5G.js → chunk-X4PPGXQG.js} +2 -2
  372. package/dist/{chunk-ZE2JTVCQ.js → chunk-X5BMQXFD.js} +11 -11
  373. package/dist/{chunk-OYJY4Y4A.js → chunk-XFNLU7EW.js} +14 -7
  374. package/dist/chunk-XFNLU7EW.js.map +1 -0
  375. package/dist/{chunk-UECU6LZI.js → chunk-XXRBOSWV.js} +3 -3
  376. package/dist/{chunk-SPKAIDWX.js → chunk-XZEFCPBL.js} +2 -2
  377. package/dist/{chunk-EZ5NYRHK.js → chunk-YL6N7QLA.js} +5 -5
  378. package/dist/{chunk-Q2ZJOECN.js → chunk-YMVTIV5L.js} +19 -19
  379. package/dist/chunk-YMVTIV5L.js.map +1 -0
  380. package/dist/{chunk-VAIESMPY.js → chunk-YVBHGMKC.js} +4 -4
  381. package/dist/{chunk-AR62NQXE.js → chunk-Z2S5VQG7.js} +2 -2
  382. package/dist/{chunk-2MXUB3ZO.js → chunk-Z5OGTWMZ.js} +15 -2
  383. package/dist/chunk-Z5OGTWMZ.js.map +1 -0
  384. package/dist/{chunk-7UQJEADK.js → chunk-ZL2O4BYP.js} +2 -2
  385. package/dist/{chunk-FOOITLHR.js → chunk-ZZHBT5WQ.js} +2 -2
  386. package/dist/{chunk-X6VJQJYY.js → chunk-ZZWHKC6A.js} +3 -3
  387. package/dist/components/timeline-annotation-shared.d.ts +1 -9
  388. package/dist/composer-messages.js +2 -2
  389. package/dist/composer.js +15 -15
  390. package/dist/{computer-viewer-D4NHQB5D.js → computer-viewer-S6TE6TN7.js} +8 -8
  391. package/dist/connect.js +12 -11
  392. package/dist/desktop.js +2 -2
  393. package/dist/editor.js +2 -2
  394. package/dist/{embedded-new-voice-X4ZW6SY4.js → embedded-new-voice-ZDZPGX25.js} +8 -8
  395. package/dist/{embedded-voice-4OD6Z3HU.js → embedded-voice-FKCUXSJO.js} +8 -8
  396. package/dist/{fleet-decision-row-5UCJXTDP.js → fleet-decision-row-VCGWYJAV.js} +2 -2
  397. package/dist/hooks/page-wake.d.ts +21 -0
  398. package/dist/hooks/use-session-events.d.ts +1 -0
  399. package/dist/index.js +206 -205
  400. package/dist/interaction.js +9 -9
  401. package/dist/{latest-question-VGVNUGAU.js → latest-question-SINEV4U6.js} +3 -3
  402. package/dist/lib/format.d.ts +3 -2
  403. package/dist/machines.js +6 -6
  404. package/dist/messages/en.d.ts +12 -3
  405. package/dist/messages.js +1 -1
  406. package/dist/model-picker-model.js +2 -2
  407. package/dist/{model-policy-picker-menu-XOPYY6YA.js → model-policy-picker-menu-66JPM3G5.js} +6 -6
  408. package/dist/model-policy-picker-menu-66JPM3G5.js.map +1 -0
  409. package/dist/model-policy.js +1 -1
  410. package/dist/native-previews.js +3 -3
  411. package/dist/{platform-activity-row-56XOVTRA.js → platform-activity-row-LU5WABI2.js} +2 -2
  412. package/dist/{queue-surface-implementation-OZDOBJ6W.js → queue-surface-implementation-Y4OUVS7N.js} +8 -7
  413. package/dist/{queue-surface-implementation-OZDOBJ6W.js.map → queue-surface-implementation-Y4OUVS7N.js.map} +1 -1
  414. package/dist/realtime.js +7 -7
  415. package/dist/{sandbox-files-LJCR437H.js → sandbox-files-NBIVKVCZ.js} +11 -11
  416. package/dist/sandbox-files-NBIVKVCZ.js.map +1 -0
  417. package/dist/session-app.js +266 -260
  418. package/dist/session-list-model.js +3 -3
  419. package/dist/{session-realtime-UISLBZ4A.js → session-realtime-3PALSNMJ.js} +3 -3
  420. package/dist/session-realtime-3PALSNMJ.js.map +1 -0
  421. package/dist/session-realtime.js +2 -2
  422. package/dist/session-ui.js +62 -61
  423. package/dist/session.d.ts +1 -1
  424. package/dist/session.js +17 -17
  425. package/dist/sites.js +2 -2
  426. package/dist/terminal.js +2 -2
  427. package/dist/this-computer.js +3 -3
  428. package/dist/timeline/annotation-model.d.ts +48 -0
  429. package/dist/{timeline-annotation-markers-ACT7XRMW.js → timeline-annotation-markers-6526H2NM.js} +11 -9
  430. package/dist/{timeline-annotation-markers-ACT7XRMW.js.map → timeline-annotation-markers-6526H2NM.js.map} +1 -1
  431. package/dist/{timeline-annotation-selection-2IA7T5VR.js → timeline-annotation-selection-KV5SM6TA.js} +16 -62
  432. package/dist/timeline-annotation-selection-KV5SM6TA.js.map +1 -0
  433. package/dist/{timeline-annotations-dialog-W5B2HMYY.js → timeline-annotations-dialog-7CDHWC7Y.js} +12 -10
  434. package/dist/{timeline-annotations-dialog-W5B2HMYY.js.map → timeline-annotations-dialog-7CDHWC7Y.js.map} +1 -1
  435. package/dist/timeline-model.d.ts +3 -0
  436. package/dist/timeline-model.js +40 -14
  437. package/dist/ui/access-list.js +24 -24
  438. package/dist/ui/choice-cards.js +2 -2
  439. package/dist/ui/composer-menu-action.js +2 -2
  440. package/dist/ui/context-menu.d.ts +3 -1
  441. package/dist/ui/context-menu.js +3 -1
  442. package/dist/ui/detail-page.js +3 -3
  443. package/dist/ui/detail-sheet.js +3 -3
  444. package/dist/ui/diff-view.js +3 -3
  445. package/dist/ui/disclosure.js +5 -5
  446. package/dist/ui/dropdown-menu.js +1 -1
  447. package/dist/ui/flush-form-page.js +5 -5
  448. package/dist/ui/form-dialog.js +4 -4
  449. package/dist/ui/list-row.js +5 -5
  450. package/dist/ui/load-failure.js +3 -3
  451. package/dist/ui/page-actions.js +3 -3
  452. package/dist/ui/revision-history.js +11 -11
  453. package/dist/ui/role-select.js +8 -8
  454. package/dist/ui/segmented-control.js +1 -1
  455. package/dist/ui/settings-nav.js +3 -3
  456. package/dist/ui/toolbar.js +3 -3
  457. package/dist/usage.js +2 -2
  458. package/dist/workbench.js +11 -11
  459. package/package.json +4 -4
  460. package/src/app/app-state.tsx +2 -1
  461. package/src/app/components/command-menu/chat-switcher.tsx +135 -0
  462. package/src/app/components/command-menu/command-menu.tsx +840 -0
  463. package/src/app/components/command-menu/keycaps.tsx +56 -0
  464. package/src/app/components/command-menu/shortcut-sheet.tsx +155 -0
  465. package/src/app/components/credits/credit-refusal-notice.test.tsx +132 -0
  466. package/src/app/components/credits/credit-refusal-notice.tsx +92 -0
  467. package/src/app/components/rail/rail-context.tsx +28 -5
  468. package/src/app/components/rail/rail-sections.tsx +3 -5
  469. package/src/app/components/rail/session-header-mute.test.tsx +23 -1
  470. package/src/app/components/rail/session-header.test.tsx +21 -2
  471. package/src/app/components/rail/session-header.tsx +31 -1
  472. package/src/app/components/rail/session-list.tsx +89 -16
  473. package/src/app/components/rail/session-shell.tsx +0 -14
  474. package/src/app/components/session/session-search-dialog.tsx +12 -1
  475. package/src/app/embed/session-app.tsx +6 -3
  476. package/src/app/lib/actions/actions-provider.tsx +486 -0
  477. package/src/app/lib/actions/actions.test.ts +249 -0
  478. package/src/app/lib/actions/chat-directory.ts +231 -0
  479. package/src/app/lib/actions/chat-operations.ts +145 -0
  480. package/src/app/lib/actions/chat-switcher.ts +62 -0
  481. package/src/app/lib/actions/chords.ts +185 -0
  482. package/src/app/lib/actions/events.ts +10 -0
  483. package/src/app/lib/actions/rank.ts +119 -0
  484. package/src/app/lib/actions/registry.ts +333 -0
  485. package/src/app/lib/credit-coverage.test.ts +83 -0
  486. package/src/app/lib/credit-coverage.tsx +48 -0
  487. package/src/app/lib/free-credit-gap.test.ts +32 -1
  488. package/src/app/lib/free-credit-gap.tsx +32 -2
  489. package/src/app/lib/integration-connect-analytics.test.ts +1 -0
  490. package/src/app/lib/integration-connect-analytics.tsx +4 -0
  491. package/src/app/lib/models-route.test.ts +18 -0
  492. package/src/app/lib/models-route.tsx +26 -4
  493. package/src/app/lib/session-search-route.tsx +6 -1
  494. package/src/app/lib/session-ui-features.tsx +28 -9
  495. package/src/app/routes/session.tsx +74 -16
  496. package/src/app/routes/sessions-index.tsx +83 -4
  497. package/src/components/timeline-annotation-selection.tsx +9 -64
  498. package/src/components/timeline-annotation-shared.ts +9 -57
  499. package/src/hooks/page-wake.ts +80 -0
  500. package/src/hooks/use-session-events.ts +309 -81
  501. package/src/lib/format.ts +3 -2
  502. package/src/messages/en.ts +13 -3
  503. package/src/model-picker-model.ts +3 -0
  504. package/src/model-policy.ts +9 -1
  505. package/src/session.ts +1 -0
  506. package/src/timeline/annotation-model.ts +217 -0
  507. package/src/timeline/projection.ts +27 -21
  508. package/src/timeline-model.ts +14 -0
  509. package/src/ui/context-menu.tsx +16 -0
  510. package/src/ui/dropdown-menu.tsx +4 -1
  511. package/src/ui/segmented-control.tsx +3 -0
  512. package/styles/compiled.css +92 -0
  513. package/dist/app/lib/keyboard-shortcuts.d.ts +0 -51
  514. package/dist/app/lib/keyboard-shortcuts.js +0 -16
  515. package/dist/chunk-2MXUB3ZO.js.map +0 -1
  516. package/dist/chunk-2RIUMV7S.js.map +0 -1
  517. package/dist/chunk-53IXIUYP.js +0 -39
  518. package/dist/chunk-53IXIUYP.js.map +0 -1
  519. package/dist/chunk-DN3TKURW.js.map +0 -1
  520. package/dist/chunk-F2GXK2Z6.js.map +0 -1
  521. package/dist/chunk-G7VLL3PG.js.map +0 -1
  522. package/dist/chunk-GRLPRM56.js.map +0 -1
  523. package/dist/chunk-HUQHJSPV.js.map +0 -1
  524. package/dist/chunk-IO6K6UYJ.js.map +0 -1
  525. package/dist/chunk-KWB5U3ZT.js.map +0 -1
  526. package/dist/chunk-L5UCO2UV.js.map +0 -1
  527. package/dist/chunk-MOF3XSUM.js.map +0 -1
  528. package/dist/chunk-N2BEUKXT.js.map +0 -1
  529. package/dist/chunk-OS3EQOIS.js.map +0 -1
  530. package/dist/chunk-OYJY4Y4A.js.map +0 -1
  531. package/dist/chunk-Q2ZJOECN.js.map +0 -1
  532. package/dist/chunk-QWCTYLMD.js.map +0 -1
  533. package/dist/chunk-RZV7SXED.js.map +0 -1
  534. package/dist/chunk-S3M5WCZW.js.map +0 -1
  535. package/dist/chunk-SOOWLNC5.js.map +0 -1
  536. package/dist/chunk-SWWYYGQO.js.map +0 -1
  537. package/dist/chunk-UO36FC3S.js.map +0 -1
  538. package/dist/chunk-UYSZKDQY.js.map +0 -1
  539. package/dist/chunk-VE3FKXJ7.js.map +0 -1
  540. package/dist/chunk-VVFWOBAM.js.map +0 -1
  541. package/dist/chunk-ZSERYHHT.js.map +0 -1
  542. package/dist/timeline-annotation-selection-2IA7T5VR.js.map +0 -1
  543. package/src/app/lib/keyboard-shortcuts.test.ts +0 -47
  544. package/src/app/lib/keyboard-shortcuts.tsx +0 -58
  545. /package/dist/app/{lib/keyboard-shortcuts.js.map → components/command-menu/keycaps.js.map} +0 -0
  546. /package/dist/{browser-viewer-ZRFZX3VN.js.map → app/components/credits/credit-refusal-notice.js.map} +0 -0
  547. /package/dist/{chat-interactive-block-HUMYWVCK.js.map → app/lib/actions/actions-provider.js.map} +0 -0
  548. /package/dist/{computer-viewer-D4NHQB5D.js.map → app/lib/credit-coverage.js.map} +0 -0
  549. /package/dist/{embedded-new-voice-X4ZW6SY4.js.map → browser-viewer-HPUMK7UP.js.map} +0 -0
  550. /package/dist/{embedded-voice-4OD6Z3HU.js.map → chat-interactive-block-22PPECCT.js.map} +0 -0
  551. /package/dist/{chunk-GVIQ7H62.js.map → chunk-2LUBBDZV.js.map} +0 -0
  552. /package/dist/{chunk-XMMVIY7B.js.map → chunk-3CCJWHQY.js.map} +0 -0
  553. /package/dist/{chunk-XS2FZ6DX.js.map → chunk-3F5ZPIWI.js.map} +0 -0
  554. /package/dist/{chunk-72US6QNB.js.map → chunk-3J2YZRY5.js.map} +0 -0
  555. /package/dist/{chunk-D4YQF4E3.js.map → chunk-3SMJ2BIQ.js.map} +0 -0
  556. /package/dist/{chunk-TBJINQXA.js.map → chunk-3WCYK36X.js.map} +0 -0
  557. /package/dist/{chunk-WPCF34V6.js.map → chunk-3WG3CRL7.js.map} +0 -0
  558. /package/dist/{chunk-JI5BYQKO.js.map → chunk-3X46PNBX.js.map} +0 -0
  559. /package/dist/{chunk-PBK44WJC.js.map → chunk-4GJ37O6G.js.map} +0 -0
  560. /package/dist/{chunk-LEXPBQ56.js.map → chunk-4SKJX3C4.js.map} +0 -0
  561. /package/dist/{chunk-ZA6YD2LW.js.map → chunk-57SYK776.js.map} +0 -0
  562. /package/dist/{chunk-22LBKJDE.js.map → chunk-5DIAN5GQ.js.map} +0 -0
  563. /package/dist/{chunk-LJ3TDK2L.js.map → chunk-5FA455GR.js.map} +0 -0
  564. /package/dist/{chunk-YPR5INHV.js.map → chunk-5X3E2Z3D.js.map} +0 -0
  565. /package/dist/{chunk-OXNWZTEU.js.map → chunk-5ZJCL6X4.js.map} +0 -0
  566. /package/dist/{chunk-62OAZ4LO.js.map → chunk-6C5GQQMC.js.map} +0 -0
  567. /package/dist/{chunk-VGITH57T.js.map → chunk-6ERTXDZM.js.map} +0 -0
  568. /package/dist/{chunk-ZQ7XQZCF.js.map → chunk-6FX73Y4I.js.map} +0 -0
  569. /package/dist/{chunk-QZO2KK2F.js.map → chunk-6P44NG6Y.js.map} +0 -0
  570. /package/dist/{chunk-N2DDJLTM.js.map → chunk-6T7Y33JA.js.map} +0 -0
  571. /package/dist/{chunk-RBAGC2MJ.js.map → chunk-75VE5QUS.js.map} +0 -0
  572. /package/dist/{chunk-MRXOGI3O.js.map → chunk-77CUDSHG.js.map} +0 -0
  573. /package/dist/{chunk-GZ65XQR5.js.map → chunk-7T7FHSGS.js.map} +0 -0
  574. /package/dist/{chunk-YGAH34CD.js.map → chunk-A3S26JSP.js.map} +0 -0
  575. /package/dist/{chunk-GYPAO6RS.js.map → chunk-A664GSDM.js.map} +0 -0
  576. /package/dist/{chunk-JSZSNMDR.js.map → chunk-ASUYLXKO.js.map} +0 -0
  577. /package/dist/{chunk-RTK7SUPL.js.map → chunk-AUUJLVA3.js.map} +0 -0
  578. /package/dist/{chunk-OOTBYSCA.js.map → chunk-BBWKPNJB.js.map} +0 -0
  579. /package/dist/{chunk-BGZIMIUU.js.map → chunk-BCUYWOQU.js.map} +0 -0
  580. /package/dist/{chunk-EKN4N4LS.js.map → chunk-BDFMNJZJ.js.map} +0 -0
  581. /package/dist/{chunk-YZKGOWCC.js.map → chunk-BIDXQAGO.js.map} +0 -0
  582. /package/dist/{chunk-Q2UUANHF.js.map → chunk-BIKAJ4DY.js.map} +0 -0
  583. /package/dist/{chunk-5IQBF2X3.js.map → chunk-BJPJ2OUX.js.map} +0 -0
  584. /package/dist/{chunk-EY2EMHZW.js.map → chunk-BPM2OTYK.js.map} +0 -0
  585. /package/dist/{chunk-MT4TBRQB.js.map → chunk-BSWS2RUZ.js.map} +0 -0
  586. /package/dist/{chunk-T7YD3VGK.js.map → chunk-C52MNKXU.js.map} +0 -0
  587. /package/dist/{chunk-THNW33K7.js.map → chunk-CEUDV4OA.js.map} +0 -0
  588. /package/dist/{chunk-LHGIS6SZ.js.map → chunk-CVK74BH7.js.map} +0 -0
  589. /package/dist/{chunk-DFO2UCYG.js.map → chunk-CW5I65ZX.js.map} +0 -0
  590. /package/dist/{chunk-SKRLKQEG.js.map → chunk-DOSC2HRQ.js.map} +0 -0
  591. /package/dist/{chunk-KVB6XDLP.js.map → chunk-DPJ2CWVN.js.map} +0 -0
  592. /package/dist/{chunk-4J6V4DH7.js.map → chunk-DXMRO2MU.js.map} +0 -0
  593. /package/dist/{chunk-42I4O4WQ.js.map → chunk-EE55IDDR.js.map} +0 -0
  594. /package/dist/{chunk-2RA6XABP.js.map → chunk-EEERTLFF.js.map} +0 -0
  595. /package/dist/{chunk-PTOTKUKO.js.map → chunk-EEO744XR.js.map} +0 -0
  596. /package/dist/{chunk-LD3HVI2J.js.map → chunk-EMFGBAQL.js.map} +0 -0
  597. /package/dist/{chunk-FQGUK4ST.js.map → chunk-ENPJKVMN.js.map} +0 -0
  598. /package/dist/{chunk-HDHK3SXK.js.map → chunk-EU6RLHMP.js.map} +0 -0
  599. /package/dist/{chunk-MRUWRQBX.js.map → chunk-FET6XHGS.js.map} +0 -0
  600. /package/dist/{chunk-M6KUY3YH.js.map → chunk-FIICQA55.js.map} +0 -0
  601. /package/dist/{chunk-NLWLCYCT.js.map → chunk-FTZXCPE3.js.map} +0 -0
  602. /package/dist/{chunk-FN2KA3MJ.js.map → chunk-FUS76DO4.js.map} +0 -0
  603. /package/dist/{chunk-AM4IIPWI.js.map → chunk-G7N5NPRJ.js.map} +0 -0
  604. /package/dist/{chunk-CCQ7YKOD.js.map → chunk-GBYZ6653.js.map} +0 -0
  605. /package/dist/{chunk-YKKVIJVX.js.map → chunk-GQDSC6QZ.js.map} +0 -0
  606. /package/dist/{chunk-5X6JP75Q.js.map → chunk-GRSODLVO.js.map} +0 -0
  607. /package/dist/{chunk-73YP3R5X.js.map → chunk-GSESCQFY.js.map} +0 -0
  608. /package/dist/{chunk-MZLEBFUZ.js.map → chunk-GZD6VBIK.js.map} +0 -0
  609. /package/dist/{chunk-IZR2QRFF.js.map → chunk-H3HH5AHS.js.map} +0 -0
  610. /package/dist/{chunk-OJPUVUB6.js.map → chunk-HAOZCLLA.js.map} +0 -0
  611. /package/dist/{chunk-ZBHDGAYL.js.map → chunk-HEFE4OZJ.js.map} +0 -0
  612. /package/dist/{chunk-WTG34JVA.js.map → chunk-HI75UTI6.js.map} +0 -0
  613. /package/dist/{chunk-OMBIG3NC.js.map → chunk-HM633ROV.js.map} +0 -0
  614. /package/dist/{chunk-WDFZWSKD.js.map → chunk-HRIP4M6H.js.map} +0 -0
  615. /package/dist/{chunk-A2BCW6CQ.js.map → chunk-HU2DRFFI.js.map} +0 -0
  616. /package/dist/{chunk-PO35PBAB.js.map → chunk-HVH7FFJH.js.map} +0 -0
  617. /package/dist/{chunk-EG7KNUF7.js.map → chunk-HYTXTKST.js.map} +0 -0
  618. /package/dist/{chunk-TFHG75A4.js.map → chunk-I4XMDFUJ.js.map} +0 -0
  619. /package/dist/{chunk-IZHVZZQA.js.map → chunk-ICAUYWSL.js.map} +0 -0
  620. /package/dist/{chunk-DCLPWYP3.js.map → chunk-IEVPJ3G6.js.map} +0 -0
  621. /package/dist/{chunk-EVWZHDSF.js.map → chunk-IKH3VTA4.js.map} +0 -0
  622. /package/dist/{chunk-TYHLEFD2.js.map → chunk-IZJNMRIR.js.map} +0 -0
  623. /package/dist/{chunk-D2SR3TEB.js.map → chunk-J243WGUA.js.map} +0 -0
  624. /package/dist/{chunk-QGSGIYE3.js.map → chunk-J2C6LB6W.js.map} +0 -0
  625. /package/dist/{chunk-MT6TRTXF.js.map → chunk-J5MEDX7C.js.map} +0 -0
  626. /package/dist/{chunk-6QHUKBJP.js.map → chunk-J7SKOO44.js.map} +0 -0
  627. /package/dist/{chunk-W2QK7PYS.js.map → chunk-JAAST75A.js.map} +0 -0
  628. /package/dist/{chunk-NQCMS4AJ.js.map → chunk-JQCGPTZ6.js.map} +0 -0
  629. /package/dist/{chunk-CMUXJHGH.js.map → chunk-JRSCWQMC.js.map} +0 -0
  630. /package/dist/{chunk-Q4OHNGGB.js.map → chunk-JRXHSVD5.js.map} +0 -0
  631. /package/dist/{chunk-SD2K5ZN5.js.map → chunk-JXYLDT6X.js.map} +0 -0
  632. /package/dist/{chunk-IXX6ZOL2.js.map → chunk-KGTMHEAP.js.map} +0 -0
  633. /package/dist/{chunk-22OBGVEJ.js.map → chunk-KOXVGPW4.js.map} +0 -0
  634. /package/dist/{chunk-NOZ5CGZE.js.map → chunk-L5GPPMUB.js.map} +0 -0
  635. /package/dist/{chunk-4FOOHMTU.js.map → chunk-LY6727IF.js.map} +0 -0
  636. /package/dist/{chunk-PT7MTXRE.js.map → chunk-MAOCN7J6.js.map} +0 -0
  637. /package/dist/{chunk-4K2JSJNX.js.map → chunk-MB5LZVDO.js.map} +0 -0
  638. /package/dist/{chunk-5LES64PP.js.map → chunk-MKOQAVOE.js.map} +0 -0
  639. /package/dist/{chunk-BMV2SNYX.js.map → chunk-MUPWNSEJ.js.map} +0 -0
  640. /package/dist/{chunk-Y5TRG22C.js.map → chunk-NRXIECWC.js.map} +0 -0
  641. /package/dist/{chunk-GOE7G5JX.js.map → chunk-NWSAF6P5.js.map} +0 -0
  642. /package/dist/{chunk-DUM363VS.js.map → chunk-OFZQJNF6.js.map} +0 -0
  643. /package/dist/{chunk-CKN5QPEL.js.map → chunk-OMF7POEY.js.map} +0 -0
  644. /package/dist/{chunk-MVXKO2BD.js.map → chunk-OXD6ET34.js.map} +0 -0
  645. /package/dist/{chunk-47JUEVME.js.map → chunk-PALX6HWV.js.map} +0 -0
  646. /package/dist/{chunk-B6OGSG7I.js.map → chunk-PE3BLBDT.js.map} +0 -0
  647. /package/dist/{chunk-RVISSNVE.js.map → chunk-PMZKJOG6.js.map} +0 -0
  648. /package/dist/{chunk-CESAMXWX.js.map → chunk-PQUTMG3S.js.map} +0 -0
  649. /package/dist/{chunk-7VFCOKPG.js.map → chunk-PWBGODZU.js.map} +0 -0
  650. /package/dist/{chunk-MOPAXD2H.js.map → chunk-QCADUTYX.js.map} +0 -0
  651. /package/dist/{chunk-CT5FBO7E.js.map → chunk-RPOUJI25.js.map} +0 -0
  652. /package/dist/{chunk-WKHYOS72.js.map → chunk-RW4GFE56.js.map} +0 -0
  653. /package/dist/{chunk-FH4GO7HO.js.map → chunk-RYLVVDR7.js.map} +0 -0
  654. /package/dist/{chunk-QZRDCFHI.js.map → chunk-S66SBBFQ.js.map} +0 -0
  655. /package/dist/{chunk-CQJFIPAH.js.map → chunk-S7TNV2I7.js.map} +0 -0
  656. /package/dist/{chunk-ZBQSIGGR.js.map → chunk-SC773IMJ.js.map} +0 -0
  657. /package/dist/{chunk-FBJ2HK7A.js.map → chunk-SGPJ3YS2.js.map} +0 -0
  658. /package/dist/{chunk-A2EWJQXX.js.map → chunk-SM5QX6UK.js.map} +0 -0
  659. /package/dist/{chunk-RKZWCTXV.js.map → chunk-TAEKDMEF.js.map} +0 -0
  660. /package/dist/{chunk-6AVCAUGL.js.map → chunk-TASEV25T.js.map} +0 -0
  661. /package/dist/{chunk-3XOISKZC.js.map → chunk-TLGDPMUX.js.map} +0 -0
  662. /package/dist/{chunk-5IUW34PG.js.map → chunk-TY3QYPJ6.js.map} +0 -0
  663. /package/dist/{chunk-VQFR4EU4.js.map → chunk-U3JK5VJV.js.map} +0 -0
  664. /package/dist/{chunk-2AWMJO54.js.map → chunk-U42P3RMZ.js.map} +0 -0
  665. /package/dist/{chunk-GUU75DES.js.map → chunk-UEJTOPLW.js.map} +0 -0
  666. /package/dist/{chunk-OZOEWLGR.js.map → chunk-UT6JAORE.js.map} +0 -0
  667. /package/dist/{chunk-5TELOQA6.js.map → chunk-UTHPUINA.js.map} +0 -0
  668. /package/dist/{chunk-26RQ6JBR.js.map → chunk-VBVCNH6D.js.map} +0 -0
  669. /package/dist/{chunk-P646DND6.js.map → chunk-VCMQPCME.js.map} +0 -0
  670. /package/dist/{chunk-LV7FMIMM.js.map → chunk-VGUHAHHV.js.map} +0 -0
  671. /package/dist/{chunk-GYVXARCY.js.map → chunk-VIBPFVU4.js.map} +0 -0
  672. /package/dist/{chunk-KHPOKZ6Z.js.map → chunk-VMAC66JX.js.map} +0 -0
  673. /package/dist/{chunk-SHKRS6I5.js.map → chunk-VRPNETPK.js.map} +0 -0
  674. /package/dist/{chunk-6U4J6RVS.js.map → chunk-WCHW4XN7.js.map} +0 -0
  675. /package/dist/{chunk-CJH6QUQJ.js.map → chunk-WD3UXNJV.js.map} +0 -0
  676. /package/dist/{chunk-H5EVWF6L.js.map → chunk-WR67FJMX.js.map} +0 -0
  677. /package/dist/{chunk-XLIJ36RG.js.map → chunk-WRMQ7EX4.js.map} +0 -0
  678. /package/dist/{chunk-7KLCFJ5G.js.map → chunk-X4PPGXQG.js.map} +0 -0
  679. /package/dist/{chunk-ZE2JTVCQ.js.map → chunk-X5BMQXFD.js.map} +0 -0
  680. /package/dist/{chunk-UECU6LZI.js.map → chunk-XXRBOSWV.js.map} +0 -0
  681. /package/dist/{chunk-SPKAIDWX.js.map → chunk-XZEFCPBL.js.map} +0 -0
  682. /package/dist/{chunk-EZ5NYRHK.js.map → chunk-YL6N7QLA.js.map} +0 -0
  683. /package/dist/{chunk-VAIESMPY.js.map → chunk-YVBHGMKC.js.map} +0 -0
  684. /package/dist/{chunk-AR62NQXE.js.map → chunk-Z2S5VQG7.js.map} +0 -0
  685. /package/dist/{chunk-7UQJEADK.js.map → chunk-ZL2O4BYP.js.map} +0 -0
  686. /package/dist/{chunk-FOOITLHR.js.map → chunk-ZZHBT5WQ.js.map} +0 -0
  687. /package/dist/{chunk-X6VJQJYY.js.map → chunk-ZZWHKC6A.js.map} +0 -0
  688. /package/dist/{model-policy-picker-menu-XOPYY6YA.js.map → computer-viewer-S6TE6TN7.js.map} +0 -0
  689. /package/dist/{sandbox-files-LJCR437H.js.map → embedded-new-voice-ZDZPGX25.js.map} +0 -0
  690. /package/dist/{session-realtime-UISLBZ4A.js.map → embedded-voice-FKCUXSJO.js.map} +0 -0
  691. /package/dist/{fleet-decision-row-5UCJXTDP.js.map → fleet-decision-row-VCGWYJAV.js.map} +0 -0
  692. /package/dist/{latest-question-VGVNUGAU.js.map → latest-question-SINEV4U6.js.map} +0 -0
  693. /package/dist/{platform-activity-row-56XOVTRA.js.map → platform-activity-row-LU5WABI2.js.map} +0 -0
@@ -0,0 +1,56 @@
1
+ import { chordKeys, chordLabel, type Chord, type ChordPlatform } from "../../lib/actions/chords";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ /**
5
+ * A chord as small keycaps: ⌘ ⇧ O on Mac, Ctrl Shift O elsewhere. Screen
6
+ * readers hear the whole chord once ("⌘⇧O") instead of each cap.
7
+ */
8
+ export function Keycaps(props: {
9
+ chord: Chord;
10
+ platform: ChordPlatform;
11
+ /** Shows this on the last cap instead of the chord's key, e.g. "1–9" for a range. */
12
+ keyLabel?: string | undefined;
13
+ /** What screen readers hear instead of the chord's own label. */
14
+ ariaLabel?: string | undefined;
15
+ className?: string | undefined;
16
+ }) {
17
+ const keys = chordKeys(props.chord, props.platform);
18
+ if (props.keyLabel) keys[keys.length - 1] = props.keyLabel;
19
+ return (
20
+ // role="img" makes the label count: browsers and screen readers ignore
21
+ // aria-label on a plain span, and the caps themselves are hidden.
22
+ <span
23
+ role="img"
24
+ className={cn("inline-flex shrink-0 items-center gap-0.5", props.className)}
25
+ aria-label={props.ariaLabel ?? chordLabel(props.chord, props.platform)}
26
+ >
27
+ {keys.map((key) => (
28
+ <kbd
29
+ key={key}
30
+ aria-hidden="true"
31
+ className={cn(
32
+ "inline-flex h-5 min-w-5 items-center justify-center rounded-[5px] border border-border bg-surface-2 px-1 font-sans text-[11px] leading-none font-medium text-fg-muted",
33
+ // Mac symbols read better a touch larger than letters.
34
+ key.length === 1 && /[⌘⇧⌥⌃↩⇥⌫↑↓←→]/.test(key) ? "text-[12px]" : null,
35
+ )}
36
+ >
37
+ {key}
38
+ </kbd>
39
+ ))}
40
+ </span>
41
+ );
42
+ }
43
+
44
+ /** A tooltip's text with its key after it, quieter: "Search sessions ⌘K". */
45
+ export function TooltipWithKeys(props: {
46
+ label: string;
47
+ shortcut: { label: string } | null | undefined;
48
+ }) {
49
+ if (!props.shortcut) return <>{props.label}</>;
50
+ return (
51
+ <span className="inline-flex items-center gap-2">
52
+ {props.label}
53
+ <span className="opacity-60">{props.shortcut.label}</span>
54
+ </span>
55
+ );
56
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * The shortcut sheet (⌘/): every action that has a key, grouped, in the
3
+ * person's own notation. It reads the action registry, so it never drifts from
4
+ * what the keys actually do.
5
+ */
6
+ import { Fragment, type RefObject } from "react";
7
+ import { useAppActions } from "../../lib/actions/actions-provider";
8
+ import { applicableChords, chordLabel, type Chord } from "../../lib/actions/chords";
9
+ import {
10
+ APP_ACTIONS,
11
+ findAction,
12
+ type ActionGroup,
13
+ type AppAction,
14
+ } from "../../lib/actions/registry";
15
+ import { Dialog, DialogContent, DialogDescription, DialogTitle } from "../../../ui/dialog";
16
+ import { Keycaps } from "./keycaps";
17
+
18
+ const GROUPS: ReadonlyArray<{ group: ActionGroup; label: string }> = [
19
+ { group: "chat", label: "Chats" },
20
+ { group: "navigate", label: "Move around" },
21
+ { group: "view", label: "View" },
22
+ { group: "help", label: "Help" },
23
+ ];
24
+
25
+ /** Titles that read better on the sheet than in menus, where the chat is implied. */
26
+ const SHEET_TITLES: Record<string, string> = {
27
+ "chat.copyLink": "Copy chat link",
28
+ "chat.pin": "Pin or unpin chat",
29
+ "go.inbox": "Go to inbox",
30
+ "go.previousChat": "Previous chat",
31
+ "go.nextChat": "Next chat",
32
+ "go.pinnedChat": "Pinned chats 1 to 9",
33
+ "commandMenu.open": "Search chats and actions",
34
+ };
35
+
36
+ type SheetRow = {
37
+ action: AppAction;
38
+ title: string;
39
+ chords: Chord[];
40
+ summary?: string | undefined;
41
+ /** Only the desktop app has this key. */
42
+ desktopOnly: boolean;
43
+ };
44
+
45
+ export default function ShortcutSheet(props: {
46
+ open: boolean;
47
+ onOpenChange: (open: boolean) => void;
48
+ /** Where focus goes back to on close. */
49
+ returnFocus: RefObject<HTMLElement | null>;
50
+ }) {
51
+ const actions = useAppActions();
52
+ if (!actions) return null;
53
+ const { platform, surface } = actions.env;
54
+ const menuAction = findAction("commandMenu.open");
55
+ const menuChord = menuAction ? actions.chordsFor(menuAction)[0] : undefined;
56
+ const rows: SheetRow[] = APP_ACTIONS.flatMap((action) => {
57
+ const here = applicableChords(action.chords, surface, platform);
58
+ const desktop = surface === "web" ? applicableChords(action.chords, "desktop", platform) : [];
59
+ if (here.length === 0 && desktop.length === 0) return [];
60
+ const title =
61
+ SHEET_TITLES[action.id] ??
62
+ (typeof action.title === "string" ? action.title : action.title(actions.env, null));
63
+ const summary = action.chordSummary?.(platform);
64
+ return [
65
+ {
66
+ action,
67
+ title,
68
+ chords: here.length > 0 ? here : desktop,
69
+ summary,
70
+ desktopOnly: here.length === 0,
71
+ },
72
+ ];
73
+ });
74
+
75
+ return (
76
+ <Dialog open={props.open} onOpenChange={props.onOpenChange}>
77
+ <DialogContent
78
+ data-og-shortcut-sheet=""
79
+ className="gap-0 p-0 sm:max-w-[720px] sm:p-0"
80
+ aria-describedby="shortcut-sheet-description"
81
+ // Focus the sheet itself: a ring on the close button reads as a selection.
82
+ onOpenAutoFocus={(event) => {
83
+ event.preventDefault();
84
+ (event.currentTarget as HTMLElement | null)?.focus();
85
+ }}
86
+ onCloseAutoFocus={(event) => {
87
+ const target = props.returnFocus.current;
88
+ if (target?.isConnected) {
89
+ event.preventDefault();
90
+ target.focus({ preventScroll: true });
91
+ }
92
+ }}
93
+ >
94
+ <div className="px-6 pt-6 pb-2 max-sm:px-5 max-sm:pt-5">
95
+ <DialogTitle className="text-base">Keyboard shortcuts</DialogTitle>
96
+ <DialogDescription id="shortcut-sheet-description" className="mt-1 text-sm text-fg-muted">
97
+ {menuChord ? (
98
+ <>
99
+ Press <Keycaps chord={menuChord} platform={platform} className="align-[-4px]" />{" "}
100
+ anywhere to find a chat or run any action.
101
+ </>
102
+ ) : (
103
+ "Every action is also in the command menu."
104
+ )}
105
+ </DialogDescription>
106
+ </div>
107
+ <div className="grid gap-x-10 px-6 pb-6 max-sm:px-5 sm:grid-cols-2">
108
+ {GROUPS.map(({ group, label }) => {
109
+ const groupRows = rows.filter((row) => row.action.group === group);
110
+ if (groupRows.length === 0) return null;
111
+ return (
112
+ <section key={group} aria-label={label} className="min-w-0 pt-4">
113
+ <h3 className="pb-1 text-xs leading-4.5 font-medium text-fg-muted">{label}</h3>
114
+ <dl>
115
+ {groupRows.map((row) => (
116
+ <div
117
+ key={row.action.id}
118
+ className="flex min-h-9 items-center gap-3 border-b border-border/60 py-1 last:border-b-0"
119
+ >
120
+ <dt className="flex min-w-0 flex-1 items-center gap-2 text-sm text-fg-label">
121
+ <span className="truncate">{row.title}</span>
122
+ {row.desktopOnly ? (
123
+ <span className="shrink-0 rounded-full bg-hover px-1.5 py-px text-[11px] leading-4 whitespace-nowrap text-fg-muted">
124
+ Desktop app
125
+ </span>
126
+ ) : null}
127
+ </dt>
128
+ <dd className="flex shrink-0 items-center gap-1.5 text-xs text-fg-muted">
129
+ {row.summary ? (
130
+ <Keycaps
131
+ chord={row.chords[0]!}
132
+ platform={platform}
133
+ keyLabel="1–9"
134
+ ariaLabel={row.summary}
135
+ />
136
+ ) : (
137
+ row.chords.map((chord, index) => (
138
+ <Fragment key={chordLabel(chord, platform)}>
139
+ {index > 0 ? <span>or</span> : null}
140
+ <Keycaps chord={chord} platform={platform} />
141
+ </Fragment>
142
+ ))
143
+ )}
144
+ </dd>
145
+ </div>
146
+ ))}
147
+ </dl>
148
+ </section>
149
+ );
150
+ })}
151
+ </div>
152
+ </DialogContent>
153
+ </Dialog>
154
+ );
155
+ }
@@ -0,0 +1,132 @@
1
+ import { afterEach, beforeAll, expect, mock, test } from "bun:test";
2
+ import { GlobalRegistrator } from "@happy-dom/global-registrator";
3
+ import { act, type ComponentProps, type ReactNode } from "react";
4
+ import { createRoot, type Root } from "react-dom/client";
5
+
6
+ mock.module("../../lib/navigation", () => ({
7
+ Link: ({
8
+ children,
9
+ to,
10
+ params,
11
+ search,
12
+ }: {
13
+ children: ReactNode;
14
+ to: string;
15
+ params: { workspaceId: string };
16
+ search: { section: string };
17
+ }) => (
18
+ <a href={`${to.replace("$workspaceId", params.workspaceId)}?section=${search.section}`}>
19
+ {children}
20
+ </a>
21
+ ),
22
+ }));
23
+
24
+ const { CreditRefusalNotice } = await import("./credit-refusal-notice");
25
+
26
+ beforeAll(() => {
27
+ try {
28
+ GlobalRegistrator.register();
29
+ } catch {
30
+ // Another web test in this process already installed Happy DOM.
31
+ }
32
+ (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
33
+ });
34
+
35
+ let root: Root | undefined;
36
+ afterEach(async () => {
37
+ await act(async () => root?.unmount());
38
+ root = undefined;
39
+ document.body.replaceChildren();
40
+ });
41
+
42
+ const SERVER_MESSAGE =
43
+ "No credits available for this model. Choose a model covered by your promotional credits or add credits.";
44
+
45
+ async function render(props: Partial<ComponentProps<typeof CreditRefusalNotice>> = {}) {
46
+ const container = document.createElement("div");
47
+ document.body.append(container);
48
+ root = createRoot(container);
49
+ await act(async () =>
50
+ root!.render(
51
+ <CreditRefusalNotice
52
+ gap={{
53
+ modelLabel: "Gemini 4 Argon",
54
+ covered: [
55
+ { id: "azure-sol/gpt-6.1-sol", label: "GPT-6.1 Sol" },
56
+ { id: "gpt-6-luna", label: "GPT-6 Luna" },
57
+ ],
58
+ selectionUsable: false,
59
+ }}
60
+ message={SERVER_MESSAGE}
61
+ workspaceId="ws"
62
+ canBuyCredits
63
+ canConnectModel
64
+ {...props}
65
+ />,
66
+ ),
67
+ );
68
+ return container;
69
+ }
70
+
71
+ test("a refused Send names the model, the reason, what the credit covers, and the next steps", async () => {
72
+ const onChooseModel = mock((_id: string) => undefined);
73
+ const container = await render({ onChooseModel });
74
+ const alert = container.querySelector('[role="alert"]');
75
+ expect(alert).not.toBeNull();
76
+ expect(alert!.textContent).toContain("Your credits don't cover Gemini 4 Argon");
77
+ expect(alert!.textContent).toContain(SERVER_MESSAGE);
78
+ expect(alert!.textContent).toContain("Your credits cover GPT-6.1 Sol and GPT-6 Luna.");
79
+ expect(alert!.textContent).not.toContain("—");
80
+ const use = [...container.querySelectorAll("button")].find(
81
+ (button) => button.textContent === "Use GPT-6.1 Sol",
82
+ );
83
+ await act(async () => use!.click());
84
+ expect(onChooseModel).toHaveBeenCalledWith("azure-sol/gpt-6.1-sol");
85
+ const links = [...container.querySelectorAll("a")].map((link) => link.getAttribute("href"));
86
+ expect(links).toEqual(["/workspaces/ws/organization?section=billing"]);
87
+ });
88
+
89
+ test("after switching to a model that can run, the notice says to send again", async () => {
90
+ const container = await render({
91
+ gap: {
92
+ modelLabel: "Gemini 4 Argon",
93
+ covered: [{ id: "gpt-6-luna", label: "GPT-6 Luna" }],
94
+ selectionUsable: true,
95
+ },
96
+ onChooseModel: () => undefined,
97
+ });
98
+ expect(container.textContent).toContain("Send again to use the selected model.");
99
+ expect(container.textContent).not.toContain("Use GPT-6 Luna");
100
+ });
101
+
102
+ test("without covered models it offers credits and a connection, and can be dismissed", async () => {
103
+ const onDismiss = mock(() => undefined);
104
+ const container = await render({
105
+ gap: { modelLabel: "Gemini 4 Argon", covered: [], selectionUsable: false },
106
+ onDismiss,
107
+ });
108
+ expect(container.textContent).not.toContain("Your credits cover");
109
+ const links = [...container.querySelectorAll("a")].map((link) => link.textContent);
110
+ expect(links).toEqual(["Buy credits", "Connect a model"]);
111
+ await act(async () =>
112
+ container.querySelector<HTMLButtonElement>('[aria-label="Dismiss"]')!.click(),
113
+ );
114
+ expect(onDismiss).toHaveBeenCalledTimes(1);
115
+ });
116
+
117
+ test("people who cannot buy credits are not offered a purchase", async () => {
118
+ const container = await render({ canBuyCredits: false, canConnectModel: false });
119
+ expect(container.querySelectorAll("a")).toHaveLength(0);
120
+ expect(container.textContent).toContain(SERVER_MESSAGE);
121
+ });
122
+
123
+ test("the refusal shows the server's sentence, not the SDK's status prefix or reference", async () => {
124
+ // OpenGeniApiError.message for a 402 from the API, as the routes pass it.
125
+ const container = await render({
126
+ message: `API 402: ${SERVER_MESSAGE} Reference: 9f1c2b7e-4d1a-4c55-9a0e-3b8f2d6c1a47.`,
127
+ });
128
+ const alert = container.querySelector('[role="alert"]')!;
129
+ expect(alert.textContent).toContain(SERVER_MESSAGE);
130
+ expect(alert.textContent).not.toContain("API 402");
131
+ expect(alert.textContent).not.toContain("Reference");
132
+ });
@@ -0,0 +1,92 @@
1
+ import { Link } from "../../lib/navigation";
2
+ import { CreditCardIcon } from "lucide-react";
3
+
4
+ import { Button } from "../../../ui/button";
5
+ import { Notice } from "../../../ui/notice";
6
+ import { analyticsAction } from "../../../ui/analytics-actions";
7
+ import { apiErrorFacts } from "../../../ui/api-error";
8
+ import { modelListSummary } from "../../lib/credit-coverage";
9
+ import type { FreeCreditGap } from "../../lib/free-credit-gap";
10
+
11
+ /**
12
+ * The API refused a Send or a new chat because no credit pays for its model.
13
+ * Stays above the composer until the next accepted message, so the refusal is
14
+ * not only a short line under a failed bubble: it names the model, the
15
+ * server's reason, the models the remaining credit covers, and the next step.
16
+ */
17
+ export function CreditRefusalNotice({
18
+ gap,
19
+ message,
20
+ workspaceId,
21
+ canBuyCredits,
22
+ canConnectModel,
23
+ onChooseModel,
24
+ onDismiss,
25
+ }: {
26
+ gap: FreeCreditGap;
27
+ /** The API's refusal text. */
28
+ message?: string | null | undefined;
29
+ workspaceId: string;
30
+ canBuyCredits: boolean;
31
+ canConnectModel: boolean;
32
+ /** Select a covered model in the composer. */
33
+ onChooseModel?: ((id: string) => void) | undefined;
34
+ onDismiss?: (() => void) | undefined;
35
+ }) {
36
+ const switchTo = !gap.selectionUsable && onChooseModel ? gap.covered[0] : undefined;
37
+ const coverage = gap.selectionUsable
38
+ ? "Send again to use the selected model."
39
+ : gap.covered.length > 0
40
+ ? `Your credits cover ${modelListSummary(gap.covered.map((model) => model.label))}.`
41
+ : null;
42
+ const connect = canConnectModel && gap.covered.length === 0 && !gap.selectionUsable;
43
+ // The server's sentence, without the SDK's "API 402:" prefix or the reference.
44
+ const reason = message ? apiErrorFacts(message).serverMessage : undefined;
45
+ return (
46
+ <Notice
47
+ tone="failed"
48
+ live="assertive"
49
+ title={`Your credits don't cover ${gap.modelLabel}`}
50
+ {...(onDismiss ? { onDismiss } : {})}
51
+ >
52
+ <span data-testid="credit-refusal-notice">
53
+ {reason ? <span className="block">{reason}</span> : null}
54
+ {coverage ? <span className="block">{coverage}</span> : null}
55
+ </span>
56
+ {switchTo || canBuyCredits || connect ? (
57
+ <div className="mt-2 flex flex-wrap gap-2">
58
+ {switchTo ? (
59
+ <Button type="button" size="sm" onClick={() => onChooseModel!(switchTo.id)}>
60
+ Use {switchTo.label}
61
+ </Button>
62
+ ) : null}
63
+ {canBuyCredits ? (
64
+ <Button asChild type="button" size="sm" variant={switchTo ? "outline" : "default"}>
65
+ <Link
66
+ to="/workspaces/$workspaceId/organization"
67
+ params={{ workspaceId }}
68
+ search={{ section: "billing" }}
69
+ {...analyticsAction("buy_credits")}
70
+ >
71
+ <CreditCardIcon className="size-3.5" />
72
+ Buy credits
73
+ </Link>
74
+ </Button>
75
+ ) : null}
76
+ {connect ? (
77
+ <Button asChild type="button" size="sm" variant="outline">
78
+ <Link
79
+ to="/workspaces/$workspaceId/organization"
80
+ params={{ workspaceId }}
81
+ search={{ section: "models", workspace: workspaceId }}
82
+ {...analyticsAction("connect_model")}
83
+ >
84
+ Connect a model
85
+ </Link>
86
+ </Button>
87
+ ) : null}
88
+ </div>
89
+ ) : null}
90
+ </Notice>
91
+ );
92
+ }
@@ -18,8 +18,9 @@ import {
18
18
 
19
19
  import { useAppContext } from "../../app-context";
20
20
  import { requestCreateComposerFocus } from "../../lib/create-composer-focus";
21
+ import { requestCommandMenu } from "../../lib/actions/events";
21
22
  import { desktopBridge, desktopCapability } from "../../lib/desktop";
22
- import { OPEN_SESSION_SEARCH_EVENT, requestSessionSearch } from "../../lib/session-search-route";
23
+ import { OPEN_SESSION_SEARCH_EVENT } from "../../lib/session-search-route";
23
24
  import { workspaceManagementLocation } from "../../lib/workspace-management-location";
24
25
  import { useUiEventTarget } from "../../lib/ui-events";
25
26
 
@@ -73,6 +74,12 @@ export type RailContextValue = {
73
74
  drawerTriggerRef: RefObject<HTMLButtonElement | null>;
74
75
  /** Retiring drawers must not take focus from an open search dialog. */
75
76
  restoreDrawerFocus: () => void;
77
+ /**
78
+ * Close the phone drawer for a dialog that takes over from it (search, the
79
+ * command menu). That dialog returns focus itself, so the retiring drawer
80
+ * must not reclaim it when its exit animation ends.
81
+ */
82
+ handOffDrawer: () => void;
76
83
  /** Navigate to a workspace's sessions index (used by the switchers). */
77
84
  openWorkspace: (workspaceId: string) => void;
78
85
  /** Switch organization: navigate to the first workspace in the target org. */
@@ -129,6 +136,8 @@ export function RailProvider({
129
136
  const appContext = useAppContext();
130
137
  const [searchOpen, setSearchOpen] = useState(false);
131
138
  const [searchMounted, setSearchMounted] = useState(false);
139
+ // What to search for when the dialog opens from the ⌘K menu ("Search messages for …").
140
+ const [searchSeed, setSearchSeed] = useState<{ query: string; nonce: number } | null>(null);
132
141
  const searchReturnFocus = useRef<HTMLElement | null>(null);
133
142
  const searchOpenRef = useRef(searchOpen);
134
143
  searchOpenRef.current = searchOpen;
@@ -151,6 +160,13 @@ export function RailProvider({
151
160
  }
152
161
  if (!searchOpenRef.current) drawerTriggerRef.current?.focus({ preventScroll: true });
153
162
  }, []);
163
+ const drawerOpenRef = useRef(drawerOpen);
164
+ drawerOpenRef.current = drawerOpen;
165
+ const handOffDrawer = useCallback(() => {
166
+ if (!drawerOpenRef.current) return;
167
+ suppressDrawerRestore.current = true;
168
+ setDrawerOpenState(false);
169
+ }, []);
154
170
  const changeSearchOpen = useCallback((next: boolean) => {
155
171
  searchOpenRef.current = next;
156
172
  setSearchOpen(next);
@@ -161,6 +177,7 @@ export function RailProvider({
161
177
  event as CustomEvent<{
162
178
  workspaceId?: string | undefined;
163
179
  returnFocus?: HTMLElement | undefined;
180
+ query?: string | undefined;
164
181
  }>
165
182
  ).detail;
166
183
  if (detail?.workspaceId !== workspaceId) return;
@@ -173,14 +190,17 @@ export function RailProvider({
173
190
  ? document.activeElement
174
191
  : null;
175
192
  }
176
- if (drawerOpen) suppressDrawerRestore.current = true;
193
+ if (typeof detail.query === "string" && detail.query) {
194
+ const query = detail.query;
195
+ setSearchSeed((current) => ({ query, nonce: (current?.nonce ?? 0) + 1 }));
196
+ }
177
197
  setSearchMounted(true);
178
198
  changeSearchOpen(true);
179
- setDrawerOpen(false);
199
+ handOffDrawer();
180
200
  };
181
201
  windowEvents.addEventListener(OPEN_SESSION_SEARCH_EVENT, open);
182
202
  return () => windowEvents.removeEventListener(OPEN_SESSION_SEARCH_EVENT, open);
183
- }, [workspaceId, isMobile, drawerOpen, changeSearchOpen, setDrawerOpen, windowEvents]);
203
+ }, [workspaceId, isMobile, changeSearchOpen, handOffDrawer, windowEvents]);
184
204
  useEffect(() => {
185
205
  searchReturnFocus.current = null;
186
206
  changeSearchOpen(false);
@@ -302,7 +322,7 @@ export function RailProvider({
302
322
  if (!bridge) return;
303
323
  return bridge.commands.onCommand((command) => {
304
324
  if (command === "newSession") startNewSession();
305
- else if (command === "searchSessions") requestSessionSearch(windowEvents, workspaceId);
325
+ else if (command === "searchSessions") requestCommandMenu(windowEvents);
306
326
  else if (command === "toggleSidebar") toggleCollapsed();
307
327
  else if (command === "openInbox") {
308
328
  setDrawerOpen(false);
@@ -326,6 +346,7 @@ export function RailProvider({
326
346
  setDrawerOpen,
327
347
  drawerTriggerRef,
328
348
  restoreDrawerFocus,
349
+ handOffDrawer,
329
350
  openWorkspace,
330
351
  openOrg,
331
352
  openSession,
@@ -340,6 +361,7 @@ export function RailProvider({
340
361
  drawerOpen,
341
362
  setDrawerOpen,
342
363
  restoreDrawerFocus,
364
+ handOffDrawer,
343
365
  setCollapsed,
344
366
  toggleCollapsed,
345
367
  openWorkspace,
@@ -360,6 +382,7 @@ export function RailProvider({
360
382
  open={searchOpen}
361
383
  onOpenChange={changeSearchOpen}
362
384
  returnFocus={searchReturnFocus}
385
+ seed={searchSeed}
363
386
  />
364
387
  </Suspense>
365
388
  ) : null}
@@ -9,7 +9,7 @@ import { useRail } from "./rail-context";
9
9
  import { NewSessionLink } from "./session-list";
10
10
  import { Button } from "../../../ui/button";
11
11
  import { Tooltip, TooltipContent, TooltipTrigger } from "../../../ui/tooltip";
12
- import { NEW_SESSION_SHORTCUT, shortcutLabel } from "../../lib/keyboard-shortcuts";
12
+ import { useActionShortcut } from "../../lib/actions/actions-provider";
13
13
  import { Link, useRouterState } from "../../lib/navigation";
14
14
  import { cn } from "../../lib/utils";
15
15
  import { windowControlsInPage } from "../../lib/desktop";
@@ -139,13 +139,11 @@ export function PrimaryNav() {
139
139
  const { primaryNav } = useContext(SessionShellSlotsContext);
140
140
  const pathname = useRouterState({ select: (state) => state.location.pathname });
141
141
  const newSessionActive = pathname === `/workspaces/${rail.workspaceId}/sessions`;
142
- const newChatShortcut = useSessionUiFeature("newChatShortcut");
142
+ const newChatShortcut = useActionShortcut("chat.new");
143
143
  return (
144
144
  <div className={cn("mt-2 grid gap-0.5 px-2", rail.collapsed && "justify-center")}>
145
145
  <NewSessionLink
146
- aria-label={
147
- newChatShortcut ? `New session · ${shortcutLabel(NEW_SESSION_SHORTCUT)}` : "New session"
148
- }
146
+ aria-label={newChatShortcut ? `New session · ${newChatShortcut.label}` : "New session"}
149
147
  className={cn(
150
148
  "group relative flex h-8 items-center rounded-md text-sm font-normal text-fg-label outline-hidden transition-colors pointer-coarse:h-10",
151
149
  "hover:bg-hover hover:text-fg focus-visible:ring-2 focus-visible:ring-ring/50",
@@ -1,10 +1,29 @@
1
1
  import { afterAll, beforeAll, expect, mock, test } from "bun:test";
2
2
  import { GlobalRegistrator } from "@happy-dom/global-registrator";
3
3
  import { act, type ReactNode } from "react";
4
- import { createRoot } from "react-dom/client";
4
+ import { createRoot as createReactRoot } from "react-dom/client";
5
5
 
6
+ import { AppContext, type AppContextValue } from "../../app-context";
6
7
  import type { Session } from "../../types";
7
8
 
9
+ // The header only renders inside the session shell, which always has the app
10
+ // context; its chat actions (copy link, pin) run through it. This test runs
11
+ // none of them, so any read of the context fails loudly.
12
+ const appContext = new Proxy({} as AppContextValue, {
13
+ get(_target, key) {
14
+ throw new Error(`The SessionHeader mute test's app context has no ${String(key)}`);
15
+ },
16
+ });
17
+
18
+ function createRoot(container: Element) {
19
+ const root = createReactRoot(container);
20
+ return {
21
+ render: (node: ReactNode) =>
22
+ root.render(<AppContext.Provider value={appContext}>{node}</AppContext.Provider>),
23
+ unmount: () => root.unmount(),
24
+ };
25
+ }
26
+
8
27
  // The menu's items, rendered inline so the test reads what the person sees.
9
28
  mock.module("../../../ui/dropdown-menu", () => ({
10
29
  DropdownMenu: ({ children }: { children: ReactNode }) => <div>{children}</div>,
@@ -12,6 +31,9 @@ mock.module("../../../ui/dropdown-menu", () => ({
12
31
  DropdownMenuContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
13
32
  DropdownMenuSeparator: () => <hr />,
14
33
  DropdownMenuMeta: ({ children }: { children: ReactNode }) => <span>{children}</span>,
34
+ DropdownMenuShortcut: ({ children }: { children: ReactNode }) => (
35
+ <span aria-hidden>{children}</span>
36
+ ),
15
37
  DropdownMenuItem: ({
16
38
  children,
17
39
  onSelect,
@@ -1,12 +1,31 @@
1
1
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
2
  import { GlobalRegistrator } from "@happy-dom/global-registrator";
3
- import { act } from "react";
4
- import { createRoot } from "react-dom/client";
3
+ import { act, type ReactNode } from "react";
4
+ import { createRoot as createReactRoot } from "react-dom/client";
5
5
 
6
+ import { AppContext, type AppContextValue } from "../../app-context";
6
7
  import type { Session } from "../../types";
7
8
 
8
9
  import { SessionHeader } from "./session-header";
9
10
 
11
+ // The header only renders inside the session shell, which always has the app
12
+ // context; its chat actions (copy link, pin) run through it. None of these
13
+ // tests run one, so any read of the context fails loudly.
14
+ const appContext = new Proxy({} as AppContextValue, {
15
+ get(_target, key) {
16
+ throw new Error(`The SessionHeader test's app context has no ${String(key)}`);
17
+ },
18
+ });
19
+
20
+ function createRoot(container: Element) {
21
+ const root = createReactRoot(container);
22
+ return {
23
+ render: (node: ReactNode) =>
24
+ root.render(<AppContext.Provider value={appContext}>{node}</AppContext.Provider>),
25
+ unmount: () => root.unmount(),
26
+ };
27
+ }
28
+
10
29
  beforeAll(() => {
11
30
  GlobalRegistrator.register();
12
31
  (