@opengeni/react 4.4.1 → 4.5.1-canary.39832248373001
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.
- package/dist/app/app-state.js +15 -15
- package/dist/app/components/Composer.js +19 -19
- package/dist/app/components/artifacts/artifact-browse-controls.js +3 -3
- package/dist/app/components/artifacts/artifact-library.js +9 -9
- package/dist/app/components/artifacts/artifact-page-chrome.js +2 -2
- package/dist/app/components/artifacts/chat-interactive-block.js +14 -14
- package/dist/app/components/artifacts/inline-chat-image.js +22 -21
- package/dist/app/components/artifacts/retained-file-preview.js +24 -23
- package/dist/app/components/artifacts/retained-text-preview.js +2 -2
- package/dist/app/components/artifacts/site-audience.js +2 -2
- package/dist/app/components/artifacts/site-conversations.js +14 -13
- package/dist/app/components/artifacts/site-data.js +4 -4
- package/dist/app/components/artifacts/site-publishing.js +20 -20
- package/dist/app/components/artifacts/site-settings.js +25 -25
- package/dist/app/components/billing-class-mark.js +3 -3
- package/dist/app/components/capabilities/capability-detail-sheet.js +6 -6
- package/dist/app/components/capabilities/capability-logo-source.js +8 -8
- package/dist/app/components/capabilities/connector-tool-permissions.js +3 -3
- package/dist/app/components/capabilities/native-connect-setup.js +8 -8
- package/dist/app/components/capabilities/prepared-mcp-setup-card.js +10 -10
- package/dist/app/components/capabilities/session-capability-card.js +43 -41
- package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
- package/dist/app/components/capabilities/session-chrome-card.js +20 -18
- package/dist/app/components/capabilities/session-custom-mcp-card.js +11 -11
- package/dist/app/components/capabilities/session-github-card.js +13 -13
- package/dist/app/components/capabilities/session-machine-card.js +19 -17
- package/dist/app/components/command-menu/chat-status.js +16 -15
- package/dist/app/components/command-menu/chat-switcher.js +19 -18
- package/dist/app/components/command-menu/chat-switcher.js.map +1 -1
- package/dist/app/components/command-menu/command-menu.js +29 -107
- package/dist/app/components/command-menu/command-menu.js.map +1 -1
- package/dist/app/components/command-menu/shortcut-sheet.js +9 -9
- package/dist/app/components/composer-mobile-plus-panel.js +9 -9
- package/dist/app/components/composer-mobile-plus.js +1 -1
- package/dist/app/components/credit-required-gate.js +1 -1
- package/dist/app/components/credit-required-prompt.js +5 -5
- package/dist/app/components/credits/coupon-redeem.js +2 -2
- package/dist/app/components/credits/credit-refusal-notice.js +2 -2
- package/dist/app/components/desktop/app-shots.js +7 -7
- package/dist/app/components/desktop/this-computer.js +4 -4
- package/dist/app/components/feedback.js +3 -3
- package/dist/app/components/follow-up-repository-menu-body.js +2 -2
- package/dist/app/components/follow-up-repository-picker.js +1 -1
- package/dist/app/components/github-app-connect-launcher.js +2 -2
- package/dist/app/components/in-app-help-link.js +2 -2
- package/dist/app/components/machines/connect-machine-dialog.js +3 -3
- package/dist/app/components/markdown.js +5 -5
- package/dist/app/components/models/models-ui.js +3 -3
- package/dist/app/components/new-session-starters.js +2 -2
- package/dist/app/components/pickers.js +6 -6
- package/dist/app/components/rail/rail-context.js +3 -3
- package/dist/app/components/rail/rail-sections.js +51 -48
- package/dist/app/components/rail/session-header.js +29 -28
- package/dist/app/components/rail/session-list.js +50 -47
- package/dist/app/components/rail/session-row-content.d.ts +6 -2
- package/dist/app/components/rail/session-row-content.js +1 -1
- package/dist/app/components/rail/session-row-hover-details.js +17 -16
- package/dist/app/components/rail/session-shell.js +78 -75
- package/dist/app/components/rail/site-session-group-heading.d.ts +7 -1
- package/dist/app/components/rail/site-session-group-heading.js +20 -3
- package/dist/app/components/repository-picker.js +2 -2
- package/dist/app/components/session/agent-configuration-panel.js +18 -18
- package/dist/app/components/session/artifact-link-boundary.js +2 -2
- package/dist/app/components/session/artifact-session-page.js +5 -5
- package/dist/app/components/session/banners.js +7 -7
- package/dist/app/components/session/codex-account-indicator.js +10 -10
- package/dist/app/components/session/editable-artifacts-workspace.js +24 -24
- package/dist/app/components/session/failed-session-banner.js +6 -6
- package/dist/app/components/session/human-input.js +41 -37
- package/dist/app/components/session/inspector.js +61 -57
- package/dist/app/components/session/inspector.js.map +1 -1
- package/dist/app/components/session/message-actions.js +3 -3
- package/dist/app/components/session/message-resource-attachments.js +12 -11
- package/dist/app/components/session/message-resource-attachments.js.map +1 -1
- package/dist/app/components/session/model-account-indicator.js +9 -9
- package/dist/app/components/session/model-recovery-notice.js +3 -3
- package/dist/app/components/session/new-session-settings-menu.js +8 -8
- package/dist/app/components/session/sandbox-switcher.js +12 -12
- package/dist/app/components/session/sandbox-workspace.js +58 -54
- package/dist/app/components/session/search-markdown-highlight.js +6 -6
- package/dist/app/components/session/search-results-view.js +7 -7
- package/dist/app/components/session/session-admin-access.js +3 -3
- package/dist/app/components/session/session-admission-notice.js +5 -5
- package/dist/app/components/session/session-machine-access-notice.js +5 -5
- package/dist/app/components/session/session-search-dialog.js +8 -8
- package/dist/app/components/session/session-tenancy-control.d.ts +2 -0
- package/dist/app/components/session/session-tenancy-control.js +26 -11
- package/dist/app/components/session/session-tenancy-control.js.map +1 -1
- package/dist/app/components/session/session-usage-limit-section.js +4 -4
- package/dist/app/components/session/session-wait-status.js +8 -7
- package/dist/app/components/session/session-wait-status.js.map +1 -1
- package/dist/app/components/session/site-origin-link.d.ts +1 -0
- package/dist/app/components/session/site-origin-link.js +2 -2
- package/dist/app/components/session/subagents.js +13 -12
- package/dist/app/components/settings/row-select.js +3 -3
- package/dist/app/components/transcription-settings.js +4 -4
- package/dist/app/components/usage/usage-entry.js +5 -5
- package/dist/app/components/workspace-composer-plus.js +12 -12
- package/dist/app/embed/memory-navigation.js +2 -2
- package/dist/app/embed/session-app.js +196 -190
- package/dist/app/lib/actions/actions-provider.js +9 -9
- package/dist/app/lib/actions/held-modifier.d.ts +11 -0
- package/dist/app/lib/app-surfaces.js +2 -2
- package/dist/app/lib/codex-usage-query.js +6 -6
- package/dist/app/lib/composer-connectors.js +9 -9
- package/dist/app/lib/console-site.d.ts +6 -0
- package/dist/app/lib/console-site.js +14 -0
- package/dist/app/lib/console-text.js +2 -2
- package/dist/app/lib/events.js +13 -12
- package/dist/app/lib/failed-session-copy.js +3 -3
- package/dist/app/lib/model-access-onboarding.js +3 -3
- package/dist/app/lib/move-chat-to-machine.js +3 -3
- package/dist/app/lib/navigation.d.ts +5 -0
- package/dist/app/lib/navigation.js +1 -1
- package/dist/app/lib/routes.d.ts +17 -0
- package/dist/app/lib/routes.js +9 -3
- package/dist/app/lib/session-branch-cache.js +12 -11
- package/dist/app/lib/session-create.js +2 -2
- package/dist/app/lib/session-deep-link.js +2 -2
- package/dist/app/lib/session-failure-toasts.d.ts +8 -0
- package/dist/app/lib/session-group-pagination.js +12 -11
- package/dist/app/lib/session-hover-facts.js +12 -11
- package/dist/app/lib/session-model.js +2 -2
- package/dist/app/lib/session-rail.js +8 -7
- package/dist/app/lib/session-rename.js +2 -2
- package/dist/app/lib/session-ui-features.d.ts +6 -1
- package/dist/app/lib/session-ui-features.js +1 -1
- package/dist/app/lib/sessions-group.d.ts +43 -3
- package/dist/app/lib/sessions-group.js +19 -12
- package/dist/app/lib/shared-query.js +3 -3
- package/dist/app/lib/site-opened.d.ts +6 -0
- package/dist/app/lib/site-opened.js +10 -0
- package/dist/app/lib/turn-failure-analytics.js +5 -5
- package/dist/app/lib/use-duplicate-site.js +2 -2
- package/dist/app/lib/use-follow-up-repositories.js +2 -2
- package/dist/app/lib/use-session-list-hint-refresh.d.ts +20 -2
- package/dist/app/lib/use-session-list-hint-refresh.js +5 -1
- package/dist/app/lib/use-workspace-machines.js +5 -5
- package/dist/app/lib/use-workspace-model-catalog.js +7 -7
- package/dist/app/lib/use-workspace-rigs.js +7 -7
- package/dist/app/lib/workspace-navigation-preference.js +4 -4
- package/dist/app/lib/workspace-scope-context.js +3 -3
- package/dist/app/routes/artifacts.js +70 -87
- package/dist/app/routes/artifacts.js.map +1 -1
- package/dist/app/routes/retained-artifact.js +36 -35
- package/dist/app/routes/retained-artifact.js.map +1 -1
- package/dist/app/routes/session-unavailable.js +6 -4
- package/dist/app/routes/session.js +127 -123
- package/dist/app/routes/sessions-index-hydration.js +3 -3
- package/dist/app/routes/sessions-index.js +96 -94
- package/dist/app/routes/site-view.d.ts +11 -0
- package/dist/app/routes/site-view.js +597 -0
- package/dist/app/routes/site-view.js.map +1 -0
- package/dist/artifacts-document.js +4 -4
- package/dist/artifacts-presentation.js +4 -4
- package/dist/artifacts-spreadsheet.js +4 -4
- package/dist/artifacts.js +13 -13
- package/dist/{browser-viewer-RYYQSRTC.js → browser-viewer-VPK3CV2H.js} +7 -5
- package/dist/{chat-interactive-block-ABCRKXJ4.js → chat-interactive-block-AMDSW656.js} +5 -5
- package/dist/chunk-22GTC4MZ.js +15 -0
- package/dist/chunk-22GTC4MZ.js.map +1 -0
- package/dist/{chunk-RQDFYQHA.js → chunk-25LWDG5D.js} +6 -6
- package/dist/{chunk-U3HSFCON.js → chunk-2CKVVAGP.js} +15 -15
- package/dist/{chunk-F6LBGYS6.js → chunk-2DL6NJP5.js} +15 -15
- package/dist/{chunk-UHFWF6ZU.js → chunk-2FPS5H2D.js} +2 -2
- package/dist/{chunk-NAWXARTY.js → chunk-2KO2G3RI.js} +72 -6
- package/dist/chunk-2KO2G3RI.js.map +1 -0
- package/dist/{chunk-TWXIFWBD.js → chunk-34EU25RL.js} +2 -2
- package/dist/{chunk-PTGRFAMH.js → chunk-3ABPIUCK.js} +2 -2
- package/dist/{chunk-722UO6YQ.js → chunk-3PEXVG4D.js} +2 -2
- package/dist/{chunk-N3ZP4IDU.js → chunk-45WYYFP6.js} +2 -2
- package/dist/{chunk-HOJGAJAB.js → chunk-4MQLGMV2.js} +5 -5
- package/dist/{chunk-L7YURQI2.js → chunk-4U4GXWXS.js} +3 -3
- package/dist/{chunk-63VGE4OH.js → chunk-5HIOVXOX.js} +3 -3
- package/dist/{chunk-GFUUFM2O.js → chunk-5M23GZA2.js} +3 -3
- package/dist/{chunk-PM3OSANE.js → chunk-5MJHH72T.js} +14 -3
- package/dist/chunk-5MJHH72T.js.map +1 -0
- package/dist/{chunk-RKB2Z457.js → chunk-5VGJXWQ2.js} +2 -2
- package/dist/{chunk-6W3LF3DB.js → chunk-5YFY4SFC.js} +2 -12
- package/dist/chunk-5YFY4SFC.js.map +1 -0
- package/dist/{chunk-I6VUUEXH.js → chunk-6AFSZKZA.js} +3 -3
- package/dist/{chunk-FBMU3VK5.js → chunk-6DCEDIF6.js} +2 -2
- package/dist/{chunk-5MZTJMZ3.js → chunk-6MRY2RUZ.js} +13 -7
- package/dist/chunk-6MRY2RUZ.js.map +1 -0
- package/dist/{chunk-4EONHNJU.js → chunk-6O4VWKSO.js} +2 -2
- package/dist/chunk-756MKA2J.js +45 -0
- package/dist/chunk-756MKA2J.js.map +1 -0
- package/dist/{chunk-BSX2R4CW.js → chunk-767WCGAX.js} +6 -6
- package/dist/{chunk-7KGKDWWR.js → chunk-7HFLYNWN.js} +2 -2
- package/dist/{chunk-OSVHU2WU.js → chunk-7IYAHFPE.js} +2 -2
- package/dist/{chunk-4EAF3HSD.js → chunk-7J7PZB4S.js} +2 -2
- package/dist/{chunk-ADJJQSYC.js → chunk-7PUFAH4I.js} +34 -32
- package/dist/chunk-7PUFAH4I.js.map +1 -0
- package/dist/{chunk-OR37STQZ.js → chunk-7R2JQHBX.js} +3 -3
- package/dist/{chunk-QM5H4FPT.js → chunk-7VN6VC3D.js} +3 -3
- package/dist/{chunk-HWDGJFM4.js → chunk-A2E3ZF6N.js} +4 -4
- package/dist/{chunk-RGW24ZZM.js → chunk-A6CK4ENG.js} +19 -17
- package/dist/chunk-A6CK4ENG.js.map +1 -0
- package/dist/{chunk-4432A3HQ.js → chunk-A6T4FGE7.js} +4 -4
- package/dist/{chunk-73SOCVLS.js → chunk-AIEXYO2X.js} +3 -3
- package/dist/{chunk-U7TC2XJQ.js → chunk-AJPW3SV4.js} +3 -3
- package/dist/{chunk-46VBQG2D.js → chunk-AOUCHCSB.js} +5 -5
- package/dist/{chunk-HDHK3SXK.js → chunk-AT4K4F6S.js} +2 -2
- package/dist/{chunk-TQGJN5UZ.js → chunk-AW3QEFOF.js} +140 -522
- package/dist/chunk-AW3QEFOF.js.map +1 -0
- package/dist/{chunk-HRJQAFKR.js → chunk-AX6YJA5U.js} +2 -2
- package/dist/{chunk-HO5Y2OOX.js → chunk-BLPXOHG6.js} +6 -6
- package/dist/{chunk-DT7BORXG.js → chunk-BMJTNPWK.js} +2 -2
- package/dist/{chunk-HIHO2QE7.js → chunk-BT2MVGHT.js} +2 -2
- package/dist/{chunk-AOLE4IRZ.js → chunk-C535KSTY.js} +2 -2
- package/dist/{chunk-IVOA3DXA.js → chunk-CB574ERL.js} +4 -4
- package/dist/{chunk-IBTXYLBW.js → chunk-CCFWY4GF.js} +2 -2
- package/dist/{chunk-ZOC3OP6F.js → chunk-CCR33J7L.js} +2 -2
- package/dist/{chunk-NYZQ7LO7.js → chunk-CDUDKETD.js} +2 -2
- package/dist/{chunk-JTN3T4QN.js → chunk-D3RK3NGM.js} +4 -4
- package/dist/{chunk-IOKSNX74.js → chunk-D5OWJZQR.js} +2 -2
- package/dist/{chunk-BJIZ7PL7.js → chunk-D64Z4V26.js} +145 -29
- package/dist/chunk-D64Z4V26.js.map +1 -0
- package/dist/{chunk-XWWXIZFP.js → chunk-DFXZYNTX.js} +7 -7
- package/dist/{chunk-SQGXMHJO.js → chunk-DGLRZMXL.js} +3 -3
- package/dist/{chunk-GNEHAPKV.js → chunk-DJFTH2DI.js} +3 -3
- package/dist/{chunk-KWKGBGAF.js → chunk-DKCX643S.js} +11 -11
- package/dist/{chunk-HQG4SLTE.js → chunk-DYJGYGPB.js} +2 -2
- package/dist/{chunk-GTQ3SNEI.js → chunk-E36IC3LU.js} +2 -2
- package/dist/{chunk-CVG4FILQ.js → chunk-ECHYJP63.js} +253 -1008
- package/dist/chunk-ECHYJP63.js.map +1 -0
- package/dist/{chunk-Q35DT6I6.js → chunk-EH7TTYE6.js} +179 -170
- package/dist/chunk-EH7TTYE6.js.map +1 -0
- package/dist/{chunk-72J6C2AJ.js → chunk-EMCB6XKU.js} +2 -2
- package/dist/{chunk-3AA6RNGE.js → chunk-ENS6E4RZ.js} +2 -2
- package/dist/{chunk-AG7VGUIW.js → chunk-ERG355NM.js} +3 -3
- package/dist/{chunk-TSBE4KOQ.js → chunk-EWL6NDOO.js} +3 -3
- package/dist/{chunk-Z5WMLJKI.js → chunk-F2RMKGDQ.js} +89 -1
- package/dist/chunk-F2RMKGDQ.js.map +1 -0
- package/dist/{chunk-X7L4H4VG.js → chunk-F33EDYS7.js} +524 -426
- package/dist/chunk-F33EDYS7.js.map +1 -0
- package/dist/{chunk-HTT3FB7T.js → chunk-F3FN6DO6.js} +2 -2
- package/dist/{chunk-ST22GONV.js → chunk-FB3B45FP.js} +11 -11
- package/dist/{chunk-P5T36BA3.js → chunk-FRP64DEK.js} +2 -2
- package/dist/{chunk-KBF3SE7G.js → chunk-FSP334UU.js} +2 -2
- package/dist/{chunk-4VKA5O7T.js → chunk-FVL4B552.js} +9 -9
- package/dist/{chunk-VP62LPLW.js → chunk-G2BX56CN.js} +5 -5
- package/dist/{chunk-CSHBR2IZ.js → chunk-GDLDBR6B.js} +2 -2
- package/dist/{chunk-PN66T6JA.js → chunk-GFSOXB2K.js} +2 -2
- package/dist/{chunk-S4EZ3JUB.js → chunk-GZGQHQI7.js} +29 -29
- package/dist/chunk-H4IE2PYF.js +792 -0
- package/dist/chunk-H4IE2PYF.js.map +1 -0
- package/dist/{chunk-XFNLU7EW.js → chunk-H5M33DAL.js} +15 -6
- package/dist/chunk-H5M33DAL.js.map +1 -0
- package/dist/{chunk-BXRIQZAH.js → chunk-HNNM2GDN.js} +3 -3
- package/dist/{chunk-EU6XSQFM.js → chunk-HPB4KSV3.js} +2 -2
- package/dist/{chunk-QCD5Y7K5.js → chunk-HSQRYJ4P.js} +5 -5
- package/dist/{chunk-YXOKAG66.js → chunk-HUXDGWAN.js} +2 -2
- package/dist/{chunk-VUHPA3XQ.js → chunk-I66ZB6KD.js} +3 -3
- package/dist/{chunk-7CZTKBTI.js → chunk-IC7KNOBB.js} +5 -5
- package/dist/{chunk-KF3MF6FP.js → chunk-IECRGM6K.js} +3 -2
- package/dist/chunk-IECRGM6K.js.map +1 -0
- package/dist/{chunk-HGMWMK5K.js → chunk-IIO2MR3B.js} +2 -2
- package/dist/chunk-IJYL5BZM.js +38 -0
- package/dist/chunk-IJYL5BZM.js.map +1 -0
- package/dist/{chunk-L6RXRRN3.js → chunk-ILDOW2IQ.js} +3 -3
- package/dist/{chunk-O756O2I7.js → chunk-IPPVX5GF.js} +1 -1
- package/dist/{chunk-X7ASQHR6.js → chunk-IUK5QGP5.js} +2 -2
- package/dist/{chunk-5JZYPZ72.js → chunk-JFK7NTEA.js} +4 -4
- package/dist/chunk-JFK7NTEA.js.map +1 -0
- package/dist/{chunk-PIVGX42P.js → chunk-JNY5MT3I.js} +2 -2
- package/dist/chunk-JRSNCSZN.js +37 -0
- package/dist/chunk-JRSNCSZN.js.map +1 -0
- package/dist/{chunk-DDK4WFJ3.js → chunk-JWN7SLTO.js} +9 -9
- package/dist/{chunk-Q35YZVDZ.js → chunk-KFWVBTUH.js} +3 -3
- package/dist/{chunk-JXT5QDJC.js → chunk-KNFDWNCH.js} +5 -5
- package/dist/{chunk-AZVANYMB.js → chunk-KUNFUSZ7.js} +2 -2
- package/dist/{chunk-DXZNDKQD.js → chunk-LEEJBZ5B.js} +2 -2
- package/dist/{chunk-STUCI6QA.js → chunk-LEKBNKLD.js} +1 -1
- package/dist/{chunk-STUCI6QA.js.map → chunk-LEKBNKLD.js.map} +1 -1
- package/dist/{chunk-RSNYGEVZ.js → chunk-LKJ2C7PH.js} +8 -8
- package/dist/{chunk-RIMKJBCD.js → chunk-LMPTC4CX.js} +2 -2
- package/dist/{chunk-3KVWXKD6.js → chunk-LQ47YL6E.js} +2 -2
- package/dist/{chunk-GAIM5RNE.js → chunk-MJQBC7C5.js} +3 -3
- package/dist/{chunk-NWZW2WHN.js → chunk-MM7OKOTE.js} +6 -6
- package/dist/{chunk-FM4OUCC2.js → chunk-MOKYT3X3.js} +3 -3
- package/dist/{chunk-GZ64CASI.js → chunk-MVZYNZXE.js} +5 -4
- package/dist/chunk-MVZYNZXE.js.map +1 -0
- package/dist/{chunk-XRRSFQEV.js → chunk-NAZZLAWX.js} +2 -2
- package/dist/{chunk-XOFUXMPP.js → chunk-ND2WCWXI.js} +4 -4
- package/dist/{chunk-6L7U46Y2.js → chunk-NKNVIO66.js} +2 -2
- package/dist/{chunk-JKUICTLM.js → chunk-NLAFNMPK.js} +2 -2
- package/dist/{chunk-OO2T63BY.js → chunk-NML44AW2.js} +2 -2
- package/dist/chunk-NQQKOJDI.js +89 -0
- package/dist/chunk-NQQKOJDI.js.map +1 -0
- package/dist/{chunk-4LKNIGHB.js → chunk-O2SBHS2N.js} +2 -2
- package/dist/{chunk-RA3FNMWF.js → chunk-O4DYOSOL.js} +5 -5
- package/dist/{chunk-ZKYYZH6L.js → chunk-OFB6TUDC.js} +4 -4
- package/dist/{chunk-DWPOQ3S5.js → chunk-OTMWHZBY.js} +2 -2
- package/dist/{chunk-VVCDB2T7.js → chunk-PCJLH45G.js} +3 -3
- package/dist/{chunk-WSMYOLHG.js → chunk-PEKPWK5M.js} +2 -2
- package/dist/{chunk-PZ24CYDO.js → chunk-PFAUGEV5.js} +2 -2
- package/dist/{chunk-KTRKZRID.js → chunk-PKEKZ2VA.js} +5 -5
- package/dist/{chunk-6JKZILLF.js → chunk-PMD7V4N7.js} +3 -3
- package/dist/{chunk-B74GSYR6.js → chunk-PUTS4DYW.js} +2 -2
- package/dist/{chunk-ZRJCGBVV.js → chunk-PVR5EELP.js} +2 -2
- package/dist/{chunk-JSIDLTTG.js → chunk-PZ2V2XIK.js} +2 -2
- package/dist/{chunk-TMEQPODK.js → chunk-PZ37VDB5.js} +2 -2
- package/dist/{chunk-FLGUVRR7.js → chunk-QBADR2FO.js} +6 -6
- package/dist/{chunk-TGVVEGZG.js → chunk-QLIDZGPV.js} +6 -6
- package/dist/{chunk-LVONK3YQ.js → chunk-QRKTESVE.js} +2 -2
- package/dist/{chunk-HT5WSUC7.js → chunk-QXEDIDBZ.js} +3 -3
- package/dist/{chunk-WURSS6MP.js → chunk-R66YMYJU.js} +2 -2
- package/dist/{chunk-6PQNLL4E.js → chunk-R7XCJWCD.js} +11 -11
- package/dist/{chunk-4R3JCVID.js → chunk-RAMZTZOB.js} +360 -103
- package/dist/chunk-RAMZTZOB.js.map +1 -0
- package/dist/{chunk-QRVNI5V6.js → chunk-SCNEQFIW.js} +3 -3
- package/dist/{chunk-BNUPYHHZ.js → chunk-SD4PPZFB.js} +4 -4
- package/dist/{chunk-ROQOVH4N.js → chunk-SFAU5R5S.js} +3 -3
- package/dist/{chunk-R63QEVPK.js → chunk-SJORXXLV.js} +6 -6
- package/dist/{chunk-FBE6AIIW.js → chunk-SOKNCW5U.js} +2 -2
- package/dist/{chunk-JRXHSVD5.js → chunk-SOXZ4LGS.js} +68 -11
- package/dist/chunk-SOXZ4LGS.js.map +1 -0
- package/dist/{chunk-EF5SYXAY.js → chunk-SQDPHCK2.js} +22 -14
- package/dist/chunk-SQDPHCK2.js.map +1 -0
- package/dist/{chunk-NDF3SH3X.js → chunk-TDIOBPLA.js} +5 -5
- package/dist/{chunk-EHCUFCXM.js → chunk-TEPPPAJI.js} +17 -7
- package/dist/chunk-TEPPPAJI.js.map +1 -0
- package/dist/{chunk-33TPANCR.js → chunk-TFK4KFKA.js} +4 -4
- package/dist/{chunk-6NIB2KGJ.js → chunk-THVIT3PW.js} +22 -22
- package/dist/{chunk-HPPKLBTJ.js → chunk-TJQDL3JH.js} +2 -2
- package/dist/{chunk-FD4Q5KFL.js → chunk-TLL22FFO.js} +2 -2
- package/dist/{chunk-7DU35P5J.js → chunk-TN5T5HRZ.js} +7 -7
- package/dist/{chunk-JK7C5A4I.js → chunk-TR4HIKJ2.js} +8 -8
- package/dist/{chunk-HNYJEAES.js → chunk-UGEWCWVV.js} +3 -3
- package/dist/chunk-ULYQEFNH.js +529 -0
- package/dist/chunk-ULYQEFNH.js.map +1 -0
- package/dist/{chunk-H5EVWF6L.js → chunk-UNNJUJVD.js} +2 -2
- package/dist/{chunk-AD22P5X3.js → chunk-UUSAOIJR.js} +3 -3
- package/dist/{chunk-Z6DKXQG7.js → chunk-UXXFMF4X.js} +2 -2
- package/dist/{chunk-RGPYMHKI.js → chunk-V3K4RQO7.js} +9 -3
- package/dist/chunk-V3K4RQO7.js.map +1 -0
- package/dist/{chunk-UP4BE32Y.js → chunk-VO6RVVP7.js} +5 -5
- package/dist/{chunk-S4SC5SSV.js → chunk-VPNXQUUS.js} +11 -11
- package/dist/{chunk-7BST7BA6.js → chunk-VW3BBTMA.js} +1 -1
- package/dist/{chunk-CBY5CXBD.js → chunk-VWSFA4LJ.js} +2 -2
- package/dist/{chunk-MYNUBDU7.js → chunk-VYKW6TB2.js} +1 -1
- package/dist/chunk-VYKW6TB2.js.map +1 -0
- package/dist/{chunk-QEJTQTF5.js → chunk-W6T5HR3Z.js} +3 -3
- package/dist/{chunk-5JEIDFPD.js → chunk-WBPQ7OPC.js} +1 -1
- package/dist/{chunk-GZLLDA6P.js → chunk-WEFN327U.js} +2 -2
- package/dist/{chunk-ANHUMDJX.js → chunk-WNDTLK44.js} +2 -2
- package/dist/{chunk-DLOYMWUQ.js → chunk-WSLPZ43N.js} +7 -7
- package/dist/{chunk-2DS4UOYQ.js → chunk-WSZQNTVN.js} +2 -2
- package/dist/{chunk-LE2EDBXU.js → chunk-WUHB422G.js} +5 -5
- package/dist/{chunk-BJW7G6EF.js → chunk-WVX5AQXS.js} +3 -3
- package/dist/{chunk-5POTDNQT.js → chunk-WWOHORRO.js} +3 -3
- package/dist/{chunk-4W7VISE7.js → chunk-WYDZP5F2.js} +93 -94
- package/dist/chunk-WYDZP5F2.js.map +1 -0
- package/dist/{chunk-KZHW27BV.js → chunk-WYEPUXGL.js} +2 -2
- package/dist/{chunk-GALB2G3W.js → chunk-X2AH4DRF.js} +2 -2
- package/dist/{chunk-NCX5SAQY.js → chunk-XN6CALYY.js} +9 -9
- package/dist/{chunk-SUVEDKE2.js → chunk-XNACICAB.js} +3 -3
- package/dist/{chunk-FDNJVZRE.js → chunk-XU4I47IP.js} +4 -4
- package/dist/chunk-XV6ZYRHK.js +59 -0
- package/dist/chunk-XV6ZYRHK.js.map +1 -0
- package/dist/{chunk-WRLWLGEF.js → chunk-Y5E3XQ2S.js} +25 -2
- package/dist/{chunk-WRLWLGEF.js.map → chunk-Y5E3XQ2S.js.map} +1 -1
- package/dist/{chunk-U36PO27Q.js → chunk-YG3IJCM2.js} +3 -3
- package/dist/{chunk-UWJ5P5CU.js → chunk-YGSJWWT3.js} +3 -3
- package/dist/{chunk-APU42QDI.js → chunk-YO64YVYL.js} +105 -101
- package/dist/chunk-YO64YVYL.js.map +1 -0
- package/dist/{chunk-P5WABK2H.js → chunk-Z4GJB24B.js} +2 -2
- package/dist/{chunk-NLMTNEWW.js → chunk-Z6E6TUAE.js} +2 -2
- package/dist/{chunk-OBQVTCTW.js → chunk-ZX5H7LWD.js} +2 -2
- package/dist/components/browser-viewer.d.ts +1 -1
- package/dist/composer.js +8 -8
- package/dist/{computer-viewer-KEDVLD42.js → computer-viewer-VA5JONUH.js} +6 -6
- package/dist/connect.js +7 -7
- package/dist/desktop.js +2 -2
- package/dist/editor.js +2 -2
- package/dist/{embedded-new-voice-LFHWWYD2.js → embedded-new-voice-6BILAOUG.js} +6 -6
- package/dist/{embedded-voice-6QS4ANNX.js → embedded-voice-UDE4JRKB.js} +6 -6
- package/dist/{fleet-decision-row-QNSTP3VX.js → fleet-decision-row-NN2HXDX3.js} +2 -2
- package/dist/hooks/internal.d.ts +38 -0
- package/dist/hooks/use-client-config-flags.d.ts +12 -0
- package/dist/hooks/use-workspace-sessions.d.ts +10 -1
- package/dist/index.js +86 -80
- package/dist/interaction.js +8 -6
- package/dist/interaction.js.map +1 -1
- package/dist/{latest-question-AW3PPDUM.js → latest-question-4WDBECXB.js} +4 -3
- package/dist/{latest-question-AW3PPDUM.js.map → latest-question-4WDBECXB.js.map} +1 -1
- package/dist/machines.js +4 -4
- package/dist/messages/en.d.ts +3 -3
- package/dist/messages.js +1 -1
- package/dist/{model-policy-picker-menu-CURJ247L.js → model-policy-picker-menu-NRTO6FRP.js} +4 -4
- package/dist/{platform-activity-row-BMXXNZKX.js → platform-activity-row-ENQVIFTL.js} +2 -2
- package/dist/{queue-surface-implementation-2X5AXB6I.js → queue-surface-implementation-H4XSNHZE.js} +8 -6
- package/dist/{queue-surface-implementation-2X5AXB6I.js.map → queue-surface-implementation-H4XSNHZE.js.map} +1 -1
- package/dist/realtime.js +5 -5
- package/dist/{sandbox-files-4FBG3GS2.js → sandbox-files-IEHODU35.js} +9 -9
- package/dist/sandbox-files-IEHODU35.js.map +1 -0
- package/dist/session-app.js +198 -192
- package/dist/session-list-model.d.ts +1 -0
- package/dist/session-list-model.js +7 -1
- package/dist/{session-realtime-2XIB254N.js → session-realtime-JNKDSGH7.js} +3 -3
- package/dist/session-realtime-JNKDSGH7.js.map +1 -0
- package/dist/session-realtime.js +2 -2
- package/dist/session-ui.js +48 -43
- package/dist/session.js +20 -18
- package/dist/sites.js +2 -2
- package/dist/terminal.js +2 -2
- package/dist/this-computer.js +3 -3
- package/dist/timeline/invoked-tool.d.ts +5 -0
- package/dist/timeline/tool-display-name.d.ts +2 -2
- package/dist/timeline/tool-icon.d.ts +14 -0
- package/dist/timeline/tool-presentation.d.ts +8 -3
- package/dist/{timeline-annotation-markers-X4K2IEOO.js → timeline-annotation-markers-ZSOFW7PG.js} +2 -2
- package/dist/{timeline-annotation-selection-MEHBW676.js → timeline-annotation-selection-YWV2UC34.js} +2 -2
- package/dist/{timeline-annotations-dialog-U2FPQ3UY.js → timeline-annotations-dialog-ZWQVX2HI.js} +3 -3
- package/dist/timeline-model.js +16 -14
- package/dist/ui/access-list.js +7 -7
- package/dist/ui/cadence-picker.js +2 -2
- package/dist/ui/list-row.js +3 -3
- package/dist/ui/revision-history.js +2 -2
- package/dist/ui/role-select.js +3 -3
- package/dist/ui/select-menu.js +2 -2
- package/dist/usage.js +3 -3
- package/dist/workbench.js +4 -4
- package/package.json +4 -4
- package/src/app/app-state.tsx +3 -1
- package/src/app/components/capabilities/session-machine-card.tsx +9 -2
- package/src/app/components/rail/session-list.tsx +254 -44
- package/src/app/components/rail/session-row-content.tsx +24 -2
- package/src/app/components/rail/session-shell.tsx +14 -9
- package/src/app/components/rail/site-session-group-heading.tsx +59 -20
- package/src/app/components/session/session-tenancy-control.tsx +18 -0
- package/src/app/components/session/site-origin-link.test.tsx +73 -0
- package/src/app/components/session/site-origin-link.tsx +4 -2
- package/src/app/embed/memory-navigation.tsx +1 -0
- package/src/app/lib/actions/held-modifier.test.ts +101 -0
- package/src/app/lib/actions/held-modifier.ts +108 -0
- package/src/app/lib/console-site.tsx +38 -0
- package/src/app/lib/navigation.tsx +4 -0
- package/src/app/lib/routes.tsx +42 -0
- package/src/app/lib/session-failure-toasts.ts +26 -0
- package/src/app/lib/session-ui-features.tsx +18 -4
- package/src/app/lib/sessions-group.tsx +219 -30
- package/src/app/lib/site-opened.tsx +48 -0
- package/src/app/lib/site-session-groups.test.ts +173 -6
- package/src/app/lib/site-view-routes.test.ts +55 -0
- package/src/app/lib/use-session-list-hint-refresh.tsx +44 -4
- package/src/app/routes/artifacts.tsx +2 -29
- package/src/app/routes/session-transient-failures.test.tsx +343 -0
- package/src/app/routes/session-unavailable.tsx +74 -3
- package/src/app/routes/session.tsx +4 -13
- package/src/app/routes/sessions-index.tsx +13 -9
- package/src/app/routes/site-view.test.tsx +476 -0
- package/src/app/routes/site-view.tsx +583 -0
- package/src/components/browser-viewer.tsx +16 -2
- package/src/hooks/internal.ts +129 -6
- package/src/hooks/use-client-config-flags.ts +8 -0
- package/src/hooks/use-session-events.ts +83 -9
- package/src/hooks/use-workspace-sessions.ts +21 -1
- package/src/messages/en.ts +3 -3
- package/src/session-list-model.ts +4 -0
- package/src/timeline/activity-rail.tsx +3 -2
- package/src/timeline/invoked-tool.ts +14 -4
- package/src/timeline/projection.ts +11 -6
- package/src/timeline/rolling-activity.tsx +6 -2
- package/src/timeline/tool-display-name.ts +2 -2
- package/src/timeline/tool-icon.tsx +165 -0
- package/src/timeline/tool-presentation.ts +207 -48
- package/src/timeline/tool-renderers.tsx +1 -70
- package/styles/compiled.css +38 -0
- package/dist/chunk-22ZBT6CN.js +0 -50
- package/dist/chunk-22ZBT6CN.js.map +0 -1
- package/dist/chunk-4R3JCVID.js.map +0 -1
- package/dist/chunk-4W7VISE7.js.map +0 -1
- package/dist/chunk-5JZYPZ72.js.map +0 -1
- package/dist/chunk-5MZTJMZ3.js.map +0 -1
- package/dist/chunk-6W3LF3DB.js.map +0 -1
- package/dist/chunk-ADJJQSYC.js.map +0 -1
- package/dist/chunk-APU42QDI.js.map +0 -1
- package/dist/chunk-BJIZ7PL7.js.map +0 -1
- package/dist/chunk-CVG4FILQ.js.map +0 -1
- package/dist/chunk-EF5SYXAY.js.map +0 -1
- package/dist/chunk-EHCUFCXM.js.map +0 -1
- package/dist/chunk-GZ64CASI.js.map +0 -1
- package/dist/chunk-JRXHSVD5.js.map +0 -1
- package/dist/chunk-KF3MF6FP.js.map +0 -1
- package/dist/chunk-MYNUBDU7.js.map +0 -1
- package/dist/chunk-NAWXARTY.js.map +0 -1
- package/dist/chunk-PM3OSANE.js.map +0 -1
- package/dist/chunk-Q35DT6I6.js.map +0 -1
- package/dist/chunk-R25ZKOZR.js +0 -24
- package/dist/chunk-R25ZKOZR.js.map +0 -1
- package/dist/chunk-RGPYMHKI.js.map +0 -1
- package/dist/chunk-RGW24ZZM.js.map +0 -1
- package/dist/chunk-TQGJN5UZ.js.map +0 -1
- package/dist/chunk-X7L4H4VG.js.map +0 -1
- package/dist/chunk-XFNLU7EW.js.map +0 -1
- package/dist/chunk-Z5WMLJKI.js.map +0 -1
- /package/dist/{browser-viewer-RYYQSRTC.js.map → app/lib/console-site.js.map} +0 -0
- /package/dist/{chat-interactive-block-ABCRKXJ4.js.map → app/lib/site-opened.js.map} +0 -0
- /package/dist/{computer-viewer-KEDVLD42.js.map → browser-viewer-VPK3CV2H.js.map} +0 -0
- /package/dist/{embedded-new-voice-LFHWWYD2.js.map → chat-interactive-block-AMDSW656.js.map} +0 -0
- /package/dist/{chunk-RQDFYQHA.js.map → chunk-25LWDG5D.js.map} +0 -0
- /package/dist/{chunk-U3HSFCON.js.map → chunk-2CKVVAGP.js.map} +0 -0
- /package/dist/{chunk-F6LBGYS6.js.map → chunk-2DL6NJP5.js.map} +0 -0
- /package/dist/{chunk-UHFWF6ZU.js.map → chunk-2FPS5H2D.js.map} +0 -0
- /package/dist/{chunk-TWXIFWBD.js.map → chunk-34EU25RL.js.map} +0 -0
- /package/dist/{chunk-PTGRFAMH.js.map → chunk-3ABPIUCK.js.map} +0 -0
- /package/dist/{chunk-722UO6YQ.js.map → chunk-3PEXVG4D.js.map} +0 -0
- /package/dist/{chunk-N3ZP4IDU.js.map → chunk-45WYYFP6.js.map} +0 -0
- /package/dist/{chunk-HOJGAJAB.js.map → chunk-4MQLGMV2.js.map} +0 -0
- /package/dist/{chunk-L7YURQI2.js.map → chunk-4U4GXWXS.js.map} +0 -0
- /package/dist/{chunk-63VGE4OH.js.map → chunk-5HIOVXOX.js.map} +0 -0
- /package/dist/{chunk-GFUUFM2O.js.map → chunk-5M23GZA2.js.map} +0 -0
- /package/dist/{chunk-RKB2Z457.js.map → chunk-5VGJXWQ2.js.map} +0 -0
- /package/dist/{chunk-I6VUUEXH.js.map → chunk-6AFSZKZA.js.map} +0 -0
- /package/dist/{chunk-FBMU3VK5.js.map → chunk-6DCEDIF6.js.map} +0 -0
- /package/dist/{chunk-4EONHNJU.js.map → chunk-6O4VWKSO.js.map} +0 -0
- /package/dist/{chunk-BSX2R4CW.js.map → chunk-767WCGAX.js.map} +0 -0
- /package/dist/{chunk-7KGKDWWR.js.map → chunk-7HFLYNWN.js.map} +0 -0
- /package/dist/{chunk-OSVHU2WU.js.map → chunk-7IYAHFPE.js.map} +0 -0
- /package/dist/{chunk-4EAF3HSD.js.map → chunk-7J7PZB4S.js.map} +0 -0
- /package/dist/{chunk-OR37STQZ.js.map → chunk-7R2JQHBX.js.map} +0 -0
- /package/dist/{chunk-QM5H4FPT.js.map → chunk-7VN6VC3D.js.map} +0 -0
- /package/dist/{chunk-HWDGJFM4.js.map → chunk-A2E3ZF6N.js.map} +0 -0
- /package/dist/{chunk-4432A3HQ.js.map → chunk-A6T4FGE7.js.map} +0 -0
- /package/dist/{chunk-73SOCVLS.js.map → chunk-AIEXYO2X.js.map} +0 -0
- /package/dist/{chunk-U7TC2XJQ.js.map → chunk-AJPW3SV4.js.map} +0 -0
- /package/dist/{chunk-46VBQG2D.js.map → chunk-AOUCHCSB.js.map} +0 -0
- /package/dist/{chunk-HDHK3SXK.js.map → chunk-AT4K4F6S.js.map} +0 -0
- /package/dist/{chunk-HRJQAFKR.js.map → chunk-AX6YJA5U.js.map} +0 -0
- /package/dist/{chunk-HO5Y2OOX.js.map → chunk-BLPXOHG6.js.map} +0 -0
- /package/dist/{chunk-DT7BORXG.js.map → chunk-BMJTNPWK.js.map} +0 -0
- /package/dist/{chunk-HIHO2QE7.js.map → chunk-BT2MVGHT.js.map} +0 -0
- /package/dist/{chunk-AOLE4IRZ.js.map → chunk-C535KSTY.js.map} +0 -0
- /package/dist/{chunk-IVOA3DXA.js.map → chunk-CB574ERL.js.map} +0 -0
- /package/dist/{chunk-IBTXYLBW.js.map → chunk-CCFWY4GF.js.map} +0 -0
- /package/dist/{chunk-ZOC3OP6F.js.map → chunk-CCR33J7L.js.map} +0 -0
- /package/dist/{chunk-NYZQ7LO7.js.map → chunk-CDUDKETD.js.map} +0 -0
- /package/dist/{chunk-JTN3T4QN.js.map → chunk-D3RK3NGM.js.map} +0 -0
- /package/dist/{chunk-IOKSNX74.js.map → chunk-D5OWJZQR.js.map} +0 -0
- /package/dist/{chunk-XWWXIZFP.js.map → chunk-DFXZYNTX.js.map} +0 -0
- /package/dist/{chunk-SQGXMHJO.js.map → chunk-DGLRZMXL.js.map} +0 -0
- /package/dist/{chunk-GNEHAPKV.js.map → chunk-DJFTH2DI.js.map} +0 -0
- /package/dist/{chunk-KWKGBGAF.js.map → chunk-DKCX643S.js.map} +0 -0
- /package/dist/{chunk-HQG4SLTE.js.map → chunk-DYJGYGPB.js.map} +0 -0
- /package/dist/{chunk-GTQ3SNEI.js.map → chunk-E36IC3LU.js.map} +0 -0
- /package/dist/{chunk-72J6C2AJ.js.map → chunk-EMCB6XKU.js.map} +0 -0
- /package/dist/{chunk-3AA6RNGE.js.map → chunk-ENS6E4RZ.js.map} +0 -0
- /package/dist/{chunk-AG7VGUIW.js.map → chunk-ERG355NM.js.map} +0 -0
- /package/dist/{chunk-TSBE4KOQ.js.map → chunk-EWL6NDOO.js.map} +0 -0
- /package/dist/{chunk-HTT3FB7T.js.map → chunk-F3FN6DO6.js.map} +0 -0
- /package/dist/{chunk-ST22GONV.js.map → chunk-FB3B45FP.js.map} +0 -0
- /package/dist/{chunk-P5T36BA3.js.map → chunk-FRP64DEK.js.map} +0 -0
- /package/dist/{chunk-KBF3SE7G.js.map → chunk-FSP334UU.js.map} +0 -0
- /package/dist/{chunk-4VKA5O7T.js.map → chunk-FVL4B552.js.map} +0 -0
- /package/dist/{chunk-VP62LPLW.js.map → chunk-G2BX56CN.js.map} +0 -0
- /package/dist/{chunk-CSHBR2IZ.js.map → chunk-GDLDBR6B.js.map} +0 -0
- /package/dist/{chunk-PN66T6JA.js.map → chunk-GFSOXB2K.js.map} +0 -0
- /package/dist/{chunk-S4EZ3JUB.js.map → chunk-GZGQHQI7.js.map} +0 -0
- /package/dist/{chunk-BXRIQZAH.js.map → chunk-HNNM2GDN.js.map} +0 -0
- /package/dist/{chunk-EU6XSQFM.js.map → chunk-HPB4KSV3.js.map} +0 -0
- /package/dist/{chunk-QCD5Y7K5.js.map → chunk-HSQRYJ4P.js.map} +0 -0
- /package/dist/{chunk-YXOKAG66.js.map → chunk-HUXDGWAN.js.map} +0 -0
- /package/dist/{chunk-VUHPA3XQ.js.map → chunk-I66ZB6KD.js.map} +0 -0
- /package/dist/{chunk-7CZTKBTI.js.map → chunk-IC7KNOBB.js.map} +0 -0
- /package/dist/{chunk-HGMWMK5K.js.map → chunk-IIO2MR3B.js.map} +0 -0
- /package/dist/{chunk-L6RXRRN3.js.map → chunk-ILDOW2IQ.js.map} +0 -0
- /package/dist/{chunk-O756O2I7.js.map → chunk-IPPVX5GF.js.map} +0 -0
- /package/dist/{chunk-X7ASQHR6.js.map → chunk-IUK5QGP5.js.map} +0 -0
- /package/dist/{chunk-PIVGX42P.js.map → chunk-JNY5MT3I.js.map} +0 -0
- /package/dist/{chunk-DDK4WFJ3.js.map → chunk-JWN7SLTO.js.map} +0 -0
- /package/dist/{chunk-Q35YZVDZ.js.map → chunk-KFWVBTUH.js.map} +0 -0
- /package/dist/{chunk-JXT5QDJC.js.map → chunk-KNFDWNCH.js.map} +0 -0
- /package/dist/{chunk-AZVANYMB.js.map → chunk-KUNFUSZ7.js.map} +0 -0
- /package/dist/{chunk-DXZNDKQD.js.map → chunk-LEEJBZ5B.js.map} +0 -0
- /package/dist/{chunk-RSNYGEVZ.js.map → chunk-LKJ2C7PH.js.map} +0 -0
- /package/dist/{chunk-RIMKJBCD.js.map → chunk-LMPTC4CX.js.map} +0 -0
- /package/dist/{chunk-3KVWXKD6.js.map → chunk-LQ47YL6E.js.map} +0 -0
- /package/dist/{chunk-GAIM5RNE.js.map → chunk-MJQBC7C5.js.map} +0 -0
- /package/dist/{chunk-NWZW2WHN.js.map → chunk-MM7OKOTE.js.map} +0 -0
- /package/dist/{chunk-FM4OUCC2.js.map → chunk-MOKYT3X3.js.map} +0 -0
- /package/dist/{chunk-XRRSFQEV.js.map → chunk-NAZZLAWX.js.map} +0 -0
- /package/dist/{chunk-XOFUXMPP.js.map → chunk-ND2WCWXI.js.map} +0 -0
- /package/dist/{chunk-6L7U46Y2.js.map → chunk-NKNVIO66.js.map} +0 -0
- /package/dist/{chunk-JKUICTLM.js.map → chunk-NLAFNMPK.js.map} +0 -0
- /package/dist/{chunk-OO2T63BY.js.map → chunk-NML44AW2.js.map} +0 -0
- /package/dist/{chunk-4LKNIGHB.js.map → chunk-O2SBHS2N.js.map} +0 -0
- /package/dist/{chunk-RA3FNMWF.js.map → chunk-O4DYOSOL.js.map} +0 -0
- /package/dist/{chunk-ZKYYZH6L.js.map → chunk-OFB6TUDC.js.map} +0 -0
- /package/dist/{chunk-DWPOQ3S5.js.map → chunk-OTMWHZBY.js.map} +0 -0
- /package/dist/{chunk-VVCDB2T7.js.map → chunk-PCJLH45G.js.map} +0 -0
- /package/dist/{chunk-WSMYOLHG.js.map → chunk-PEKPWK5M.js.map} +0 -0
- /package/dist/{chunk-PZ24CYDO.js.map → chunk-PFAUGEV5.js.map} +0 -0
- /package/dist/{chunk-KTRKZRID.js.map → chunk-PKEKZ2VA.js.map} +0 -0
- /package/dist/{chunk-6JKZILLF.js.map → chunk-PMD7V4N7.js.map} +0 -0
- /package/dist/{chunk-B74GSYR6.js.map → chunk-PUTS4DYW.js.map} +0 -0
- /package/dist/{chunk-ZRJCGBVV.js.map → chunk-PVR5EELP.js.map} +0 -0
- /package/dist/{chunk-JSIDLTTG.js.map → chunk-PZ2V2XIK.js.map} +0 -0
- /package/dist/{chunk-TMEQPODK.js.map → chunk-PZ37VDB5.js.map} +0 -0
- /package/dist/{chunk-FLGUVRR7.js.map → chunk-QBADR2FO.js.map} +0 -0
- /package/dist/{chunk-TGVVEGZG.js.map → chunk-QLIDZGPV.js.map} +0 -0
- /package/dist/{chunk-LVONK3YQ.js.map → chunk-QRKTESVE.js.map} +0 -0
- /package/dist/{chunk-HT5WSUC7.js.map → chunk-QXEDIDBZ.js.map} +0 -0
- /package/dist/{chunk-WURSS6MP.js.map → chunk-R66YMYJU.js.map} +0 -0
- /package/dist/{chunk-6PQNLL4E.js.map → chunk-R7XCJWCD.js.map} +0 -0
- /package/dist/{chunk-QRVNI5V6.js.map → chunk-SCNEQFIW.js.map} +0 -0
- /package/dist/{chunk-BNUPYHHZ.js.map → chunk-SD4PPZFB.js.map} +0 -0
- /package/dist/{chunk-ROQOVH4N.js.map → chunk-SFAU5R5S.js.map} +0 -0
- /package/dist/{chunk-R63QEVPK.js.map → chunk-SJORXXLV.js.map} +0 -0
- /package/dist/{chunk-FBE6AIIW.js.map → chunk-SOKNCW5U.js.map} +0 -0
- /package/dist/{chunk-NDF3SH3X.js.map → chunk-TDIOBPLA.js.map} +0 -0
- /package/dist/{chunk-33TPANCR.js.map → chunk-TFK4KFKA.js.map} +0 -0
- /package/dist/{chunk-6NIB2KGJ.js.map → chunk-THVIT3PW.js.map} +0 -0
- /package/dist/{chunk-HPPKLBTJ.js.map → chunk-TJQDL3JH.js.map} +0 -0
- /package/dist/{chunk-FD4Q5KFL.js.map → chunk-TLL22FFO.js.map} +0 -0
- /package/dist/{chunk-7DU35P5J.js.map → chunk-TN5T5HRZ.js.map} +0 -0
- /package/dist/{chunk-JK7C5A4I.js.map → chunk-TR4HIKJ2.js.map} +0 -0
- /package/dist/{chunk-HNYJEAES.js.map → chunk-UGEWCWVV.js.map} +0 -0
- /package/dist/{chunk-H5EVWF6L.js.map → chunk-UNNJUJVD.js.map} +0 -0
- /package/dist/{chunk-AD22P5X3.js.map → chunk-UUSAOIJR.js.map} +0 -0
- /package/dist/{chunk-Z6DKXQG7.js.map → chunk-UXXFMF4X.js.map} +0 -0
- /package/dist/{chunk-UP4BE32Y.js.map → chunk-VO6RVVP7.js.map} +0 -0
- /package/dist/{chunk-S4SC5SSV.js.map → chunk-VPNXQUUS.js.map} +0 -0
- /package/dist/{chunk-7BST7BA6.js.map → chunk-VW3BBTMA.js.map} +0 -0
- /package/dist/{chunk-CBY5CXBD.js.map → chunk-VWSFA4LJ.js.map} +0 -0
- /package/dist/{chunk-QEJTQTF5.js.map → chunk-W6T5HR3Z.js.map} +0 -0
- /package/dist/{chunk-5JEIDFPD.js.map → chunk-WBPQ7OPC.js.map} +0 -0
- /package/dist/{chunk-GZLLDA6P.js.map → chunk-WEFN327U.js.map} +0 -0
- /package/dist/{chunk-ANHUMDJX.js.map → chunk-WNDTLK44.js.map} +0 -0
- /package/dist/{chunk-DLOYMWUQ.js.map → chunk-WSLPZ43N.js.map} +0 -0
- /package/dist/{chunk-2DS4UOYQ.js.map → chunk-WSZQNTVN.js.map} +0 -0
- /package/dist/{chunk-LE2EDBXU.js.map → chunk-WUHB422G.js.map} +0 -0
- /package/dist/{chunk-BJW7G6EF.js.map → chunk-WVX5AQXS.js.map} +0 -0
- /package/dist/{chunk-5POTDNQT.js.map → chunk-WWOHORRO.js.map} +0 -0
- /package/dist/{chunk-KZHW27BV.js.map → chunk-WYEPUXGL.js.map} +0 -0
- /package/dist/{chunk-GALB2G3W.js.map → chunk-X2AH4DRF.js.map} +0 -0
- /package/dist/{chunk-NCX5SAQY.js.map → chunk-XN6CALYY.js.map} +0 -0
- /package/dist/{chunk-SUVEDKE2.js.map → chunk-XNACICAB.js.map} +0 -0
- /package/dist/{chunk-FDNJVZRE.js.map → chunk-XU4I47IP.js.map} +0 -0
- /package/dist/{chunk-U36PO27Q.js.map → chunk-YG3IJCM2.js.map} +0 -0
- /package/dist/{chunk-UWJ5P5CU.js.map → chunk-YGSJWWT3.js.map} +0 -0
- /package/dist/{chunk-P5WABK2H.js.map → chunk-Z4GJB24B.js.map} +0 -0
- /package/dist/{chunk-NLMTNEWW.js.map → chunk-Z6E6TUAE.js.map} +0 -0
- /package/dist/{chunk-OBQVTCTW.js.map → chunk-ZX5H7LWD.js.map} +0 -0
- /package/dist/{embedded-voice-6QS4ANNX.js.map → computer-viewer-VA5JONUH.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-CURJ247L.js.map → embedded-new-voice-6BILAOUG.js.map} +0 -0
- /package/dist/{sandbox-files-4FBG3GS2.js.map → embedded-voice-UDE4JRKB.js.map} +0 -0
- /package/dist/{fleet-decision-row-QNSTP3VX.js.map → fleet-decision-row-NN2HXDX3.js.map} +0 -0
- /package/dist/{session-realtime-2XIB254N.js.map → model-policy-picker-menu-NRTO6FRP.js.map} +0 -0
- /package/dist/{platform-activity-row-BMXXNZKX.js.map → platform-activity-row-ENQVIFTL.js.map} +0 -0
- /package/dist/{timeline-annotation-markers-X4K2IEOO.js.map → timeline-annotation-markers-ZSOFW7PG.js.map} +0 -0
- /package/dist/{timeline-annotation-selection-MEHBW676.js.map → timeline-annotation-selection-YWV2UC34.js.map} +0 -0
- /package/dist/{timeline-annotations-dialog-U2FPQ3UY.js.map → timeline-annotations-dialog-ZWQVX2HI.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app/components/command-menu/chat-switcher.tsx"],"sourcesContent":["/**\n * The Control+Tab chat switcher's list: recently viewed chats in the middle of\n * the window while Control is held. The actions provider owns the keys and\n * the selection; this only draws it. Focus never moves here, so releasing\n * Control (and the chat being switched to) behaves exactly as without it.\n */\nimport { MessageSquareIcon, PinIcon, type LucideIcon } from \"lucide-react\";\nimport { useEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { ChatRecord } from \"../../lib/actions/chat-directory\";\nimport { readChatDirectory, useChatDirectoryVersion } from \"../../lib/actions/chat-directory\";\nimport type { ChatSwitcherState } from \"../../lib/actions/chat-switcher\";\nimport type { ChordPlatform } from \"../../lib/actions/chords\";\nimport type { WorkspaceChoice } from \"../../lib/actions/registry\";\nimport { cn } from \"../../lib/utils\";\nimport { formatRelativeTime } from \"../../../ui/relative-time\";\nimport { currentChatStatus } from \"../../lib/actions/chat-status\";\nimport { ChatStatusMarks, useChatStatusRefresh } from \"./chat-status\";\nimport { Keycaps } from \"./keycaps\";\nimport { WorkspaceTag } from \"./workspace-tag\";\n\nfunction chatIcon(record: ChatRecord | undefined): LucideIcon {\n return record?.pinned ? PinIcon : MessageSquareIcon;\n}\n\nexport default function ChatSwitcher(props: {\n state: ChatSwitcherState;\n subjectId: string;\n workspaceId: string;\n workspaces: readonly WorkspaceChoice[];\n currentChatId: string | null;\n platform: ChordPlatform;\n onHover(index: number): void;\n onPick(index: number): void;\n onDismiss(): void;\n}) {\n const listRef = useRef<HTMLDivElement>(null);\n const { index, visible } = props.state;\n // Read statuses as soon as Control+Tab is pressed, before the list shows.\n useChatStatusRefresh({\n subjectId: props.subjectId,\n workspaceId: props.workspaceId,\n ids: props.state.ids,\n active: true,\n });\n useChatDirectoryVersion(props.subjectId);\n useEffect(() => {\n if (!visible) return;\n listRef.current\n ?.querySelector<HTMLElement>(`[data-switcher-index=\"${index}\"]`)\n ?.scrollIntoView({ block: \"nearest\" });\n }, [index, visible]);\n if (!visible || typeof document === \"undefined\") return null;\n const directory = readChatDirectory(props.subjectId, props.workspaceId);\n const now = Date.now();\n const sidebarIds = new Set([...directory.sidebarOrder, ...directory.pinnedOrder]);\n const workspaceNames = new Map(\n props.workspaces.map((workspace) => [workspace.id, workspace.name]),\n );\n const activeId = `og-chat-switcher-${index}`;\n return createPortal(\n <div\n data-og-chat-switcher=\"\"\n // A light dim, as under ⌘K, lifts the list off the chat behind it.\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/15 p-4 animate-in fade-in-0 duration-[100ms] dark:bg-black/40\"\n // A click outside the list puts it away without switching.\n onPointerDown={(event) => {\n if (event.target === event.currentTarget) props.onDismiss();\n }}\n >\n <div\n className={cn(\n \"flex max-h-[min(480px,70dvh)] w-full max-w-[440px] flex-col overflow-hidden\",\n \"rounded-2xl border border-border bg-surface text-fg shadow-og-lg\",\n \"animate-in fade-in-0 zoom-in-98 duration-[100ms]\",\n )}\n >\n <div className=\"px-4 pt-3 pb-1 text-xs leading-4.5 font-medium text-fg-muted\">\n Recent chats\n </div>\n <div\n ref={listRef}\n role=\"listbox\"\n aria-label=\"Recent chats\"\n aria-activedescendant={activeId}\n className=\"min-h-0 flex-1 overflow-y-auto px-1.5 pb-1.5\"\n >\n {props.state.ids.map((id, position) => {\n const record = directory.rows.get(id);\n const Icon = chatIcon(record);\n const selected = position === index;\n const meta =\n id === props.currentChatId\n ? \"Open now\"\n : record?.updatedAt\n ? formatRelativeTime(record.updatedAt, { now })\n : undefined;\n // Chats in other workspaces say where they are.\n const elsewhere =\n record && record.workspaceId !== props.workspaceId\n ? (workspaceNames.get(record.workspaceId) ?? null)\n : null;\n return (\n <div\n key={id}\n id={`og-chat-switcher-${position}`}\n data-switcher-index={position}\n role=\"option\"\n aria-selected={selected}\n onPointerMove={() => {\n if (!selected) props.onHover(position);\n }}\n // Control+click is a right-click on a Mac: pick on release, and\n // keep the context menu away.\n onPointerUp={(event) => {\n if (event.button === 0) props.onPick(position);\n }}\n onContextMenu={(event) => event.preventDefault()}\n className={cn(\n \"flex min-h-9 w-full min-w-0 cursor-default items-center gap-2.5 rounded-[10px] px-2.5 py-1.5 text-sm text-fg-label select-none\",\n selected ? \"bg-hover text-fg\" : null,\n )}\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\"size-4 shrink-0\", selected ? \"text-fg\" : \"text-fg-muted\")}\n />\n <span className=\"min-w-0 flex-1 truncate\">{record?.title ?? \"Untitled chat\"}</span>\n {elsewhere ? <WorkspaceTag name={elsewhere} /> : null}\n <ChatStatusMarks\n status={record ? currentChatStatus(record, sidebarIds, now) : null}\n />\n {meta ? (\n <span className=\"shrink-0 text-xs text-fg-muted tabular-nums\">{meta}</span>\n ) : null}\n </div>\n );\n })}\n </div>\n <div className=\"flex shrink-0 items-center gap-4 border-t border-border px-4 py-2 text-xs text-fg-muted\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Keycaps\n chord={{ code: \"Tab\", control: true, mod: props.platform !== \"mac\" }}\n platform={props.platform}\n />\n Next\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Keycaps\n chord={{ code: \"Tab\", control: true, mod: props.platform !== \"mac\", shift: true }}\n platform={props.platform}\n />\n Back\n </span>\n <span className=\"ml-auto\">Release to open</span>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/components/command-menu/chat-switcher.tsx"],"sourcesContent":["/**\n * The Control+Tab chat switcher's list: recently viewed chats in the middle of\n * the window while Control is held. The actions provider owns the keys and\n * the selection; this only draws it. Focus never moves here, so releasing\n * Control (and the chat being switched to) behaves exactly as without it.\n */\nimport { MessageSquareIcon, PinIcon, type LucideIcon } from \"lucide-react\";\nimport { useEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { ChatRecord } from \"../../lib/actions/chat-directory\";\nimport { readChatDirectory, useChatDirectoryVersion } from \"../../lib/actions/chat-directory\";\nimport type { ChatSwitcherState } from \"../../lib/actions/chat-switcher\";\nimport type { ChordPlatform } from \"../../lib/actions/chords\";\nimport type { WorkspaceChoice } from \"../../lib/actions/registry\";\nimport { cn } from \"../../lib/utils\";\nimport { formatRelativeTime } from \"../../../ui/relative-time\";\nimport { currentChatStatus } from \"../../lib/actions/chat-status\";\nimport { ChatStatusMarks, useChatStatusRefresh } from \"./chat-status\";\nimport { Keycaps } from \"./keycaps\";\nimport { WorkspaceTag } from \"./workspace-tag\";\n\nfunction chatIcon(record: ChatRecord | undefined): LucideIcon {\n return record?.pinned ? PinIcon : MessageSquareIcon;\n}\n\nexport default function ChatSwitcher(props: {\n state: ChatSwitcherState;\n subjectId: string;\n workspaceId: string;\n workspaces: readonly WorkspaceChoice[];\n currentChatId: string | null;\n platform: ChordPlatform;\n onHover(index: number): void;\n onPick(index: number): void;\n onDismiss(): void;\n}) {\n const listRef = useRef<HTMLDivElement>(null);\n const { index, visible } = props.state;\n // Read statuses as soon as Control+Tab is pressed, before the list shows.\n useChatStatusRefresh({\n subjectId: props.subjectId,\n workspaceId: props.workspaceId,\n ids: props.state.ids,\n active: true,\n });\n useChatDirectoryVersion(props.subjectId);\n useEffect(() => {\n if (!visible) return;\n listRef.current\n ?.querySelector<HTMLElement>(`[data-switcher-index=\"${index}\"]`)\n ?.scrollIntoView({ block: \"nearest\" });\n }, [index, visible]);\n if (!visible || typeof document === \"undefined\") return null;\n const directory = readChatDirectory(props.subjectId, props.workspaceId);\n const now = Date.now();\n const sidebarIds = new Set([...directory.sidebarOrder, ...directory.pinnedOrder]);\n const workspaceNames = new Map(\n props.workspaces.map((workspace) => [workspace.id, workspace.name]),\n );\n const activeId = `og-chat-switcher-${index}`;\n return createPortal(\n <div\n data-og-chat-switcher=\"\"\n // A light dim, as under ⌘K, lifts the list off the chat behind it.\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/15 p-4 animate-in fade-in-0 duration-[100ms] dark:bg-black/40\"\n // A click outside the list puts it away without switching.\n onPointerDown={(event) => {\n if (event.target === event.currentTarget) props.onDismiss();\n }}\n >\n <div\n className={cn(\n \"flex max-h-[min(480px,70dvh)] w-full max-w-[440px] flex-col overflow-hidden\",\n \"rounded-2xl border border-border bg-surface text-fg shadow-og-lg\",\n \"animate-in fade-in-0 zoom-in-98 duration-[100ms]\",\n )}\n >\n <div className=\"px-4 pt-3 pb-1 text-xs leading-4.5 font-medium text-fg-muted\">\n Recent chats\n </div>\n <div\n ref={listRef}\n role=\"listbox\"\n aria-label=\"Recent chats\"\n aria-activedescendant={activeId}\n className=\"min-h-0 flex-1 overflow-y-auto px-1.5 pb-1.5\"\n >\n {props.state.ids.map((id, position) => {\n const record = directory.rows.get(id);\n const Icon = chatIcon(record);\n const selected = position === index;\n const meta =\n id === props.currentChatId\n ? \"Open now\"\n : record?.updatedAt\n ? formatRelativeTime(record.updatedAt, { now })\n : undefined;\n // Chats in other workspaces say where they are.\n const elsewhere =\n record && record.workspaceId !== props.workspaceId\n ? (workspaceNames.get(record.workspaceId) ?? null)\n : null;\n return (\n <div\n key={id}\n id={`og-chat-switcher-${position}`}\n data-switcher-index={position}\n role=\"option\"\n aria-selected={selected}\n onPointerMove={() => {\n if (!selected) props.onHover(position);\n }}\n // Control+click is a right-click on a Mac: pick on release, and\n // keep the context menu away.\n onPointerUp={(event) => {\n if (event.button === 0) props.onPick(position);\n }}\n onContextMenu={(event) => event.preventDefault()}\n className={cn(\n \"flex min-h-9 w-full min-w-0 cursor-default items-center gap-2.5 rounded-[10px] px-2.5 py-1.5 text-sm text-fg-label select-none\",\n selected ? \"bg-hover text-fg\" : null,\n )}\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\"size-4 shrink-0\", selected ? \"text-fg\" : \"text-fg-muted\")}\n />\n <span className=\"min-w-0 flex-1 truncate\">{record?.title ?? \"Untitled chat\"}</span>\n {elsewhere ? <WorkspaceTag name={elsewhere} /> : null}\n <ChatStatusMarks\n status={record ? currentChatStatus(record, sidebarIds, now) : null}\n />\n {meta ? (\n <span className=\"shrink-0 text-xs text-fg-muted tabular-nums\">{meta}</span>\n ) : null}\n </div>\n );\n })}\n </div>\n <div className=\"flex shrink-0 items-center gap-4 border-t border-border px-4 py-2 text-xs text-fg-muted\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Keycaps\n chord={{ code: \"Tab\", control: true, mod: props.platform !== \"mac\" }}\n platform={props.platform}\n />\n Next\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Keycaps\n chord={{ code: \"Tab\", control: true, mod: props.platform !== \"mac\", shift: true }}\n platform={props.platform}\n />\n Back\n </span>\n <span className=\"ml-auto\">Release to open</span>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
WorkspaceTag
|
|
4
|
-
} from "../../../chunk-IX3NMGIP.js";
|
|
5
2
|
import {
|
|
6
3
|
ChatStatusMarks,
|
|
7
4
|
currentChatStatus,
|
|
8
5
|
useChatStatusRefresh
|
|
9
|
-
} from "../../../chunk-
|
|
6
|
+
} from "../../../chunk-XN6CALYY.js";
|
|
7
|
+
import {
|
|
8
|
+
WorkspaceTag
|
|
9
|
+
} from "../../../chunk-IX3NMGIP.js";
|
|
10
10
|
import {
|
|
11
11
|
Keycaps
|
|
12
12
|
} from "../../../chunk-OHGG2G3A.js";
|
|
13
|
-
import "../../../chunk-PM3OSANE.js";
|
|
14
13
|
import {
|
|
15
14
|
actionIcon,
|
|
16
15
|
actionTitle,
|
|
17
16
|
appActions,
|
|
18
17
|
useAppActions
|
|
19
|
-
} from "../../../chunk-
|
|
18
|
+
} from "../../../chunk-TR4HIKJ2.js";
|
|
20
19
|
import {
|
|
21
20
|
matchesChord
|
|
22
21
|
} from "../../../chunk-BTF7WNUT.js";
|
|
@@ -24,24 +23,25 @@ import {
|
|
|
24
23
|
readChatDirectory,
|
|
25
24
|
rememberChats,
|
|
26
25
|
useChatDirectoryVersion
|
|
27
|
-
} from "../../../chunk-
|
|
28
|
-
import "../../../chunk-
|
|
26
|
+
} from "../../../chunk-NML44AW2.js";
|
|
27
|
+
import "../../../chunk-5MJHH72T.js";
|
|
29
28
|
import "../../../chunk-O5S57N6H.js";
|
|
30
|
-
import "../../../chunk-KJJBQ3KV.js";
|
|
31
29
|
import "../../../chunk-OSI2QWSL.js";
|
|
32
|
-
import "../../../chunk-
|
|
30
|
+
import "../../../chunk-D64Z4V26.js";
|
|
33
31
|
import "../../../chunk-UBJWSGD4.js";
|
|
34
32
|
import "../../../chunk-K3TJNJSU.js";
|
|
35
|
-
import "../../../chunk-
|
|
36
|
-
import "../../../chunk-
|
|
33
|
+
import "../../../chunk-E36IC3LU.js";
|
|
34
|
+
import "../../../chunk-VO6RVVP7.js";
|
|
37
35
|
import "../../../chunk-MMY23KS7.js";
|
|
38
36
|
import "../../../chunk-TXIIBNCA.js";
|
|
39
37
|
import "../../../chunk-3RWVKGQM.js";
|
|
40
38
|
import "../../../chunk-XXZKL5UI.js";
|
|
41
39
|
import "../../../chunk-7ZEGSUR7.js";
|
|
42
|
-
import "../../../chunk-XFNLU7EW.js";
|
|
43
|
-
import "../../../chunk-WGPLDFEC.js";
|
|
44
40
|
import "../../../chunk-HQA6FUM5.js";
|
|
41
|
+
import "../../../chunk-WGPLDFEC.js";
|
|
42
|
+
import "../../../chunk-H5M33DAL.js";
|
|
43
|
+
import "../../../chunk-NS3HKFUX.js";
|
|
44
|
+
import "../../../chunk-KJJBQ3KV.js";
|
|
45
45
|
import "../../../chunk-FABYS4WM.js";
|
|
46
46
|
import "../../../chunk-5TLEWXAB.js";
|
|
47
47
|
import {
|
|
@@ -52,11 +52,11 @@ import {
|
|
|
52
52
|
DialogPortal
|
|
53
53
|
} from "../../../chunk-HZUL2CUH.js";
|
|
54
54
|
import "../../../chunk-I7NCHCA7.js";
|
|
55
|
-
import "../../../chunk-
|
|
55
|
+
import "../../../chunk-TJQDL3JH.js";
|
|
56
56
|
import "../../../chunk-FIDD34ZF.js";
|
|
57
57
|
import "../../../chunk-74JEZLLQ.js";
|
|
58
58
|
import "../../../chunk-YG6NARQY.js";
|
|
59
|
-
import "../../../chunk-
|
|
59
|
+
import "../../../chunk-VYKW6TB2.js";
|
|
60
60
|
import "../../../chunk-IZUAIHR4.js";
|
|
61
61
|
import {
|
|
62
62
|
useAppContext
|
|
@@ -67,15 +67,21 @@ import {
|
|
|
67
67
|
import "../../../chunk-KS57MLGE.js";
|
|
68
68
|
import "../../../chunk-A3KMTJZS.js";
|
|
69
69
|
import "../../../chunk-HMU5IELG.js";
|
|
70
|
-
import
|
|
70
|
+
import {
|
|
71
|
+
LOOSE_MATCH_BELOW,
|
|
72
|
+
foldForSearch,
|
|
73
|
+
rankLabel,
|
|
74
|
+
rankWithKeywords
|
|
75
|
+
} from "../../../chunk-F2RMKGDQ.js";
|
|
71
76
|
import "../../../chunk-LY6727IF.js";
|
|
72
|
-
import "../../../chunk-
|
|
73
|
-
import "../../../chunk-
|
|
74
|
-
import "../../../chunk-TQGJN5UZ.js";
|
|
77
|
+
import "../../../chunk-6AFSZKZA.js";
|
|
78
|
+
import "../../../chunk-AW3QEFOF.js";
|
|
75
79
|
import "../../../chunk-HEVQKE27.js";
|
|
76
|
-
import "../../../chunk-
|
|
80
|
+
import "../../../chunk-LJUMYUBO.js";
|
|
81
|
+
import "../../../chunk-WNDTLK44.js";
|
|
77
82
|
import "../../../chunk-IZV5FTJC.js";
|
|
78
|
-
import "../../../chunk-
|
|
83
|
+
import "../../../chunk-ULYQEFNH.js";
|
|
84
|
+
import "../../../chunk-LEKBNKLD.js";
|
|
79
85
|
import "../../../chunk-DNJ23AWQ.js";
|
|
80
86
|
import "../../../chunk-OB3YGXHQ.js";
|
|
81
87
|
import "../../../chunk-DHXKEJBH.js";
|
|
@@ -85,7 +91,7 @@ import "../../../chunk-CFEFYPNR.js";
|
|
|
85
91
|
import "../../../chunk-SJGAHTY5.js";
|
|
86
92
|
import "../../../chunk-4NHJ6EXL.js";
|
|
87
93
|
import "../../../chunk-TXS65BB2.js";
|
|
88
|
-
import "../../../chunk-
|
|
94
|
+
import "../../../chunk-JFK7NTEA.js";
|
|
89
95
|
|
|
90
96
|
// src/app/components/command-menu/command-menu.tsx
|
|
91
97
|
import {
|
|
@@ -109,90 +115,6 @@ import {
|
|
|
109
115
|
SearchIcon,
|
|
110
116
|
TextSearchIcon
|
|
111
117
|
} from "lucide-react";
|
|
112
|
-
|
|
113
|
-
// src/app/lib/actions/rank.ts
|
|
114
|
-
var COMBINING_MARKS = /[\u0300-\u036f]/g;
|
|
115
|
-
var LOOSE_MATCH_BELOW = 400;
|
|
116
|
-
function foldForSearch(value) {
|
|
117
|
-
return value.normalize("NFD").replace(COMBINING_MARKS, "").toLowerCase().replace(/\s+/g, " ").trim();
|
|
118
|
-
}
|
|
119
|
-
function wordStarts(label) {
|
|
120
|
-
const starts = [];
|
|
121
|
-
for (let index = 0; index < label.length; index++) {
|
|
122
|
-
const previous = index === 0 ? " " : label[index - 1];
|
|
123
|
-
const current = label[index];
|
|
124
|
-
if (/[\p{L}\p{N}]/u.test(current) && !/[\p{L}\p{N}]/u.test(previous)) starts.push(index);
|
|
125
|
-
}
|
|
126
|
-
return starts;
|
|
127
|
-
}
|
|
128
|
-
function subsequenceScore(label, query) {
|
|
129
|
-
const startList = wordStarts(label);
|
|
130
|
-
const starts = new Set(startList);
|
|
131
|
-
const wordOf = (index) => {
|
|
132
|
-
let word = -1;
|
|
133
|
-
for (const start of startList) {
|
|
134
|
-
if (start > index) break;
|
|
135
|
-
word++;
|
|
136
|
-
}
|
|
137
|
-
return word;
|
|
138
|
-
};
|
|
139
|
-
let position = 0;
|
|
140
|
-
let score = 0;
|
|
141
|
-
let previous = -2;
|
|
142
|
-
const fits = (found) => found === previous + 1 || starts.has(found) || previous >= 0 && wordOf(found) === wordOf(previous);
|
|
143
|
-
for (const character of query) {
|
|
144
|
-
if (character === " ") continue;
|
|
145
|
-
let found = label.indexOf(character, position);
|
|
146
|
-
while (found >= 0 && !fits(found)) found = label.indexOf(character, found + 1);
|
|
147
|
-
if (found < 0) return null;
|
|
148
|
-
score += found === previous + 1 ? 3 : starts.has(found) ? 2 : 0;
|
|
149
|
-
previous = found;
|
|
150
|
-
position = found + 1;
|
|
151
|
-
}
|
|
152
|
-
return score;
|
|
153
|
-
}
|
|
154
|
-
function rankLabel(rawLabel, rawQuery) {
|
|
155
|
-
const query = foldForSearch(rawQuery);
|
|
156
|
-
if (!query) return 0;
|
|
157
|
-
const label = foldForSearch(rawLabel);
|
|
158
|
-
if (!label) return null;
|
|
159
|
-
const lengthPenalty = Math.min(label.length, 200) / 1e3;
|
|
160
|
-
if (label === query) return 1e3;
|
|
161
|
-
if (label.startsWith(query)) return 900 - lengthPenalty;
|
|
162
|
-
const at = label.indexOf(query);
|
|
163
|
-
if (at >= 0) {
|
|
164
|
-
const starts = wordStarts(label);
|
|
165
|
-
if (starts.includes(at)) return 800 - at / 100 - lengthPenalty;
|
|
166
|
-
return 600 - at / 100 - lengthPenalty;
|
|
167
|
-
}
|
|
168
|
-
const words = query.split(" ").filter(Boolean);
|
|
169
|
-
if (words.length > 1 && words.every((word) => label.includes(word))) {
|
|
170
|
-
const starts = wordStarts(label);
|
|
171
|
-
const wordStartHits = words.filter(
|
|
172
|
-
(word) => starts.some((start) => label.startsWith(word, start))
|
|
173
|
-
).length;
|
|
174
|
-
return 500 + wordStartHits / words.length * 50 - lengthPenalty;
|
|
175
|
-
}
|
|
176
|
-
if (query.replace(/ /g, "").length < 2) return null;
|
|
177
|
-
const subsequence = subsequenceScore(label, query);
|
|
178
|
-
if (subsequence === null) return null;
|
|
179
|
-
const letters = query.replace(/ /g, "").length;
|
|
180
|
-
if (subsequence < letters) return null;
|
|
181
|
-
return 100 + Math.min(subsequence, 200) - lengthPenalty * 10;
|
|
182
|
-
}
|
|
183
|
-
function rankWithKeywords(label, keywords, query) {
|
|
184
|
-
let best = rankLabel(label, query);
|
|
185
|
-
for (const keyword of keywords ?? []) {
|
|
186
|
-
const rank = rankLabel(keyword, query);
|
|
187
|
-
if (rank !== null) {
|
|
188
|
-
const discounted = rank - 150;
|
|
189
|
-
if (best === null || discounted > best) best = discounted;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return best;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// src/app/components/command-menu/command-menu.tsx
|
|
196
118
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
197
119
|
var RECENT_LIMIT = 6;
|
|
198
120
|
var CHAT_RESULT_LIMIT = 8;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app/components/command-menu/command-menu.tsx","../../../../src/app/lib/actions/rank.ts"],"sourcesContent":["/**\n * The ⌘K menu: find a chat by its title, or run any action, from one field.\n *\n * It opens instantly from what the app already knows (chats the sidebar has\n * loaded and the chats opened recently) and merges the server's title search as\n * it arrives. Chats in the person's other workspaces show too, tagged with\n * their workspace, and so do workspaces to switch to. Tab on a chat shows that\n * chat's actions; the chords of chat actions work on the highlighted chat\n * while the menu is open.\n */\nimport {\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport {\n ArchiveIcon,\n ArrowUpRightIcon,\n ChevronRightIcon,\n CornerDownLeftIcon,\n LockIcon,\n MessageSquareIcon,\n PinIcon,\n SearchIcon,\n TextSearchIcon,\n type LucideIcon,\n} from \"lucide-react\";\nimport type { SessionListRow } from \"../../../session-list-model\";\nimport { useAppContext } from \"../../app-context\";\nimport {\n readChatDirectory,\n rememberChats,\n useChatDirectoryVersion,\n type ChatRecord,\n} from \"../../lib/actions/chat-directory\";\nimport { matchesChord, type Chord } from \"../../lib/actions/chords\";\nimport { useAppActions } from \"../../lib/actions/actions-provider\";\nimport {\n foldForSearch,\n LOOSE_MATCH_BELOW,\n rankLabel,\n rankWithKeywords,\n} from \"../../lib/actions/rank\";\nimport {\n appActions,\n actionIcon,\n actionTitle,\n type ActionEnv,\n type AppAction,\n type WorkspaceChoice,\n} from \"../../lib/actions/registry\";\nimport { cn } from \"../../lib/utils\";\nimport { DialogOverlay, DialogPortal } from \"../../../ui/dialog\";\nimport { formatRelativeTime } from \"../../../ui/relative-time\";\nimport { Keycaps } from \"./keycaps\";\nimport { WorkspaceTag } from \"./workspace-tag\";\nimport { ChatStatusMarks, useChatStatusRefresh } from \"./chat-status\";\nimport { currentChatStatus, type ChatStatus } from \"../../lib/actions/chat-status\";\n\ntype Item = {\n key: string;\n group: string;\n icon: LucideIcon;\n /** A workspace's initial, drawn as the workspace picker draws it, instead of the icon. */\n tile?: string | undefined;\n title: string;\n /** Text to mark as matched in the title. */\n highlight?: string | undefined;\n /** Quiet text on the right (when, \"Archived\"). */\n meta?: string | undefined;\n /** The workspace a chat lives in, when it is not the one on screen. */\n workspaceTag?: string | undefined;\n chord?: Chord | undefined;\n /** Present on chat rows: Tab opens their actions, chat chords act on them. */\n chat?: ChatRecord | undefined;\n /** The chat's sidebar status marks, while its status is known to be current. */\n status?: ChatStatus | null | undefined;\n run(options: { newTab: boolean }): void;\n};\n\ntype Group = { label: string; items: Item[]; best: number };\n\nconst RECENT_LIMIT = 6;\nconst CHAT_RESULT_LIMIT = 8;\nconst ACTION_RESULT_LIMIT = 6;\nconst WORKSPACE_RESULT_LIMIT = 4;\nconst SERVER_DEBOUNCE_MS = 120;\n/** Other workspaces whose titles the server searches too, most used first. */\nconst OTHER_WORKSPACES_SEARCHED = 9;\n/** A chat in another workspace ranks just below an equal match here. */\nconst ELSEWHERE_PENALTY = 10;\n\nfunction relativeMeta(record: ChatRecord, now: number): string | undefined {\n if (record.archived) return \"Archived\";\n if (!record.updatedAt) return undefined;\n return formatRelativeTime(record.updatedAt, { now });\n}\n\nfunction chatIcon(record: ChatRecord): LucideIcon {\n if (record.archived) return ArchiveIcon;\n if (record.pinned) return PinIcon;\n return MessageSquareIcon;\n}\n\n/** Rows the menu may list: top-level chats only (subagent chats live under their parent). */\nfunction listable(record: ChatRecord): boolean {\n return !record.row || record.row.parentSessionId === null;\n}\n\n/** Marks the query's words in a title, case- and accent-insensitively. */\nfunction Highlighted(props: { text: string; query: string | undefined }) {\n const { text, query } = props;\n const words = query ? foldForSearch(query).split(\" \").filter(Boolean) : [];\n if (words.length === 0) return <>{text}</>;\n // Fold per character so positions in the folded text map back to the title.\n const folded = Array.from(text, (character) => foldForSearch(character) || \" \");\n const joined = folded.join(\"\");\n const marked = new Array<boolean>(folded.length).fill(false);\n const offsets: number[] = [];\n let offset = 0;\n for (const piece of folded) {\n offsets.push(offset);\n offset += piece.length;\n }\n const indexAt = (position: number) => {\n let index = offsets.findIndex((start) => start > position);\n index = index < 0 ? offsets.length - 1 : index - 1;\n return index;\n };\n const phrase = words.join(\" \");\n const ranges: Array<[number, number]> = [];\n const whole = joined.indexOf(phrase);\n if (whole >= 0) ranges.push([whole, whole + phrase.length]);\n else {\n for (const word of words) {\n const at = joined.indexOf(word);\n if (at >= 0) ranges.push([at, at + word.length]);\n }\n }\n for (const [start, end] of ranges) {\n for (let index = indexAt(start); index <= indexAt(end - 1); index++) marked[index] = true;\n }\n const characters = Array.from(text);\n const parts: ReactNode[] = [];\n let run = \"\";\n let runMarked = false;\n characters.forEach((character, index) => {\n const isMarked = marked[index] ?? false;\n if (index > 0 && isMarked !== runMarked) {\n parts.push(\n runMarked ? (\n <mark key={parts.length} className=\"bg-transparent font-medium text-fg\">\n {run}\n </mark>\n ) : (\n run\n ),\n );\n run = \"\";\n }\n run += character;\n runMarked = isMarked;\n });\n if (run) {\n parts.push(\n runMarked ? (\n <mark key={parts.length} className=\"bg-transparent font-medium text-fg\">\n {run}\n </mark>\n ) : (\n run\n ),\n );\n }\n return <>{parts}</>;\n}\n\n/**\n * The server's title search: this workspace, and the person's other workspaces\n * they use most, side by side. Each workspace's matches join the list as they\n * arrive.\n */\nfunction useServerTitleSearch(\n workspaceIds: readonly string[],\n subjectId: string,\n query: string,\n open: boolean,\n) {\n const { client } = useAppContext();\n const [state, setState] = useState<{ query: string; rows: SessionListRow[]; loading: boolean }>({\n query: \"\",\n rows: [],\n loading: false,\n });\n const searchKey = workspaceIds.join(\",\");\n useEffect(() => {\n const trimmed = query.trim();\n if (!open || !trimmed || !searchKey) {\n setState({ query: \"\", rows: [], loading: false });\n return;\n }\n setState((current) => ({ ...current, loading: true }));\n const controller = new AbortController();\n const timer = window.setTimeout(() => {\n const targets = searchKey.split(\",\");\n let pending = targets.length;\n let first = true;\n const settle = (rows: SessionListRow[]) => {\n if (controller.signal.aborted) return;\n pending -= 1;\n const replace = first;\n first = false;\n setState((current) => ({\n query: trimmed,\n rows: replace || current.query !== trimmed ? rows : [...current.rows, ...rows],\n loading: pending > 0,\n }));\n };\n targets.forEach((workspaceId, index) => {\n client\n .listSessionPage(workspaceId, {\n search: trimmed,\n archiveStatus: \"all\",\n // This workspace first and fullest; a few from each of the others.\n limit: index === 0 ? 20 : 6,\n signal: controller.signal,\n })\n .then((page) => {\n const rows = [...(page.pinned ?? []), ...page.sessions];\n rememberChats(subjectId, rows);\n settle(rows);\n })\n .catch(() => {\n // Local results still show; the server search is an addition.\n settle([]);\n });\n });\n }, SERVER_DEBOUNCE_MS);\n return () => {\n window.clearTimeout(timer);\n controller.abort();\n };\n }, [client, searchKey, subjectId, query, open]);\n return state;\n}\n\nexport default function CommandMenu(props: {\n open: boolean;\n /** Opens listing workspaces to switch to. */\n pickWorkspace: boolean;\n onOpenChange: (open: boolean) => void;\n /** Where focus goes back to after a plain close. */\n returnFocus: RefObject<HTMLElement | null>;\n}) {\n const actions = useAppActions();\n if (!actions) return null;\n return (\n <CommandMenuDialog\n {...props}\n env={actions.env}\n run={actions.run}\n chordsFor={actions.chordsFor}\n />\n );\n}\n\nfunction CommandMenuDialog(props: {\n open: boolean;\n pickWorkspace: boolean;\n onOpenChange: (open: boolean) => void;\n returnFocus: RefObject<HTMLElement | null>;\n env: ActionEnv;\n run(action: AppAction, chat?: SessionListRow | null, chord?: Chord): void;\n chordsFor(action: AppAction): Chord[];\n}) {\n const { env, run, chordsFor, onOpenChange } = props;\n const { workspaceId, subjectId, platform, surface, workspaces } = env;\n const directoryVersion = useChatDirectoryVersion(subjectId);\n const [query, setQuery] = useState(\"\");\n const [focusChat, setFocusChat] = useState<ChatRecord | null>(null);\n const [pickingWorkspace, setPickingWorkspace] = useState(props.pickWorkspace);\n const [active, setActive] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const ranAction = useRef(false);\n /** Runs right after the menu has returned focus (see `AppAction.opensDialog`). */\n const afterClose = useRef<(() => void) | null>(null);\n const listId = useId();\n const workspaceNames = useMemo(\n () => new Map(workspaces.map((workspace) => [workspace.id, workspace.name])),\n [workspaces],\n );\n /** Chats the menu may show: this workspace's, and those of other workspaces still open to the person. */\n const reachable = useCallback(\n (id: string) => id === workspaceId || workspaceNames.has(id),\n [workspaceId, workspaceNames],\n );\n // The server searches this workspace and the other workspaces used most recently.\n const searchWorkspaceIds = useMemo(() => {\n void directoryVersion;\n const directory = readChatDirectory(subjectId, workspaceId);\n const used: string[] = [];\n for (const id of directory.recent) {\n const record = directory.rows.get(id);\n if (record && !used.includes(record.workspaceId)) used.push(record.workspaceId);\n }\n const others = [...used, ...workspaces.map((workspace) => workspace.id)].filter(\n (id, index, all) => id !== workspaceId && reachable(id) && all.indexOf(id) === index,\n );\n return [workspaceId, ...others.slice(0, OTHER_WORKSPACES_SEARCHED)];\n // Which workspaces to search changes only when the menu opens.\n }, [props.open, subjectId, workspaceId, workspaces, reachable]); // eslint-disable-line react-hooks/exhaustive-deps\n const server = useServerTitleSearch(\n searchWorkspaceIds,\n subjectId,\n focusChat || pickingWorkspace ? \"\" : query,\n props.open,\n );\n\n // Every open starts fresh.\n useEffect(() => {\n if (!props.open) return;\n setQuery(\"\");\n setFocusChat(null);\n setPickingWorkspace(props.pickWorkspace);\n setActive(0);\n ranAction.current = false;\n afterClose.current = null;\n }, [props.open, props.pickWorkspace]);\n\n const close = useCallback(() => onOpenChange(false), [onOpenChange]);\n\n const runAction = useCallback(\n (action: AppAction, chat: SessionListRow | null, chord?: Chord) => {\n if (action.opensDialog) {\n afterClose.current = () => run(action, action.forChat ? chat : undefined, chord);\n close();\n return;\n }\n ranAction.current = true;\n close();\n run(action, action.forChat ? chat : undefined, chord);\n },\n [close, run],\n );\n\n const openChat = useCallback(\n (record: ChatRecord, newTab: boolean) => {\n ranAction.current = true;\n close();\n if (newTab && surface === \"web\") {\n window.open(env.ops.linkTo(record), \"_blank\", \"noopener\");\n return;\n }\n env.openChat(record.id, record.workspaceId);\n },\n [close, env, surface],\n );\n\n const openWorkspace = useCallback(\n (id: string) => {\n ranAction.current = true;\n close();\n if (id !== workspaceId) env.openWorkspace(id);\n },\n [close, env, workspaceId],\n );\n\n const startPickingWorkspace = useCallback(() => {\n setFocusChat(null);\n setPickingWorkspace(true);\n setQuery(\"\");\n inputRef.current?.focus();\n }, []);\n\n const actionItem = useCallback(\n (action: AppAction, chat: SessionListRow | null, group: string, highlight?: string): Item => ({\n key: `action:${action.id}`,\n group,\n icon: actionIcon(action, chat),\n title: actionTitle(action, env, chat),\n highlight,\n chord: chordsFor(action)[0],\n // Switching workspace lists the workspaces right here.\n run: () =>\n action.id === \"go.switchWorkspace\" ? startPickingWorkspace() : runAction(action, chat),\n }),\n [chordsFor, env, runAction, startPickingWorkspace],\n );\n\n const groups = useMemo<Group[]>(() => {\n void directoryVersion;\n const now = Date.now();\n const directory = readChatDirectory(subjectId, workspaceId);\n const current = env.currentChat;\n const sidebarIds = new Set([...directory.sidebarOrder, ...directory.pinnedOrder]);\n\n const chatItem = (record: ChatRecord, group: string, highlight?: string): Item => ({\n key: `chat:${record.id}`,\n group,\n icon: chatIcon(record),\n title: record.title,\n highlight,\n meta: current?.id === record.id ? \"Open now\" : relativeMeta(record, now),\n workspaceTag:\n record.workspaceId === workspaceId ? undefined : workspaceNames.get(record.workspaceId),\n chat: record,\n status: currentChatStatus(record, sidebarIds, now),\n run: ({ newTab }) => openChat(record, newTab),\n });\n\n const workspaceItem = (choice: WorkspaceChoice, group: string, highlight?: string): Item => ({\n key: `workspace:${choice.id}`,\n group,\n icon: LockIcon,\n // A Personal workspace shows its lock, as in the workspace picker.\n tile: choice.personal ? undefined : (choice.name.trim()[0] ?? \"W\").toUpperCase(),\n title: choice.name,\n highlight,\n meta: choice.id === workspaceId ? \"Current\" : undefined,\n run: () => openWorkspace(choice.id),\n });\n\n // Workspaces to switch to, by organization.\n if (pickingWorkspace) {\n const trimmed = query.trim();\n const organizations = new Set(workspaces.map((choice) => choice.organization));\n const scored = workspaces.flatMap((choice) => {\n if (!trimmed) return [{ choice, rank: 0 }];\n const rank =\n rankLabel(choice.name, trimmed) ??\n (organizations.size > 1 ? rankLabel(choice.organization, trimmed) : null);\n return rank === null ? [] : [{ choice, rank }];\n });\n const realMatch = scored.some((entry) => entry.rank >= LOOSE_MATCH_BELOW);\n const kept = scored.filter(\n (entry) => !trimmed || !realMatch || entry.rank >= LOOSE_MATCH_BELOW,\n );\n if (trimmed) {\n kept.sort((a, b) => b.rank - a.rank);\n return [\n {\n label: \"Workspaces\",\n items: kept.map((entry) => workspaceItem(entry.choice, \"Workspaces\", trimmed)),\n best: 0,\n },\n ];\n }\n const byOrganization = new Map<string, Item[]>();\n for (const { choice } of kept) {\n const label = organizations.size > 1 ? choice.organization : \"Workspaces\";\n const list = byOrganization.get(label) ?? [];\n list.push(workspaceItem(choice, label));\n byOrganization.set(label, list);\n }\n return [...byOrganization].map(([label, items]) => ({ label, items, best: 0 }));\n }\n\n // A chat's own actions (after Tab).\n if (focusChat) {\n // Chats in other workspaces offer what works from here: open and copy link.\n const sameWorkspace = focusChat.workspaceId === workspaceId;\n const row = sameWorkspace\n ? (focusChat.row ?? (current?.id === focusChat.id ? current : null))\n : null;\n const items: Array<{ item: Item; rank: number }> = [];\n const openRank = rankLabel(\"Open\", query);\n if (openRank !== null) {\n items.push({\n rank: openRank + 1,\n item: {\n key: \"open\",\n group: focusChat.title,\n icon: CornerDownLeftIcon,\n title: \"Open\",\n highlight: query,\n run: () => openChat(focusChat, false),\n },\n });\n }\n if (surface === \"web\") {\n const tabRank = rankLabel(\"Open in new tab\", query);\n if (tabRank !== null) {\n items.push({\n rank: tabRank,\n item: {\n key: \"open-tab\",\n group: focusChat.title,\n icon: ArrowUpRightIcon,\n title: \"Open in new tab\",\n highlight: query,\n run: () => openChat(focusChat, true),\n },\n });\n }\n }\n for (const action of appActions()) {\n if (!action.forChat || action.inCommandMenu === false) continue;\n // Copy link needs only the id; the rest need the chat's row.\n const target = row ?? (action.id === \"chat.copyLink\" ? pseudoRow(focusChat) : null);\n if (!target || !action.available(env, target)) continue;\n const rank = rankWithKeywords(actionTitle(action, env, target), action.keywords, query);\n if (rank === null) continue;\n items.push({ rank, item: actionItem(action, target, focusChat.title, query) });\n }\n if (query) items.sort((a, b) => b.rank - a.rank);\n return [{ label: focusChat.title, items: items.map((entry) => entry.item), best: 0 }];\n }\n\n const trimmed = query.trim();\n if (!trimmed) {\n const result: Group[] = [];\n // Chats opened recently come first; the top of the sidebar fills the\n // rest, so a fresh window still offers somewhere to go.\n const recentIds = [...new Set([...directory.recent, ...directory.sidebarOrder])].filter(\n (id) => id !== current?.id,\n );\n const recent = recentIds\n .map((id) => directory.rows.get(id))\n .filter((record): record is ChatRecord =>\n Boolean(record && listable(record) && !record.archived && reachable(record.workspaceId)),\n )\n .slice(0, RECENT_LIMIT);\n if (recent.length > 0) {\n result.push({\n label: \"Recent chats\",\n items: recent.map((record) => chatItem(record, \"Recent chats\")),\n best: 0,\n });\n }\n if (current) {\n const chatActions = appActions().filter(\n (action) =>\n action.forChat &&\n action.inCommandMenu !== false &&\n action.id !== \"chat.find\" &&\n action.available(env, current),\n );\n if (chatActions.length > 0) {\n result.push({\n label: \"This chat\",\n items: chatActions.map((action) => actionItem(action, current, \"This chat\")),\n best: 0,\n });\n }\n }\n const general = appActions().filter(\n (action) =>\n !action.forChat &&\n action.inCommandMenu !== false &&\n action.id !== \"commandMenu.open\" &&\n action.available(env, null),\n );\n if (general.length > 0) {\n result.push({\n label: \"Go to\",\n items: general.map((action) => actionItem(action, null, \"Go to\")),\n best: 0,\n });\n }\n return result;\n }\n\n // Chats: everything the app knows, ranked by title, plus the server's matches.\n const recentIndex = new Map(directory.recent.map((id, index) => [id, index]));\n const serverIds = new Set(server.query === trimmed ? server.rows.map((row) => row.id) : []);\n const scored: Array<{ record: ChatRecord; rank: number; loose: boolean }> = [];\n for (const record of directory.rows.values()) {\n if (!listable(record) || !reachable(record.workspaceId)) continue;\n let rank = rankLabel(record.title, trimmed);\n const loose = rank !== null && rank < LOOSE_MATCH_BELOW;\n // The server matched every word in the title or first message.\n if (rank === null && serverIds.has(record.id)) rank = 50;\n if (rank === null) continue;\n const visited = recentIndex.get(record.id);\n if (visited !== undefined) rank += Math.max(0, 20 - visited);\n if (record.pinned) rank += 5;\n if (record.archived) rank -= 300;\n if (record.workspaceId !== workspaceId) rank -= ELSEWHERE_PENALTY;\n scored.push({ record, rank, loose });\n }\n\n const actionScores: Array<{ item: Item; rank: number; loose: boolean }> = [];\n for (const action of appActions()) {\n if (action.inCommandMenu === false) continue;\n const target = action.forChat ? current : null;\n if (action.forChat && !target) continue;\n if (!action.available(env, target)) continue;\n const rank = rankWithKeywords(actionTitle(action, env, target), action.keywords, trimmed);\n if (rank === null) continue;\n actionScores.push({\n rank,\n loose: rank < LOOSE_MATCH_BELOW,\n item: actionItem(action, target, \"Actions\", trimmed),\n });\n }\n const workspaceScores: Array<{ item: Item; rank: number; loose: boolean }> = [];\n for (const choice of workspaces) {\n if (choice.id === workspaceId) continue;\n const rank = rankLabel(choice.name, trimmed);\n if (rank === null) continue;\n workspaceScores.push({\n rank,\n loose: rank < LOOSE_MATCH_BELOW,\n item: workspaceItem(choice, \"Workspaces\", trimmed),\n });\n }\n // Letters-in-order guesses only help when nothing really matches; next to\n // real matches they are noise (\"pin\" → \"Postgres … investigation\").\n const hasRealMatch =\n scored.some((entry) => !entry.loose) ||\n actionScores.some((entry) => !entry.loose) ||\n workspaceScores.some((entry) => !entry.loose);\n const chats = scored\n .filter((entry) => !hasRealMatch || !entry.loose)\n .sort((a, b) => b.rank - a.rank || b.record.updatedAt - a.record.updatedAt)\n .slice(0, CHAT_RESULT_LIMIT);\n const actionsFound = actionScores\n .filter((entry) => !hasRealMatch || !entry.loose)\n .sort((a, b) => b.rank - a.rank)\n .slice(0, ACTION_RESULT_LIMIT);\n const workspacesFound = workspaceScores\n .filter((entry) => !hasRealMatch || !entry.loose)\n .sort((a, b) => b.rank - a.rank)\n .slice(0, WORKSPACE_RESULT_LIMIT);\n\n const result: Group[] = [];\n if (chats.length > 0) {\n result.push({\n label: \"Chats\",\n items: chats.map((entry) => chatItem(entry.record, \"Chats\", trimmed)),\n best: chats[0]!.rank,\n });\n }\n if (actionsFound.length > 0) {\n result.push({\n label: \"Actions\",\n items: actionsFound.map((entry) => entry.item),\n best: actionsFound[0]!.rank,\n });\n }\n if (workspacesFound.length > 0) {\n result.push({\n label: \"Workspaces\",\n items: workspacesFound.map((entry) => entry.item),\n // Chats and actions first on a tie: a workspace is a bigger jump.\n best: workspacesFound[0]!.rank - 1,\n });\n }\n // A clearly better action match (\"new\" → New chat) comes before chats.\n result.sort((a, b) => b.best - a.best);\n result.push({\n label: \"Messages\",\n best: -Infinity,\n items: [\n {\n key: \"search-messages\",\n group: \"Messages\",\n icon: TextSearchIcon,\n title: `Search messages for “${trimmed}”`,\n run: () => {\n afterClose.current = () => env.searchMessages(trimmed);\n close();\n },\n },\n ],\n });\n return result;\n }, [\n actionItem,\n close,\n directoryVersion,\n env,\n focusChat,\n openChat,\n openWorkspace,\n pickingWorkspace,\n query,\n reachable,\n server.query,\n server.rows,\n subjectId,\n surface,\n workspaceId,\n workspaceNames,\n workspaces,\n ]);\n\n const items = useMemo(() => groups.flatMap((group) => group.items), [groups]);\n const listedChatIds = useMemo(\n () => items.flatMap((item) => (item.chat ? [item.chat.id] : [])),\n [items],\n );\n useChatStatusRefresh({ subjectId, workspaceId, ids: listedChatIds, active: props.open });\n const activeIndex = items.length === 0 ? -1 : Math.min(active, items.length - 1);\n const activeItem = activeIndex >= 0 ? items[activeIndex] : undefined;\n const searching = Boolean(query.trim()) && !focusChat && !pickingWorkspace && server.loading;\n\n // Typing starts at the best match; the workspace list starts at the current workspace's neighbour.\n useEffect(() => {\n if (pickingWorkspace && !query) {\n const index = workspaces.findIndex((choice) => choice.id === workspaceId);\n setActive(index >= 0 && workspaces.length > 1 ? (index + 1) % workspaces.length : 0);\n return;\n }\n setActive(0);\n }, [query, focusChat, pickingWorkspace, workspaces, workspaceId]);\n\n // Keep the highlighted row in view without scrolling the page.\n useLayoutEffect(() => {\n if (!activeItem) return;\n const element = listRef.current?.querySelector<HTMLElement>(\n `[data-item-key=\"${CSS.escape(activeItem.key)}\"]`,\n );\n element?.scrollIntoView({ block: \"nearest\" });\n }, [activeItem]);\n\n const enterChat = useCallback((record: ChatRecord) => {\n setFocusChat(record);\n setQuery(\"\");\n inputRef.current?.focus();\n }, []);\n const leaveChat = useCallback(() => {\n setFocusChat(null);\n setPickingWorkspace(false);\n setQuery(\"\");\n }, []);\n\n const onKeyDown = useCallback(\n (event: ReactKeyboardEvent<HTMLDivElement>) => {\n if (event.nativeEvent.isComposing) return;\n const count = items.length;\n const mod = platform === \"mac\" ? event.metaKey : event.ctrlKey;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowUp\": {\n if (event.altKey || mod) break;\n event.preventDefault();\n if (count === 0) return;\n const step = event.key === \"ArrowDown\" ? 1 : -1;\n setActive((current) => (Math.min(current, count - 1) + step + count) % count);\n return;\n }\n case \"PageDown\":\n case \"PageUp\": {\n event.preventDefault();\n if (count === 0) return;\n const step = event.key === \"PageDown\" ? 5 : -5;\n setActive((current) => Math.max(0, Math.min(count - 1, current + step)));\n return;\n }\n case \"Home\":\n case \"End\": {\n // Inside the field these move the caret, unless the field is empty.\n if (query) break;\n event.preventDefault();\n setActive(event.key === \"Home\" ? 0 : Math.max(0, count - 1));\n return;\n }\n case \"Enter\": {\n event.preventDefault();\n activeItem?.run({ newTab: mod });\n return;\n }\n case \"Tab\": {\n event.preventDefault();\n if (event.shiftKey) {\n if (focusChat || pickingWorkspace) leaveChat();\n return;\n }\n if (!focusChat && activeItem?.chat) enterChat(activeItem.chat);\n return;\n }\n case \"Backspace\": {\n if ((focusChat || pickingWorkspace) && !query) {\n event.preventDefault();\n leaveChat();\n }\n return;\n }\n default:\n break;\n }\n // A chat action's chord acts on the highlighted chat, as in Linear.\n const chatRecord = focusChat ?? activeItem?.chat;\n if (!chatRecord) return;\n const sameWorkspace = chatRecord.workspaceId === workspaceId;\n for (const action of appActions()) {\n if (!action.forChat) continue;\n const chord = chordsFor(action).find((candidate) =>\n matchesChord(event.nativeEvent, candidate, platform),\n );\n if (!chord) continue;\n const row =\n (sameWorkspace\n ? (chatRecord.row ?? (env.currentChat?.id === chatRecord.id ? env.currentChat : null))\n : null) ?? (action.id === \"chat.copyLink\" ? pseudoRow(chatRecord) : null);\n event.preventDefault();\n event.stopPropagation();\n if (row && action.available(env, row)) runAction(action, row, chord);\n return;\n }\n },\n [\n activeItem,\n chordsFor,\n enterChat,\n env,\n focusChat,\n items.length,\n leaveChat,\n pickingWorkspace,\n platform,\n query,\n runAction,\n workspaceId,\n ],\n );\n\n const placeholder = focusChat\n ? \"Search actions…\"\n : pickingWorkspace\n ? \"Switch to workspace…\"\n : \"Search chats or run an action…\";\n const optionId = (item: Item) => `${listId}-${item.key.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n\n return (\n <DialogPrimitive.Root open={props.open} onOpenChange={onOpenChange}>\n <DialogPortal>\n <DialogOverlay className=\"bg-black/25 dark:bg-black/45\" />\n <DialogPrimitive.Content\n data-og-command-menu=\"\"\n aria-label=\"Command menu\"\n aria-describedby={undefined}\n onOpenAutoFocus={(event) => {\n event.preventDefault();\n inputRef.current?.focus();\n }}\n onCloseAutoFocus={(event) => {\n // An action moves focus where it belongs (the new chat's composer,\n // the title being renamed); only a plain close returns focus.\n if (ranAction.current) {\n event.preventDefault();\n return;\n }\n const target = props.returnFocus.current;\n if (target?.isConnected) {\n event.preventDefault();\n target.focus({ preventScroll: true });\n }\n const next = afterClose.current;\n afterClose.current = null;\n next?.();\n }}\n onEscapeKeyDown={(event) => {\n // Esc steps back out of a chat's actions, or the workspace list\n // reached from the menu, before it closes the menu.\n if (!focusChat && !(pickingWorkspace && !props.pickWorkspace)) return;\n event.preventDefault();\n leaveChat();\n }}\n onKeyDown={onKeyDown}\n className={cn(\n \"fixed top-[12dvh] left-1/2 z-50 flex max-h-[min(560px,76dvh)] w-[calc(100vw-1.5rem)] max-w-[640px] -translate-x-1/2 flex-col overflow-hidden\",\n \"rounded-2xl border border-border bg-surface text-fg shadow-og-lg outline-hidden\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-98\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-98\",\n \"duration-[120ms] max-sm:top-3\",\n )}\n >\n <DialogPrimitive.Title className=\"sr-only\">Command menu</DialogPrimitive.Title>\n <div className=\"flex min-h-13 shrink-0 items-center gap-2.5 border-b border-border px-4\">\n <SearchIcon aria-hidden=\"true\" className=\"size-4 shrink-0 text-fg-muted\" />\n {focusChat ? (\n <button\n type=\"button\"\n onClick={leaveChat}\n title=\"Back to all results\"\n className=\"inline-flex max-w-[45%] shrink-0 items-center gap-1 rounded-full bg-hover py-0.5 pr-1.5 pl-2.5 text-xs font-medium text-fg outline-hidden hover:bg-selection focus-visible:outline-2 focus-visible:outline-ring/55\"\n >\n <span className=\"truncate\">{focusChat.title}</span>\n <ChevronRightIcon aria-hidden=\"true\" className=\"size-3.5 text-fg-muted\" />\n </button>\n ) : pickingWorkspace ? (\n <button\n type=\"button\"\n onClick={leaveChat}\n title=\"Back to all results\"\n className=\"inline-flex shrink-0 items-center gap-1 rounded-full bg-hover py-0.5 pr-1.5 pl-2.5 text-xs font-medium text-fg outline-hidden hover:bg-selection focus-visible:outline-2 focus-visible:outline-ring/55\"\n >\n Workspaces\n <ChevronRightIcon aria-hidden=\"true\" className=\"size-3.5 text-fg-muted\" />\n </button>\n ) : null}\n <input\n ref={inputRef}\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeItem ? optionId(activeItem) : undefined}\n aria-label={\n focusChat\n ? `Actions for ${focusChat.title}`\n : pickingWorkspace\n ? \"Search workspaces\"\n : \"Search chats and actions\"\n }\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n enterKeyHint=\"go\"\n value={query}\n maxLength={200}\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n // The whole menu is the focus context; a ring on the field adds noise.\n style={{ outline: \"none\" }}\n className=\"h-13 min-w-0 flex-1 bg-transparent text-[15px] text-fg outline-hidden placeholder:text-fg-subtle\"\n />\n {searching ? (\n <span\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 animate-spin rounded-full border-[1.5px] border-fg-subtle/40 border-t-fg-muted\"\n />\n ) : null}\n </div>\n <div\n ref={listRef}\n id={listId}\n role=\"listbox\"\n aria-label={focusChat ? \"Chat actions\" : pickingWorkspace ? \"Workspaces\" : \"Results\"}\n className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain p-1.5\"\n >\n {items.length === 0 ? (\n <p className=\"px-2.5 py-6 text-center text-sm text-fg-muted\">\n {searching ? \"Searching…\" : \"No matches\"}\n </p>\n ) : (\n groups.map((group) =>\n group.items.length === 0 ? null : (\n <div key={group.label} role=\"group\" aria-label={group.label}>\n {groups.length > 1 || !focusChat ? (\n <div className=\"truncate px-2.5 pt-2 pb-1 text-xs leading-4.5 font-medium text-fg-muted\">\n {group.label}\n </div>\n ) : null}\n {group.items.map((item) => {\n const index = items.indexOf(item);\n const selected = index === activeIndex;\n const Icon = item.icon;\n return (\n <div\n key={item.key}\n id={optionId(item)}\n data-item-key={item.key}\n role=\"option\"\n aria-selected={selected}\n onPointerMove={() => {\n if (!selected) setActive(index);\n }}\n onPointerDown={(event) => event.preventDefault()}\n onClick={(event) =>\n item.run({ newTab: platform === \"mac\" ? event.metaKey : event.ctrlKey })\n }\n className={cn(\n \"relative flex min-h-9 w-full min-w-0 cursor-default items-center gap-2.5 rounded-[10px] px-2.5 py-1.5 text-sm text-fg-label select-none pointer-coarse:min-h-11\",\n selected ? \"bg-hover text-fg\" : null,\n )}\n >\n {item.tile ? (\n <span\n aria-hidden=\"true\"\n className=\"flex size-4 shrink-0 items-center justify-center rounded-[4px] bg-surface-3 text-2xs font-semibold text-fg-muted\"\n >\n {item.tile}\n </span>\n ) : (\n <Icon\n aria-hidden=\"true\"\n className={cn(\n \"size-4 shrink-0\",\n selected ? \"text-fg\" : \"text-fg-muted\",\n )}\n />\n )}\n <span className=\"min-w-0 flex-1 truncate\">\n <Highlighted text={item.title} query={item.highlight} />\n </span>\n {item.workspaceTag ? <WorkspaceTag name={item.workspaceTag} /> : null}\n <ChatStatusMarks status={item.status ?? null} />\n {item.meta ? (\n <span className=\"shrink-0 text-xs text-fg-muted tabular-nums\">\n {item.meta}\n </span>\n ) : null}\n {item.chord ? (\n // Touch screens have no keys to press.\n <Keycaps\n chord={item.chord}\n platform={platform}\n className=\"pointer-coarse:hidden\"\n />\n ) : null}\n </div>\n );\n })}\n </div>\n ),\n )\n )}\n </div>\n <div className=\"hidden shrink-0 items-center gap-4 border-t border-border px-4 py-2 text-xs text-fg-muted pointer-fine:flex\">\n <FooterHint\n keys={[{ code: \"ArrowUp\" }, { code: \"ArrowDown\" }]}\n label=\"Move\"\n platform={platform}\n />\n <FooterHint\n keys={[{ code: \"Enter\" }]}\n label={pickingWorkspace ? \"Switch\" : \"Open\"}\n platform={platform}\n />\n {focusChat || pickingWorkspace ? (\n <FooterHint keys={[{ code: \"Escape\" }]} label=\"Back\" platform={platform} />\n ) : (\n <FooterHint keys={[{ code: \"Tab\" }]} label=\"Chat actions\" platform={platform} />\n )}\n {surface === \"web\" && !focusChat && !pickingWorkspace ? (\n <FooterHint\n keys={[{ code: \"Enter\", mod: true }]}\n label=\"New tab\"\n platform={platform}\n />\n ) : null}\n <span className=\"ml-auto inline-flex items-center gap-1.5\">\n <Keycaps chord={{ code: \"Slash\", mod: true }} platform={platform} />\n All shortcuts\n </span>\n </div>\n </DialogPrimitive.Content>\n </DialogPortal>\n </DialogPrimitive.Root>\n );\n}\n\nfunction FooterHint(props: { keys: Chord[]; label: string; platform: ActionEnv[\"platform\"] }) {\n return (\n <span className=\"inline-flex items-center gap-1.5\">\n <span className=\"inline-flex items-center gap-0.5\">\n {props.keys.map((chord) => (\n <Keycaps key={chord.code} chord={chord} platform={props.platform} />\n ))}\n </span>\n {props.label}\n </span>\n );\n}\n\n/** Enough of a chat row to copy its link when only a recent-chats record is known. */\nfunction pseudoRow(record: ChatRecord): SessionListRow {\n return { id: record.id, workspaceId: record.workspaceId } as SessionListRow;\n}\n","/**\n * Ranks short labels (chat titles, action names) against what someone typed.\n *\n * Higher is better; `null` means no match. Tiers, best first:\n * whole label starts with the query, a word starts with it, it appears\n * anywhere, every query word appears in some order, and finally the query's\n * letters appear in order (\"kbsh\" → \"Keyboard shortcuts\"). Within a tier,\n * shorter labels and earlier positions win. Letters-in-order matches rank below\n * `LOOSE_MATCH_BELOW`, so a list can drop them once it has real matches.\n */\n\nconst COMBINING_MARKS = /[\\u0300-\\u036f]/g;\n\n/** Ranks below this are letters-in-order guesses rather than real matches. */\nexport const LOOSE_MATCH_BELOW = 400;\n\n/** Case- and accent-insensitive form used for matching. */\nexport function foldForSearch(value: string): string {\n return value\n .normalize(\"NFD\")\n .replace(COMBINING_MARKS, \"\")\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction wordStarts(label: string): number[] {\n const starts: number[] = [];\n for (let index = 0; index < label.length; index++) {\n const previous = index === 0 ? \" \" : label[index - 1]!;\n const current = label[index]!;\n if (/[\\p{L}\\p{N}]/u.test(current) && !/[\\p{L}\\p{N}]/u.test(previous)) starts.push(index);\n }\n return starts;\n}\n\nfunction subsequenceScore(label: string, query: string): number | null {\n // Letters in order, read the way people abbreviate: the first letter starts a\n // word, and moving on to a later word means landing on its first letter\n // (\"kbsh\" → Keyboard shortcuts). Consecutive letters are worth more.\n const startList = wordStarts(label);\n const starts = new Set(startList);\n const wordOf = (index: number) => {\n let word = -1;\n for (const start of startList) {\n if (start > index) break;\n word++;\n }\n return word;\n };\n let position = 0;\n let score = 0;\n let previous = -2;\n // Prefer the next letter inside the current word; otherwise only the start\n // of a later word counts.\n const fits = (found: number) =>\n found === previous + 1 ||\n starts.has(found) ||\n (previous >= 0 && wordOf(found) === wordOf(previous));\n for (const character of query) {\n if (character === \" \") continue;\n let found = label.indexOf(character, position);\n while (found >= 0 && !fits(found)) found = label.indexOf(character, found + 1);\n if (found < 0) return null;\n score += found === previous + 1 ? 3 : starts.has(found) ? 2 : 0;\n previous = found;\n position = found + 1;\n }\n return score;\n}\n\nexport function rankLabel(rawLabel: string, rawQuery: string): number | null {\n const query = foldForSearch(rawQuery);\n if (!query) return 0;\n const label = foldForSearch(rawLabel);\n if (!label) return null;\n const lengthPenalty = Math.min(label.length, 200) / 1000;\n if (label === query) return 1000;\n if (label.startsWith(query)) return 900 - lengthPenalty;\n const at = label.indexOf(query);\n if (at >= 0) {\n const starts = wordStarts(label);\n if (starts.includes(at)) return 800 - at / 100 - lengthPenalty;\n return 600 - at / 100 - lengthPenalty;\n }\n const words = query.split(\" \").filter(Boolean);\n if (words.length > 1 && words.every((word) => label.includes(word))) {\n const starts = wordStarts(label);\n const wordStartHits = words.filter((word) =>\n starts.some((start) => label.startsWith(word, start)),\n ).length;\n return 500 + (wordStartHits / words.length) * 50 - lengthPenalty;\n }\n if (query.replace(/ /g, \"\").length < 2) return null;\n const subsequence = subsequenceScore(label, query);\n if (subsequence === null) return null;\n // Only keep loose matches that hit word starts or runs; random letters scattered\n // across a long title are noise.\n const letters = query.replace(/ /g, \"\").length;\n if (subsequence < letters) return null;\n return 100 + Math.min(subsequence, 200) - lengthPenalty * 10;\n}\n\n/** The best rank across a label and extra keywords (a keyword match ranks below the same match on the name). */\nexport function rankWithKeywords(\n label: string,\n keywords: readonly string[] | undefined,\n query: string,\n): number | null {\n let best = rankLabel(label, query);\n for (const keyword of keywords ?? []) {\n const rank = rankLabel(keyword, query);\n if (rank !== null) {\n const discounted = rank - 150;\n if (best === null || discounted > best) best = discounted;\n }\n }\n return best;\n}\n"],"mappings":"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","names":["trimmed","scored","items","result"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/components/command-menu/command-menu.tsx"],"sourcesContent":["/**\n * The ⌘K menu: find a chat by its title, or run any action, from one field.\n *\n * It opens instantly from what the app already knows (chats the sidebar has\n * loaded and the chats opened recently) and merges the server's title search as\n * it arrives. Chats in the person's other workspaces show too, tagged with\n * their workspace, and so do workspaces to switch to. Tab on a chat shows that\n * chat's actions; the chords of chat actions work on the highlighted chat\n * while the menu is open.\n */\nimport {\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport {\n ArchiveIcon,\n ArrowUpRightIcon,\n ChevronRightIcon,\n CornerDownLeftIcon,\n LockIcon,\n MessageSquareIcon,\n PinIcon,\n SearchIcon,\n TextSearchIcon,\n type LucideIcon,\n} from \"lucide-react\";\nimport type { SessionListRow } from \"../../../session-list-model\";\nimport { useAppContext } from \"../../app-context\";\nimport {\n readChatDirectory,\n rememberChats,\n useChatDirectoryVersion,\n type ChatRecord,\n} from \"../../lib/actions/chat-directory\";\nimport { matchesChord, type Chord } from \"../../lib/actions/chords\";\nimport { useAppActions } from \"../../lib/actions/actions-provider\";\nimport {\n foldForSearch,\n LOOSE_MATCH_BELOW,\n rankLabel,\n rankWithKeywords,\n} from \"../../lib/actions/rank\";\nimport {\n appActions,\n actionIcon,\n actionTitle,\n type ActionEnv,\n type AppAction,\n type WorkspaceChoice,\n} from \"../../lib/actions/registry\";\nimport { cn } from \"../../lib/utils\";\nimport { DialogOverlay, DialogPortal } from \"../../../ui/dialog\";\nimport { formatRelativeTime } from \"../../../ui/relative-time\";\nimport { Keycaps } from \"./keycaps\";\nimport { WorkspaceTag } from \"./workspace-tag\";\nimport { ChatStatusMarks, useChatStatusRefresh } from \"./chat-status\";\nimport { currentChatStatus, type ChatStatus } from \"../../lib/actions/chat-status\";\n\ntype Item = {\n key: string;\n group: string;\n icon: LucideIcon;\n /** A workspace's initial, drawn as the workspace picker draws it, instead of the icon. */\n tile?: string | undefined;\n title: string;\n /** Text to mark as matched in the title. */\n highlight?: string | undefined;\n /** Quiet text on the right (when, \"Archived\"). */\n meta?: string | undefined;\n /** The workspace a chat lives in, when it is not the one on screen. */\n workspaceTag?: string | undefined;\n chord?: Chord | undefined;\n /** Present on chat rows: Tab opens their actions, chat chords act on them. */\n chat?: ChatRecord | undefined;\n /** The chat's sidebar status marks, while its status is known to be current. */\n status?: ChatStatus | null | undefined;\n run(options: { newTab: boolean }): void;\n};\n\ntype Group = { label: string; items: Item[]; best: number };\n\nconst RECENT_LIMIT = 6;\nconst CHAT_RESULT_LIMIT = 8;\nconst ACTION_RESULT_LIMIT = 6;\nconst WORKSPACE_RESULT_LIMIT = 4;\nconst SERVER_DEBOUNCE_MS = 120;\n/** Other workspaces whose titles the server searches too, most used first. */\nconst OTHER_WORKSPACES_SEARCHED = 9;\n/** A chat in another workspace ranks just below an equal match here. */\nconst ELSEWHERE_PENALTY = 10;\n\nfunction relativeMeta(record: ChatRecord, now: number): string | undefined {\n if (record.archived) return \"Archived\";\n if (!record.updatedAt) return undefined;\n return formatRelativeTime(record.updatedAt, { now });\n}\n\nfunction chatIcon(record: ChatRecord): LucideIcon {\n if (record.archived) return ArchiveIcon;\n if (record.pinned) return PinIcon;\n return MessageSquareIcon;\n}\n\n/** Rows the menu may list: top-level chats only (subagent chats live under their parent). */\nfunction listable(record: ChatRecord): boolean {\n return !record.row || record.row.parentSessionId === null;\n}\n\n/** Marks the query's words in a title, case- and accent-insensitively. */\nfunction Highlighted(props: { text: string; query: string | undefined }) {\n const { text, query } = props;\n const words = query ? foldForSearch(query).split(\" \").filter(Boolean) : [];\n if (words.length === 0) return <>{text}</>;\n // Fold per character so positions in the folded text map back to the title.\n const folded = Array.from(text, (character) => foldForSearch(character) || \" \");\n const joined = folded.join(\"\");\n const marked = new Array<boolean>(folded.length).fill(false);\n const offsets: number[] = [];\n let offset = 0;\n for (const piece of folded) {\n offsets.push(offset);\n offset += piece.length;\n }\n const indexAt = (position: number) => {\n let index = offsets.findIndex((start) => start > position);\n index = index < 0 ? offsets.length - 1 : index - 1;\n return index;\n };\n const phrase = words.join(\" \");\n const ranges: Array<[number, number]> = [];\n const whole = joined.indexOf(phrase);\n if (whole >= 0) ranges.push([whole, whole + phrase.length]);\n else {\n for (const word of words) {\n const at = joined.indexOf(word);\n if (at >= 0) ranges.push([at, at + word.length]);\n }\n }\n for (const [start, end] of ranges) {\n for (let index = indexAt(start); index <= indexAt(end - 1); index++) marked[index] = true;\n }\n const characters = Array.from(text);\n const parts: ReactNode[] = [];\n let run = \"\";\n let runMarked = false;\n characters.forEach((character, index) => {\n const isMarked = marked[index] ?? false;\n if (index > 0 && isMarked !== runMarked) {\n parts.push(\n runMarked ? (\n <mark key={parts.length} className=\"bg-transparent font-medium text-fg\">\n {run}\n </mark>\n ) : (\n run\n ),\n );\n run = \"\";\n }\n run += character;\n runMarked = isMarked;\n });\n if (run) {\n parts.push(\n runMarked ? (\n <mark key={parts.length} className=\"bg-transparent font-medium text-fg\">\n {run}\n </mark>\n ) : (\n run\n ),\n );\n }\n return <>{parts}</>;\n}\n\n/**\n * The server's title search: this workspace, and the person's other workspaces\n * they use most, side by side. Each workspace's matches join the list as they\n * arrive.\n */\nfunction useServerTitleSearch(\n workspaceIds: readonly string[],\n subjectId: string,\n query: string,\n open: boolean,\n) {\n const { client } = useAppContext();\n const [state, setState] = useState<{ query: string; rows: SessionListRow[]; loading: boolean }>({\n query: \"\",\n rows: [],\n loading: false,\n });\n const searchKey = workspaceIds.join(\",\");\n useEffect(() => {\n const trimmed = query.trim();\n if (!open || !trimmed || !searchKey) {\n setState({ query: \"\", rows: [], loading: false });\n return;\n }\n setState((current) => ({ ...current, loading: true }));\n const controller = new AbortController();\n const timer = window.setTimeout(() => {\n const targets = searchKey.split(\",\");\n let pending = targets.length;\n let first = true;\n const settle = (rows: SessionListRow[]) => {\n if (controller.signal.aborted) return;\n pending -= 1;\n const replace = first;\n first = false;\n setState((current) => ({\n query: trimmed,\n rows: replace || current.query !== trimmed ? rows : [...current.rows, ...rows],\n loading: pending > 0,\n }));\n };\n targets.forEach((workspaceId, index) => {\n client\n .listSessionPage(workspaceId, {\n search: trimmed,\n archiveStatus: \"all\",\n // This workspace first and fullest; a few from each of the others.\n limit: index === 0 ? 20 : 6,\n signal: controller.signal,\n })\n .then((page) => {\n const rows = [...(page.pinned ?? []), ...page.sessions];\n rememberChats(subjectId, rows);\n settle(rows);\n })\n .catch(() => {\n // Local results still show; the server search is an addition.\n settle([]);\n });\n });\n }, SERVER_DEBOUNCE_MS);\n return () => {\n window.clearTimeout(timer);\n controller.abort();\n };\n }, [client, searchKey, subjectId, query, open]);\n return state;\n}\n\nexport default function CommandMenu(props: {\n open: boolean;\n /** Opens listing workspaces to switch to. */\n pickWorkspace: boolean;\n onOpenChange: (open: boolean) => void;\n /** Where focus goes back to after a plain close. */\n returnFocus: RefObject<HTMLElement | null>;\n}) {\n const actions = useAppActions();\n if (!actions) return null;\n return (\n <CommandMenuDialog\n {...props}\n env={actions.env}\n run={actions.run}\n chordsFor={actions.chordsFor}\n />\n );\n}\n\nfunction CommandMenuDialog(props: {\n open: boolean;\n pickWorkspace: boolean;\n onOpenChange: (open: boolean) => void;\n returnFocus: RefObject<HTMLElement | null>;\n env: ActionEnv;\n run(action: AppAction, chat?: SessionListRow | null, chord?: Chord): void;\n chordsFor(action: AppAction): Chord[];\n}) {\n const { env, run, chordsFor, onOpenChange } = props;\n const { workspaceId, subjectId, platform, surface, workspaces } = env;\n const directoryVersion = useChatDirectoryVersion(subjectId);\n const [query, setQuery] = useState(\"\");\n const [focusChat, setFocusChat] = useState<ChatRecord | null>(null);\n const [pickingWorkspace, setPickingWorkspace] = useState(props.pickWorkspace);\n const [active, setActive] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const ranAction = useRef(false);\n /** Runs right after the menu has returned focus (see `AppAction.opensDialog`). */\n const afterClose = useRef<(() => void) | null>(null);\n const listId = useId();\n const workspaceNames = useMemo(\n () => new Map(workspaces.map((workspace) => [workspace.id, workspace.name])),\n [workspaces],\n );\n /** Chats the menu may show: this workspace's, and those of other workspaces still open to the person. */\n const reachable = useCallback(\n (id: string) => id === workspaceId || workspaceNames.has(id),\n [workspaceId, workspaceNames],\n );\n // The server searches this workspace and the other workspaces used most recently.\n const searchWorkspaceIds = useMemo(() => {\n void directoryVersion;\n const directory = readChatDirectory(subjectId, workspaceId);\n const used: string[] = [];\n for (const id of directory.recent) {\n const record = directory.rows.get(id);\n if (record && !used.includes(record.workspaceId)) used.push(record.workspaceId);\n }\n const others = [...used, ...workspaces.map((workspace) => workspace.id)].filter(\n (id, index, all) => id !== workspaceId && reachable(id) && all.indexOf(id) === index,\n );\n return [workspaceId, ...others.slice(0, OTHER_WORKSPACES_SEARCHED)];\n // Which workspaces to search changes only when the menu opens.\n }, [props.open, subjectId, workspaceId, workspaces, reachable]); // eslint-disable-line react-hooks/exhaustive-deps\n const server = useServerTitleSearch(\n searchWorkspaceIds,\n subjectId,\n focusChat || pickingWorkspace ? \"\" : query,\n props.open,\n );\n\n // Every open starts fresh.\n useEffect(() => {\n if (!props.open) return;\n setQuery(\"\");\n setFocusChat(null);\n setPickingWorkspace(props.pickWorkspace);\n setActive(0);\n ranAction.current = false;\n afterClose.current = null;\n }, [props.open, props.pickWorkspace]);\n\n const close = useCallback(() => onOpenChange(false), [onOpenChange]);\n\n const runAction = useCallback(\n (action: AppAction, chat: SessionListRow | null, chord?: Chord) => {\n if (action.opensDialog) {\n afterClose.current = () => run(action, action.forChat ? chat : undefined, chord);\n close();\n return;\n }\n ranAction.current = true;\n close();\n run(action, action.forChat ? chat : undefined, chord);\n },\n [close, run],\n );\n\n const openChat = useCallback(\n (record: ChatRecord, newTab: boolean) => {\n ranAction.current = true;\n close();\n if (newTab && surface === \"web\") {\n window.open(env.ops.linkTo(record), \"_blank\", \"noopener\");\n return;\n }\n env.openChat(record.id, record.workspaceId);\n },\n [close, env, surface],\n );\n\n const openWorkspace = useCallback(\n (id: string) => {\n ranAction.current = true;\n close();\n if (id !== workspaceId) env.openWorkspace(id);\n },\n [close, env, workspaceId],\n );\n\n const startPickingWorkspace = useCallback(() => {\n setFocusChat(null);\n setPickingWorkspace(true);\n setQuery(\"\");\n inputRef.current?.focus();\n }, []);\n\n const actionItem = useCallback(\n (action: AppAction, chat: SessionListRow | null, group: string, highlight?: string): Item => ({\n key: `action:${action.id}`,\n group,\n icon: actionIcon(action, chat),\n title: actionTitle(action, env, chat),\n highlight,\n chord: chordsFor(action)[0],\n // Switching workspace lists the workspaces right here.\n run: () =>\n action.id === \"go.switchWorkspace\" ? startPickingWorkspace() : runAction(action, chat),\n }),\n [chordsFor, env, runAction, startPickingWorkspace],\n );\n\n const groups = useMemo<Group[]>(() => {\n void directoryVersion;\n const now = Date.now();\n const directory = readChatDirectory(subjectId, workspaceId);\n const current = env.currentChat;\n const sidebarIds = new Set([...directory.sidebarOrder, ...directory.pinnedOrder]);\n\n const chatItem = (record: ChatRecord, group: string, highlight?: string): Item => ({\n key: `chat:${record.id}`,\n group,\n icon: chatIcon(record),\n title: record.title,\n highlight,\n meta: current?.id === record.id ? \"Open now\" : relativeMeta(record, now),\n workspaceTag:\n record.workspaceId === workspaceId ? undefined : workspaceNames.get(record.workspaceId),\n chat: record,\n status: currentChatStatus(record, sidebarIds, now),\n run: ({ newTab }) => openChat(record, newTab),\n });\n\n const workspaceItem = (choice: WorkspaceChoice, group: string, highlight?: string): Item => ({\n key: `workspace:${choice.id}`,\n group,\n icon: LockIcon,\n // A Personal workspace shows its lock, as in the workspace picker.\n tile: choice.personal ? undefined : (choice.name.trim()[0] ?? \"W\").toUpperCase(),\n title: choice.name,\n highlight,\n meta: choice.id === workspaceId ? \"Current\" : undefined,\n run: () => openWorkspace(choice.id),\n });\n\n // Workspaces to switch to, by organization.\n if (pickingWorkspace) {\n const trimmed = query.trim();\n const organizations = new Set(workspaces.map((choice) => choice.organization));\n const scored = workspaces.flatMap((choice) => {\n if (!trimmed) return [{ choice, rank: 0 }];\n const rank =\n rankLabel(choice.name, trimmed) ??\n (organizations.size > 1 ? rankLabel(choice.organization, trimmed) : null);\n return rank === null ? [] : [{ choice, rank }];\n });\n const realMatch = scored.some((entry) => entry.rank >= LOOSE_MATCH_BELOW);\n const kept = scored.filter(\n (entry) => !trimmed || !realMatch || entry.rank >= LOOSE_MATCH_BELOW,\n );\n if (trimmed) {\n kept.sort((a, b) => b.rank - a.rank);\n return [\n {\n label: \"Workspaces\",\n items: kept.map((entry) => workspaceItem(entry.choice, \"Workspaces\", trimmed)),\n best: 0,\n },\n ];\n }\n const byOrganization = new Map<string, Item[]>();\n for (const { choice } of kept) {\n const label = organizations.size > 1 ? choice.organization : \"Workspaces\";\n const list = byOrganization.get(label) ?? [];\n list.push(workspaceItem(choice, label));\n byOrganization.set(label, list);\n }\n return [...byOrganization].map(([label, items]) => ({ label, items, best: 0 }));\n }\n\n // A chat's own actions (after Tab).\n if (focusChat) {\n // Chats in other workspaces offer what works from here: open and copy link.\n const sameWorkspace = focusChat.workspaceId === workspaceId;\n const row = sameWorkspace\n ? (focusChat.row ?? (current?.id === focusChat.id ? current : null))\n : null;\n const items: Array<{ item: Item; rank: number }> = [];\n const openRank = rankLabel(\"Open\", query);\n if (openRank !== null) {\n items.push({\n rank: openRank + 1,\n item: {\n key: \"open\",\n group: focusChat.title,\n icon: CornerDownLeftIcon,\n title: \"Open\",\n highlight: query,\n run: () => openChat(focusChat, false),\n },\n });\n }\n if (surface === \"web\") {\n const tabRank = rankLabel(\"Open in new tab\", query);\n if (tabRank !== null) {\n items.push({\n rank: tabRank,\n item: {\n key: \"open-tab\",\n group: focusChat.title,\n icon: ArrowUpRightIcon,\n title: \"Open in new tab\",\n highlight: query,\n run: () => openChat(focusChat, true),\n },\n });\n }\n }\n for (const action of appActions()) {\n if (!action.forChat || action.inCommandMenu === false) continue;\n // Copy link needs only the id; the rest need the chat's row.\n const target = row ?? (action.id === \"chat.copyLink\" ? pseudoRow(focusChat) : null);\n if (!target || !action.available(env, target)) continue;\n const rank = rankWithKeywords(actionTitle(action, env, target), action.keywords, query);\n if (rank === null) continue;\n items.push({ rank, item: actionItem(action, target, focusChat.title, query) });\n }\n if (query) items.sort((a, b) => b.rank - a.rank);\n return [{ label: focusChat.title, items: items.map((entry) => entry.item), best: 0 }];\n }\n\n const trimmed = query.trim();\n if (!trimmed) {\n const result: Group[] = [];\n // Chats opened recently come first; the top of the sidebar fills the\n // rest, so a fresh window still offers somewhere to go.\n const recentIds = [...new Set([...directory.recent, ...directory.sidebarOrder])].filter(\n (id) => id !== current?.id,\n );\n const recent = recentIds\n .map((id) => directory.rows.get(id))\n .filter((record): record is ChatRecord =>\n Boolean(record && listable(record) && !record.archived && reachable(record.workspaceId)),\n )\n .slice(0, RECENT_LIMIT);\n if (recent.length > 0) {\n result.push({\n label: \"Recent chats\",\n items: recent.map((record) => chatItem(record, \"Recent chats\")),\n best: 0,\n });\n }\n if (current) {\n const chatActions = appActions().filter(\n (action) =>\n action.forChat &&\n action.inCommandMenu !== false &&\n action.id !== \"chat.find\" &&\n action.available(env, current),\n );\n if (chatActions.length > 0) {\n result.push({\n label: \"This chat\",\n items: chatActions.map((action) => actionItem(action, current, \"This chat\")),\n best: 0,\n });\n }\n }\n const general = appActions().filter(\n (action) =>\n !action.forChat &&\n action.inCommandMenu !== false &&\n action.id !== \"commandMenu.open\" &&\n action.available(env, null),\n );\n if (general.length > 0) {\n result.push({\n label: \"Go to\",\n items: general.map((action) => actionItem(action, null, \"Go to\")),\n best: 0,\n });\n }\n return result;\n }\n\n // Chats: everything the app knows, ranked by title, plus the server's matches.\n const recentIndex = new Map(directory.recent.map((id, index) => [id, index]));\n const serverIds = new Set(server.query === trimmed ? server.rows.map((row) => row.id) : []);\n const scored: Array<{ record: ChatRecord; rank: number; loose: boolean }> = [];\n for (const record of directory.rows.values()) {\n if (!listable(record) || !reachable(record.workspaceId)) continue;\n let rank = rankLabel(record.title, trimmed);\n const loose = rank !== null && rank < LOOSE_MATCH_BELOW;\n // The server matched every word in the title or first message.\n if (rank === null && serverIds.has(record.id)) rank = 50;\n if (rank === null) continue;\n const visited = recentIndex.get(record.id);\n if (visited !== undefined) rank += Math.max(0, 20 - visited);\n if (record.pinned) rank += 5;\n if (record.archived) rank -= 300;\n if (record.workspaceId !== workspaceId) rank -= ELSEWHERE_PENALTY;\n scored.push({ record, rank, loose });\n }\n\n const actionScores: Array<{ item: Item; rank: number; loose: boolean }> = [];\n for (const action of appActions()) {\n if (action.inCommandMenu === false) continue;\n const target = action.forChat ? current : null;\n if (action.forChat && !target) continue;\n if (!action.available(env, target)) continue;\n const rank = rankWithKeywords(actionTitle(action, env, target), action.keywords, trimmed);\n if (rank === null) continue;\n actionScores.push({\n rank,\n loose: rank < LOOSE_MATCH_BELOW,\n item: actionItem(action, target, \"Actions\", trimmed),\n });\n }\n const workspaceScores: Array<{ item: Item; rank: number; loose: boolean }> = [];\n for (const choice of workspaces) {\n if (choice.id === workspaceId) continue;\n const rank = rankLabel(choice.name, trimmed);\n if (rank === null) continue;\n workspaceScores.push({\n rank,\n loose: rank < LOOSE_MATCH_BELOW,\n item: workspaceItem(choice, \"Workspaces\", trimmed),\n });\n }\n // Letters-in-order guesses only help when nothing really matches; next to\n // real matches they are noise (\"pin\" → \"Postgres … investigation\").\n const hasRealMatch =\n scored.some((entry) => !entry.loose) ||\n actionScores.some((entry) => !entry.loose) ||\n workspaceScores.some((entry) => !entry.loose);\n const chats = scored\n .filter((entry) => !hasRealMatch || !entry.loose)\n .sort((a, b) => b.rank - a.rank || b.record.updatedAt - a.record.updatedAt)\n .slice(0, CHAT_RESULT_LIMIT);\n const actionsFound = actionScores\n .filter((entry) => !hasRealMatch || !entry.loose)\n .sort((a, b) => b.rank - a.rank)\n .slice(0, ACTION_RESULT_LIMIT);\n const workspacesFound = workspaceScores\n .filter((entry) => !hasRealMatch || !entry.loose)\n .sort((a, b) => b.rank - a.rank)\n .slice(0, WORKSPACE_RESULT_LIMIT);\n\n const result: Group[] = [];\n if (chats.length > 0) {\n result.push({\n label: \"Chats\",\n items: chats.map((entry) => chatItem(entry.record, \"Chats\", trimmed)),\n best: chats[0]!.rank,\n });\n }\n if (actionsFound.length > 0) {\n result.push({\n label: \"Actions\",\n items: actionsFound.map((entry) => entry.item),\n best: actionsFound[0]!.rank,\n });\n }\n if (workspacesFound.length > 0) {\n result.push({\n label: \"Workspaces\",\n items: workspacesFound.map((entry) => entry.item),\n // Chats and actions first on a tie: a workspace is a bigger jump.\n best: workspacesFound[0]!.rank - 1,\n });\n }\n // A clearly better action match (\"new\" → New chat) comes before chats.\n result.sort((a, b) => b.best - a.best);\n result.push({\n label: \"Messages\",\n best: -Infinity,\n items: [\n {\n key: \"search-messages\",\n group: \"Messages\",\n icon: TextSearchIcon,\n title: `Search messages for “${trimmed}”`,\n run: () => {\n afterClose.current = () => env.searchMessages(trimmed);\n close();\n },\n },\n ],\n });\n return result;\n }, [\n actionItem,\n close,\n directoryVersion,\n env,\n focusChat,\n openChat,\n openWorkspace,\n pickingWorkspace,\n query,\n reachable,\n server.query,\n server.rows,\n subjectId,\n surface,\n workspaceId,\n workspaceNames,\n workspaces,\n ]);\n\n const items = useMemo(() => groups.flatMap((group) => group.items), [groups]);\n const listedChatIds = useMemo(\n () => items.flatMap((item) => (item.chat ? [item.chat.id] : [])),\n [items],\n );\n useChatStatusRefresh({ subjectId, workspaceId, ids: listedChatIds, active: props.open });\n const activeIndex = items.length === 0 ? -1 : Math.min(active, items.length - 1);\n const activeItem = activeIndex >= 0 ? items[activeIndex] : undefined;\n const searching = Boolean(query.trim()) && !focusChat && !pickingWorkspace && server.loading;\n\n // Typing starts at the best match; the workspace list starts at the current workspace's neighbour.\n useEffect(() => {\n if (pickingWorkspace && !query) {\n const index = workspaces.findIndex((choice) => choice.id === workspaceId);\n setActive(index >= 0 && workspaces.length > 1 ? (index + 1) % workspaces.length : 0);\n return;\n }\n setActive(0);\n }, [query, focusChat, pickingWorkspace, workspaces, workspaceId]);\n\n // Keep the highlighted row in view without scrolling the page.\n useLayoutEffect(() => {\n if (!activeItem) return;\n const element = listRef.current?.querySelector<HTMLElement>(\n `[data-item-key=\"${CSS.escape(activeItem.key)}\"]`,\n );\n element?.scrollIntoView({ block: \"nearest\" });\n }, [activeItem]);\n\n const enterChat = useCallback((record: ChatRecord) => {\n setFocusChat(record);\n setQuery(\"\");\n inputRef.current?.focus();\n }, []);\n const leaveChat = useCallback(() => {\n setFocusChat(null);\n setPickingWorkspace(false);\n setQuery(\"\");\n }, []);\n\n const onKeyDown = useCallback(\n (event: ReactKeyboardEvent<HTMLDivElement>) => {\n if (event.nativeEvent.isComposing) return;\n const count = items.length;\n const mod = platform === \"mac\" ? event.metaKey : event.ctrlKey;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowUp\": {\n if (event.altKey || mod) break;\n event.preventDefault();\n if (count === 0) return;\n const step = event.key === \"ArrowDown\" ? 1 : -1;\n setActive((current) => (Math.min(current, count - 1) + step + count) % count);\n return;\n }\n case \"PageDown\":\n case \"PageUp\": {\n event.preventDefault();\n if (count === 0) return;\n const step = event.key === \"PageDown\" ? 5 : -5;\n setActive((current) => Math.max(0, Math.min(count - 1, current + step)));\n return;\n }\n case \"Home\":\n case \"End\": {\n // Inside the field these move the caret, unless the field is empty.\n if (query) break;\n event.preventDefault();\n setActive(event.key === \"Home\" ? 0 : Math.max(0, count - 1));\n return;\n }\n case \"Enter\": {\n event.preventDefault();\n activeItem?.run({ newTab: mod });\n return;\n }\n case \"Tab\": {\n event.preventDefault();\n if (event.shiftKey) {\n if (focusChat || pickingWorkspace) leaveChat();\n return;\n }\n if (!focusChat && activeItem?.chat) enterChat(activeItem.chat);\n return;\n }\n case \"Backspace\": {\n if ((focusChat || pickingWorkspace) && !query) {\n event.preventDefault();\n leaveChat();\n }\n return;\n }\n default:\n break;\n }\n // A chat action's chord acts on the highlighted chat, as in Linear.\n const chatRecord = focusChat ?? activeItem?.chat;\n if (!chatRecord) return;\n const sameWorkspace = chatRecord.workspaceId === workspaceId;\n for (const action of appActions()) {\n if (!action.forChat) continue;\n const chord = chordsFor(action).find((candidate) =>\n matchesChord(event.nativeEvent, candidate, platform),\n );\n if (!chord) continue;\n const row =\n (sameWorkspace\n ? (chatRecord.row ?? (env.currentChat?.id === chatRecord.id ? env.currentChat : null))\n : null) ?? (action.id === \"chat.copyLink\" ? pseudoRow(chatRecord) : null);\n event.preventDefault();\n event.stopPropagation();\n if (row && action.available(env, row)) runAction(action, row, chord);\n return;\n }\n },\n [\n activeItem,\n chordsFor,\n enterChat,\n env,\n focusChat,\n items.length,\n leaveChat,\n pickingWorkspace,\n platform,\n query,\n runAction,\n workspaceId,\n ],\n );\n\n const placeholder = focusChat\n ? \"Search actions…\"\n : pickingWorkspace\n ? \"Switch to workspace…\"\n : \"Search chats or run an action…\";\n const optionId = (item: Item) => `${listId}-${item.key.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n\n return (\n <DialogPrimitive.Root open={props.open} onOpenChange={onOpenChange}>\n <DialogPortal>\n <DialogOverlay className=\"bg-black/25 dark:bg-black/45\" />\n <DialogPrimitive.Content\n data-og-command-menu=\"\"\n aria-label=\"Command menu\"\n aria-describedby={undefined}\n onOpenAutoFocus={(event) => {\n event.preventDefault();\n inputRef.current?.focus();\n }}\n onCloseAutoFocus={(event) => {\n // An action moves focus where it belongs (the new chat's composer,\n // the title being renamed); only a plain close returns focus.\n if (ranAction.current) {\n event.preventDefault();\n return;\n }\n const target = props.returnFocus.current;\n if (target?.isConnected) {\n event.preventDefault();\n target.focus({ preventScroll: true });\n }\n const next = afterClose.current;\n afterClose.current = null;\n next?.();\n }}\n onEscapeKeyDown={(event) => {\n // Esc steps back out of a chat's actions, or the workspace list\n // reached from the menu, before it closes the menu.\n if (!focusChat && !(pickingWorkspace && !props.pickWorkspace)) return;\n event.preventDefault();\n leaveChat();\n }}\n onKeyDown={onKeyDown}\n className={cn(\n \"fixed top-[12dvh] left-1/2 z-50 flex max-h-[min(560px,76dvh)] w-[calc(100vw-1.5rem)] max-w-[640px] -translate-x-1/2 flex-col overflow-hidden\",\n \"rounded-2xl border border-border bg-surface text-fg shadow-og-lg outline-hidden\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-98\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-98\",\n \"duration-[120ms] max-sm:top-3\",\n )}\n >\n <DialogPrimitive.Title className=\"sr-only\">Command menu</DialogPrimitive.Title>\n <div className=\"flex min-h-13 shrink-0 items-center gap-2.5 border-b border-border px-4\">\n <SearchIcon aria-hidden=\"true\" className=\"size-4 shrink-0 text-fg-muted\" />\n {focusChat ? (\n <button\n type=\"button\"\n onClick={leaveChat}\n title=\"Back to all results\"\n className=\"inline-flex max-w-[45%] shrink-0 items-center gap-1 rounded-full bg-hover py-0.5 pr-1.5 pl-2.5 text-xs font-medium text-fg outline-hidden hover:bg-selection focus-visible:outline-2 focus-visible:outline-ring/55\"\n >\n <span className=\"truncate\">{focusChat.title}</span>\n <ChevronRightIcon aria-hidden=\"true\" className=\"size-3.5 text-fg-muted\" />\n </button>\n ) : pickingWorkspace ? (\n <button\n type=\"button\"\n onClick={leaveChat}\n title=\"Back to all results\"\n className=\"inline-flex shrink-0 items-center gap-1 rounded-full bg-hover py-0.5 pr-1.5 pl-2.5 text-xs font-medium text-fg outline-hidden hover:bg-selection focus-visible:outline-2 focus-visible:outline-ring/55\"\n >\n Workspaces\n <ChevronRightIcon aria-hidden=\"true\" className=\"size-3.5 text-fg-muted\" />\n </button>\n ) : null}\n <input\n ref={inputRef}\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeItem ? optionId(activeItem) : undefined}\n aria-label={\n focusChat\n ? `Actions for ${focusChat.title}`\n : pickingWorkspace\n ? \"Search workspaces\"\n : \"Search chats and actions\"\n }\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n enterKeyHint=\"go\"\n value={query}\n maxLength={200}\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n // The whole menu is the focus context; a ring on the field adds noise.\n style={{ outline: \"none\" }}\n className=\"h-13 min-w-0 flex-1 bg-transparent text-[15px] text-fg outline-hidden placeholder:text-fg-subtle\"\n />\n {searching ? (\n <span\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 animate-spin rounded-full border-[1.5px] border-fg-subtle/40 border-t-fg-muted\"\n />\n ) : null}\n </div>\n <div\n ref={listRef}\n id={listId}\n role=\"listbox\"\n aria-label={focusChat ? \"Chat actions\" : pickingWorkspace ? \"Workspaces\" : \"Results\"}\n className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain p-1.5\"\n >\n {items.length === 0 ? (\n <p className=\"px-2.5 py-6 text-center text-sm text-fg-muted\">\n {searching ? \"Searching…\" : \"No matches\"}\n </p>\n ) : (\n groups.map((group) =>\n group.items.length === 0 ? null : (\n <div key={group.label} role=\"group\" aria-label={group.label}>\n {groups.length > 1 || !focusChat ? (\n <div className=\"truncate px-2.5 pt-2 pb-1 text-xs leading-4.5 font-medium text-fg-muted\">\n {group.label}\n </div>\n ) : null}\n {group.items.map((item) => {\n const index = items.indexOf(item);\n const selected = index === activeIndex;\n const Icon = item.icon;\n return (\n <div\n key={item.key}\n id={optionId(item)}\n data-item-key={item.key}\n role=\"option\"\n aria-selected={selected}\n onPointerMove={() => {\n if (!selected) setActive(index);\n }}\n onPointerDown={(event) => event.preventDefault()}\n onClick={(event) =>\n item.run({ newTab: platform === \"mac\" ? event.metaKey : event.ctrlKey })\n }\n className={cn(\n \"relative flex min-h-9 w-full min-w-0 cursor-default items-center gap-2.5 rounded-[10px] px-2.5 py-1.5 text-sm text-fg-label select-none pointer-coarse:min-h-11\",\n selected ? \"bg-hover text-fg\" : null,\n )}\n >\n {item.tile ? (\n <span\n aria-hidden=\"true\"\n className=\"flex size-4 shrink-0 items-center justify-center rounded-[4px] bg-surface-3 text-2xs font-semibold text-fg-muted\"\n >\n {item.tile}\n </span>\n ) : (\n <Icon\n aria-hidden=\"true\"\n className={cn(\n \"size-4 shrink-0\",\n selected ? \"text-fg\" : \"text-fg-muted\",\n )}\n />\n )}\n <span className=\"min-w-0 flex-1 truncate\">\n <Highlighted text={item.title} query={item.highlight} />\n </span>\n {item.workspaceTag ? <WorkspaceTag name={item.workspaceTag} /> : null}\n <ChatStatusMarks status={item.status ?? null} />\n {item.meta ? (\n <span className=\"shrink-0 text-xs text-fg-muted tabular-nums\">\n {item.meta}\n </span>\n ) : null}\n {item.chord ? (\n // Touch screens have no keys to press.\n <Keycaps\n chord={item.chord}\n platform={platform}\n className=\"pointer-coarse:hidden\"\n />\n ) : null}\n </div>\n );\n })}\n </div>\n ),\n )\n )}\n </div>\n <div className=\"hidden shrink-0 items-center gap-4 border-t border-border px-4 py-2 text-xs text-fg-muted pointer-fine:flex\">\n <FooterHint\n keys={[{ code: \"ArrowUp\" }, { code: \"ArrowDown\" }]}\n label=\"Move\"\n platform={platform}\n />\n <FooterHint\n keys={[{ code: \"Enter\" }]}\n label={pickingWorkspace ? \"Switch\" : \"Open\"}\n platform={platform}\n />\n {focusChat || pickingWorkspace ? (\n <FooterHint keys={[{ code: \"Escape\" }]} label=\"Back\" platform={platform} />\n ) : (\n <FooterHint keys={[{ code: \"Tab\" }]} label=\"Chat actions\" platform={platform} />\n )}\n {surface === \"web\" && !focusChat && !pickingWorkspace ? (\n <FooterHint\n keys={[{ code: \"Enter\", mod: true }]}\n label=\"New tab\"\n platform={platform}\n />\n ) : null}\n <span className=\"ml-auto inline-flex items-center gap-1.5\">\n <Keycaps chord={{ code: \"Slash\", mod: true }} platform={platform} />\n All shortcuts\n </span>\n </div>\n </DialogPrimitive.Content>\n </DialogPortal>\n </DialogPrimitive.Root>\n );\n}\n\nfunction FooterHint(props: { keys: Chord[]; label: string; platform: ActionEnv[\"platform\"] }) {\n return (\n <span className=\"inline-flex items-center gap-1.5\">\n <span className=\"inline-flex items-center gap-0.5\">\n {props.keys.map((chord) => (\n <Keycaps key={chord.code} chord={chord} platform={props.platform} />\n ))}\n </span>\n {props.label}\n </span>\n );\n}\n\n/** Enough of a chat row to copy its link when only a recent-chats record is known. */\nfunction pseudoRow(record: ChatRecord): SessionListRow {\n return { id: record.id, workspaceId: record.workspaceId } as SessionListRow;\n}\n"],"mappings":"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","names":["trimmed","scored","items","result"]}
|