@openhands/agent-canvas 1.0.0-alpha.7 → 1.0.0-alpha.8
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/README.md +9 -18
- package/bin/agent-canvas.mjs +27 -1
- package/build/assets/{QueryClientProvider-DITRCGAK.js → QueryClientProvider-B7kl84Kj.js} +1 -1
- package/build/assets/{Trans-D43bd3yR.js → Trans-1j65oy9O.js} +1 -1
- package/build/assets/{acp-providers-SCPK1BIU.js → acp-providers-DauuOsW9.js} +1 -1
- package/build/assets/{acp-route-guard-IWlFmS6x.js → acp-route-guard-CQTmeJwM.js} +1 -1
- package/build/assets/{active-backend-context-CkP3ZEJs.js → active-backend-context-TVbjnvmP.js} +1 -1
- package/build/assets/add-backend-modal-KMmPQNZU.js +1 -0
- package/build/assets/{agent-server-client-options-8OJSXbm8.js → agent-server-client-options-DT2GP6VJ.js} +1 -1
- package/build/assets/{agent-server-compatibility-DvKtnXHw.js → agent-server-compatibility-2aOx5iWd.js} +1 -1
- package/build/assets/{agent-server-conversation-service.api-BdEre_71.js → agent-server-conversation-service.api-DSl9G5UR.js} +3 -3
- package/build/assets/{agent-settings-DdisD2Xx.js → agent-settings-B247S9G3.js} +2 -2
- package/build/assets/{alert-banner-CvTYN73l.js → alert-banner-BWoqueRw.js} +1 -1
- package/build/assets/{analytics-consent-form-modal-BKgT9i2w.js → analytics-consent-form-modal-C7sXfxRh.js} +1 -1
- package/build/assets/{app-settings-DcYXtxGP.js → app-settings-BVeSaty9.js} +1 -1
- package/build/assets/{automation-detail-D7GEU0vR.js → automation-detail-g5-RZ0da.js} +1 -1
- package/build/assets/{automations-list-CkVNsgzm.js → automations-list-DHoq_0MM.js} +1 -1
- package/build/assets/{backend-form-modal-KudhWUX8.js → backend-form-modal-K6IMCr3p.js} +1 -1
- package/build/assets/{backend-synced-settings-badge-BFy2HylT.js → backend-synced-settings-badge-nAfiUWvM.js} +1 -1
- package/build/assets/{base-modal-B4HvlFHE.js → base-modal-CQRvRHu1.js} +1 -1
- package/build/assets/{brand-button-8fVVei4i.js → brand-button-C2nEKopC.js} +1 -1
- package/build/assets/{browser-vYpdU3CR.js → browser-DKG63inJ.js} +1 -1
- package/build/assets/{browser-tab-DTM6RyoV.js → browser-tab-B_BuTvrO.js} +1 -1
- package/build/assets/{checkmark-BcvXE9bf.js → checkmark-BJJrZUF8.js} +1 -1
- package/build/assets/{chevron-left-small-BqSkXTeq.js → chevron-left-small-CSh-sE9L.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-DRvuu-RD.js → circle-plus-check-toggle-qs8Va1cC.js} +1 -1
- package/build/assets/{clock-DfoVUZVq.js → clock-ZR4Kn-_Y.js} +1 -1
- package/build/assets/{close-SnIy2eLD.js → close-BdmyeRqS.js} +1 -1
- package/build/assets/{combobox-caret-BMsz5mQX.js → combobox-caret-B53O9Hsq.js} +1 -1
- package/build/assets/{condenser-settings-DduLQcpV.js → condenser-settings-A35V3yng.js} +1 -1
- package/build/assets/{confirmation-modal-B-DOYMUH.js → confirmation-modal-C9-La0h3.js} +1 -1
- package/build/assets/{context-menu-list-item-DzjPB8aC.js → context-menu-list-item-Buu9nc0q.js} +1 -1
- package/build/assets/conversation-BD5WemJI.js +19 -0
- package/build/assets/conversation-C47K62n8.js +1 -0
- package/build/assets/conversation-panel-Dn-S56Gk.js +1 -0
- package/build/assets/{conversation-service.api-YTGTw0pz.js → conversation-service.api-C8pYCyV6.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-BtFDbyTe.js → conversation-tab-empty-state-D8dNvo-V.js} +1 -1
- package/build/assets/{conversation-websocket-context-DulnrIHh.js → conversation-websocket-context-Ywrxd_9p.js} +1 -1
- package/build/assets/{copy-BxgbrjDT.js → copy-C7Ti2d8C.js} +1 -1
- package/build/assets/{custom-toast-handlers-BYxhSr3t.js → custom-toast-handlers-BOc3qeQ7.js} +1 -1
- package/build/assets/declaration-D378OjpZ.js +1 -0
- package/build/assets/{device-verify-CTbXX9CQ.js → device-verify-CMusn8nX.js} +1 -1
- package/build/assets/edit-automation-modal-Dnjxbjn7.js +1 -0
- package/build/assets/{ellipsis-button-BoU2-xlG.js → ellipsis-button-ugUATsNo.js} +1 -1
- package/build/assets/{entry.client-DU7-q4ZU.js → entry.client-D9uR9Blz.js} +2 -2
- package/build/assets/{enum-filter-dropdown-BJt-NplD.js → enum-filter-dropdown-1vpOGySB.js} +1 -1
- package/build/assets/{environment-switch-overlay-DQ1n6Iu6.js → environment-switch-overlay-CTCTQikP.js} +1 -1
- package/build/assets/{extensions-hub-BW1FAKFJ.js → extensions-hub-BSUseHVF.js} +1 -1
- package/build/assets/{extensions-navigation-CbPMhSML.js → extensions-navigation-CT1kc1u_.js} +1 -1
- package/build/assets/{files-tab-CbJ4s7Ik.js → files-tab-B3A1NDlZ.js} +1 -1
- package/build/assets/{folder-CerIk8uG.js → folder-0WSMImNX.js} +1 -1
- package/build/assets/git-control-bar-branch-button-CcIpmyfM.js +27 -0
- package/build/assets/{git-provider-icon-D8RE4unY.js → git-provider-icon-DYE9n7fs.js} +1 -1
- package/build/assets/{home-DR11ejqB.js → home-dIzxi5Dd.js} +1 -1
- package/build/assets/{i18n-DkYgs32x.js → i18n-DjAGhTis.js} +1 -1
- package/build/assets/install-server-modal-z5VaHeXd.js +1 -0
- package/build/assets/{launch-DKCU9uJH.js → launch-hZ0ifhcV.js} +1 -1
- package/build/assets/{lesson-plan-CmkRbe6Z.js → lesson-plan-DRYG5SLI.js} +1 -1
- package/build/assets/{link-external-CvxB0BmI.js → link-external-Df8J52xI.js} +1 -1
- package/build/assets/{llm-client-BpIfxETv.js → llm-client-ChQzg4wX.js} +1 -1
- package/build/assets/llm-settings-2036m7Wt.js +1 -0
- package/build/assets/{llm-settings-BOJC4vD-.js → llm-settings-CcHqGOYL.js} +1 -1
- package/build/assets/{loading-spinner-91b5FiMQ.js → loading-spinner-C04FGh14.js} +1 -1
- package/build/assets/{manage-backends-modal-DqpzcxdI.js → manage-backends-modal-rYeyGx7j.js} +1 -1
- package/build/assets/{manage-workspaces-modal-eG6XgAvw.js → manage-workspaces-modal-C5EuW8m1.js} +1 -1
- package/build/assets/manifest-97e839da.js +1 -0
- package/build/assets/{markdown-renderer-wZnLDbA1.js → markdown-renderer-CEX4Becj.js} +1 -1
- package/build/assets/mcp-C06YssEI.js +9 -0
- package/build/assets/messages-T2ewVkbp.js +36 -0
- package/build/assets/{modal-backdrop-B04pVYAD.js → modal-backdrop-DTYGVmOR.js} +1 -1
- package/build/assets/{modal-body-CgUoFQA1.js → modal-body-YElmM1dV.js} +1 -1
- package/build/assets/{modal-close-button-SM_WXzDY.js → modal-close-button-C_GpQt9F.js} +1 -1
- package/build/assets/{model-selector-7id-Uirf.js → model-selector-DeMmw-Xa.js} +1 -1
- package/build/assets/{navigation-context-BFjstyH6.js → navigation-context-DeIPtGPp.js} +1 -1
- package/build/assets/{navigation-link-DFQ7YcWq.js → navigation-link-C9JD4PYD.js} +1 -1
- package/build/assets/{openhands-logo-DkDp75rC.js → openhands-logo-CI5Fhn1W.js} +1 -1
- package/build/assets/{option-service.api-DN0ZcGjw.js → option-service.api-DsI1UW7N.js} +1 -1
- package/build/assets/{organization-service.api-Ct2dZF8M.js → organization-service.api-COwMPFg5.js} +1 -1
- package/build/assets/{path-utils-D1ZtqFC7.js → path-utils-CqJboYxo.js} +1 -1
- package/build/assets/{plan-components-gOm-daR3.js → plan-components-DEjMuDDG.js} +1 -1
- package/build/assets/{planner-tab-yubfN-6U.js → planner-tab-BrntFmb1.js} +1 -1
- package/build/assets/{profiles-client-D4twHRVf.js → profiles-client-BGkKEV9j.js} +1 -1
- package/build/assets/{providers-C2T07PM3.js → providers-DXvCAN_u.js} +1 -1
- package/build/assets/{proxy-BMZyC45G.js → proxy-CurRmrqf.js} +1 -1
- package/build/assets/{query-client-config-CiK0GJJO.js → query-client-config-Ba7qAAoO.js} +1 -1
- package/build/assets/recommended-automations-launcher-BI9NhG8Y.js +52 -0
- package/build/assets/root-BS1Td78t.js +2 -0
- package/build/assets/root-DHeCXo9N.css +1 -0
- package/build/assets/{root-layout-B4QioBS6.js → root-layout-BLjAEgle.js} +2 -2
- package/build/assets/{sdk-section-page-03k88tIR.js → sdk-section-page-CJW0G04-.js} +1 -1
- package/build/assets/{sdk-settings-schema-BY8dOy3a.js → sdk-settings-schema-QBYH-ONX.js} +1 -1
- package/build/assets/{search-BCAF9EDS.js → search-Cq_cFrDt.js} +1 -1
- package/build/assets/{secrets-service-Z3qtRb_G.js → secrets-service-Bwd5DeUs.js} +1 -1
- package/build/assets/{secrets-settings-BnlByuMZ.js → secrets-settings-MLXqOtX2.js} +1 -1
- package/build/assets/{server-client-CG1zHqph.js → server-client-C3mC8Hl3.js} +1 -1
- package/build/assets/{settings-DyzGLF_d.js → settings-D7E2U5tK.js} +1 -1
- package/build/assets/{settings-client-CkXDJwIY.js → settings-client-CwjfwoiB.js} +1 -1
- package/build/assets/{settings-dropdown-input-CAQWQgx-.js → settings-dropdown-input-VwAXNrOb.js} +1 -1
- package/build/assets/{settings-gear-D4ZkEDGb.js → settings-gear-BJwWR1ej.js} +1 -1
- package/build/assets/{settings-index-KtTw49xL.js → settings-index-J-3BNR0W.js} +1 -1
- package/build/assets/{settings-input-BWCZt9g2.js → settings-input-DBywAnA7.js} +1 -1
- package/build/assets/{settings-list-classes-xMleGkTC.js → settings-list-classes-BOS092DR.js} +1 -1
- package/build/assets/{settings-modal-Cv2YWSUY.js → settings-modal-B8vgWDTe.js} +1 -1
- package/build/assets/{settings-section-header-context-1wfkgjZZ.js → settings-section-header-context-32x6WTyL.js} +1 -1
- package/build/assets/settings-service.api-FvJGK45W.js +1 -0
- package/build/assets/{settings-switch-CGap2LtG.js → settings-switch-DTKmHC8F.js} +1 -1
- package/build/assets/{settings-utils-BBozxqqi.js → settings-utils-BsvSU3OM.js} +1 -1
- package/build/assets/{shared-conversation-DQlzwdpo.js → shared-conversation-a0QV8o99.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-DXplko7u.js → sidebar-mobile-menu-toggle-DTUNI1WQ.js} +1 -1
- package/build/assets/{sidebar-nav-link-B4h8naZ7.js → sidebar-nav-link-CnWoZcwc.js} +1 -1
- package/build/assets/{skill-card-pill-row-D0oTWx-a.js → skill-card-pill-row-tZ599jli.js} +1 -1
- package/build/assets/{skills-BN8atjgW.js → skills-ZyAO5dyK.js} +1 -1
- package/build/assets/{skills-plugins-BTnp7QcQ.js → skills-plugins-BSRz041I.js} +1 -1
- package/build/assets/{skills-settings-CbOQvzkR.js → skills-settings-DOnMn9q1.js} +2 -2
- package/build/assets/{status-DDL-ipIP.js → status-CsatcFbK.js} +1 -1
- package/build/assets/{styled-tooltip-Awq4HMw3.js → styled-tooltip-CS3mB_1X.js} +1 -1
- package/build/assets/{switch-skeleton-Bv21RGWd.js → switch-skeleton-C-CfhYYV.js} +1 -1
- package/build/assets/{task-list-tab-B45ktzHM.js → task-list-tab-Day9nhRT.js} +1 -1
- package/build/assets/{terminal-DGuR4559.js → terminal-LNa-iU5c.js} +1 -1
- package/build/assets/{terminal-D5pzR9Ru.js → terminal-ro4SNjUU.js} +1 -1
- package/build/assets/{toggle-switch-gj6T-wsU.js → toggle-switch-k-IZCDbt.js} +1 -1
- package/build/assets/{typography-BbaUAC4V.js → typography-vVUMoNUg.js} +1 -1
- package/build/assets/{u-check-circle-DHGiAi-w.js → u-check-circle-DplbarS5.js} +1 -1
- package/build/assets/{u-check-circle-half-BPcWtWwv.js → u-check-circle-half-yDuiSZHC.js} +1 -1
- package/build/assets/{u-circuit-B_nK9hOu.js → u-circuit-C9tYkpeK.js} +1 -1
- package/build/assets/{u-edit-BPFJBd34.js → u-edit-KAUlufD8.js} +1 -1
- package/build/assets/{use-active-conversation-Bu5J9iLy.js → use-active-conversation-D15D9GgR.js} +1 -1
- package/build/assets/{use-agent-settings-schema-BbtOsR7P.js → use-agent-settings-schema-Bvp5UzV8.js} +1 -1
- package/build/assets/{use-agent-state-DN9Nc5pP.js → use-agent-state-DE5dlEXJ.js} +1 -1
- package/build/assets/{use-cloud-current-user-id-B_rMUiu8.js → use-cloud-current-user-id-DWVar4st.js} +1 -1
- package/build/assets/{use-config-Bcz2JL2t.js → use-config-BSu_53GL.js} +1 -1
- package/build/assets/{use-conversation-id-BOaaZahn.js → use-conversation-id-DajhCn2A.js} +1 -1
- package/build/assets/{use-create-conversation-BWFA_FId.js → use-create-conversation-DW7AGgLA.js} +1 -1
- package/build/assets/{use-handle-plan-click-CgrCGmT1.js → use-handle-plan-click-DpgEQDAV.js} +1 -1
- package/build/assets/use-is-authed-hXC8vxgT.js +1 -0
- package/build/assets/{use-is-creating-conversation-DhoM7UAB.js → use-is-creating-conversation-DhDeeWfA.js} +1 -1
- package/build/assets/{use-launch-skill-in-chat-DOyQsXFO.js → use-launch-skill-in-chat-DVGPFrbI.js} +1 -1
- package/build/assets/{use-llm-profiles-CAIzHJDX.js → use-llm-profiles-D3-KXwQ0.js} +1 -1
- package/build/assets/use-runtime-is-ready-XFbT16BD.js +1 -0
- package/build/assets/{use-save-settings-5m3w89Ph.js → use-save-settings-CEEKSTWG.js} +1 -1
- package/build/assets/{use-settings-DzG0C3vO.js → use-settings-DQ7Oo1Hj.js} +1 -1
- package/build/assets/{use-settings-nav-items-BIsKeX52.js → use-settings-nav-items-YmrXrjn9.js} +2 -2
- package/build/assets/{use-skills-Cn-78xP1.js → use-skills-Xe0vjPMt.js} +1 -1
- package/build/assets/{use-unified-vscode-url-C5iI-Z5A.js → use-unified-vscode-url-BOsIOd-b.js} +1 -1
- package/build/assets/use-user-conversation-Mc0mQgkl.js +1 -0
- package/build/assets/{useMutation-CRJwk4cR.js → useMutation-B4OUESdw.js} +1 -1
- package/build/assets/{useTranslation-01pF7z10.js → useTranslation-CpIcQBq6.js} +1 -1
- package/build/assets/{utils-Czcl6buL.js → utils-D-HX7JCe.js} +1 -1
- package/build/assets/{vendor~conversation-panel~conversation-CbjvWBSu.js → vendor~conversation-panel~conversation-BlCIz9XQ.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CofhIDpd.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Ds9quNZ9.js} +1 -1
- package/build/assets/vendor~home~mcp~automations-list-C5PoHCy6.js +1 -0
- package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-BQPOygpY.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-CGlZoBKa.js} +1 -1
- package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-CyYIBiBk.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-DE11mPxp.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-CuGq_cxH.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-8b8V5bfO.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-CFpDeb9o.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-Dy7L6fMG.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-C1p8-pMr.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-D40EXhZx.js} +1 -1
- package/build/assets/vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-CHrEOFl6.js +48 -0
- package/build/assets/{vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~kyz9p27j-DlKA6SoO.js → vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~kyz9p27j-CyUbhpbm.js} +1 -1
- package/build/assets/{verification-settings-DbziMp4K.js → verification-settings-BtlTiHP8.js} +1 -1
- package/build/assets/{vscode-tab-BVhQR2rt.js → vscode-tab-C0ShhiSU.js} +1 -1
- package/build/assets/{waiting-for-runtime-message-JotSOBdC.js → waiting-for-runtime-message-DWPl_Yby.js} +1 -1
- package/build/assets/{x-mark-CZ57VvRX.js → x-mark-CWI0f9yI.js} +1 -1
- package/build/favicon.svg +1 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +8 -0
- package/build/locales/ca/openhands.json +8 -0
- package/build/locales/de/openhands.json +8 -0
- package/build/locales/en/openhands.json +8 -0
- package/build/locales/es/openhands.json +8 -0
- package/build/locales/fr/openhands.json +8 -0
- package/build/locales/it/openhands.json +8 -0
- package/build/locales/ja/openhands.json +8 -0
- package/build/locales/ko-KR/openhands.json +8 -0
- package/build/locales/no/openhands.json +8 -0
- package/build/locales/pt/openhands.json +8 -0
- package/build/locales/tr/openhands.json +8 -0
- package/build/locales/uk/openhands.json +8 -0
- package/build/locales/zh-CN/openhands.json +8 -0
- package/build/locales/zh-TW/openhands.json +8 -0
- package/config/defaults.json +1 -1
- package/dist/api/agent-server-config.cjs +1 -1
- package/dist/api/agent-server-config.cjs.map +1 -1
- package/dist/api/agent-server-config.d.ts +1 -1
- package/dist/api/agent-server-config.js +1 -1
- package/dist/api/agent-server-config.js.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +12 -0
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +4 -0
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/mcp-service/mcp-service.api.cjs +2 -0
- package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -0
- package/dist/api/mcp-service/mcp-service.api.d.ts +6 -0
- package/dist/api/mcp-service/mcp-service.api.js +36 -0
- package/dist/api/mcp-service/mcp-service.api.js.map +1 -0
- package/dist/api/settings-service/settings-service.api.cjs +1 -1
- package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
- package/dist/api/settings-service/settings-service.api.d.ts +1 -0
- package/dist/api/settings-service/settings-service.api.js +59 -41
- package/dist/api/settings-service/settings-service.api.js.map +1 -1
- package/dist/components/features/automations/detail/activity-log-item.d.ts +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.d.ts +1 -1
- package/dist/components/features/chat/change-agent-button.cjs +1 -1
- package/dist/components/features/chat/change-agent-button.cjs.map +1 -1
- package/dist/components/features/chat/change-agent-button.js +65 -59
- package/dist/components/features/chat/change-agent-button.js.map +1 -1
- package/dist/components/features/chat/chat-interface.cjs +2 -2
- package/dist/components/features/chat/chat-interface.cjs.map +1 -1
- package/dist/components/features/chat/chat-interface.js +15 -14
- package/dist/components/features/chat/chat-interface.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-actions.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-actions.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-actions.js +127 -149
- package/dist/components/features/chat/components/chat-input-actions.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-model.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-model.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-model.d.ts +10 -0
- package/dist/components/features/chat/components/chat-input-model.js +95 -60
- package/dist/components/features/chat/components/chat-input-model.js.map +1 -1
- package/dist/components/features/chat/git-control-bar.cjs +1 -1
- package/dist/components/features/chat/git-control-bar.cjs.map +1 -1
- package/dist/components/features/chat/git-control-bar.js +60 -59
- package/dist/components/features/chat/git-control-bar.js.map +1 -1
- package/dist/components/features/conversation/conversation-name-with-status.cjs +1 -1
- package/dist/components/features/conversation/conversation-name-with-status.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-name-with-status.js +2 -2
- package/dist/components/features/conversation/conversation-name-with-status.js.map +1 -1
- package/dist/components/features/conversation/conversation-name.cjs +1 -1
- package/dist/components/features/conversation/conversation-name.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-name.js +3 -3
- package/dist/components/features/conversation/conversation-name.js.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +16 -16
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
- package/dist/components/features/mcp-logo-badge.cjs +1 -1
- package/dist/components/features/mcp-logo-badge.cjs.map +1 -1
- package/dist/components/features/mcp-logo-badge.d.ts +2 -2
- package/dist/components/features/mcp-logo-badge.js +1 -1
- package/dist/components/features/mcp-logo-badge.js.map +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.js +64 -41
- package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
- package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
- package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
- package/dist/components/features/mcp-page/install-server-modal.d.ts +1 -1
- package/dist/components/features/mcp-page/install-server-modal.js +126 -102
- package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
- package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
- package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
- package/dist/components/features/mcp-page/installed-server-card.js +1 -1
- package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
- package/dist/components/features/mcp-page/marketplace-card.cjs +1 -1
- package/dist/components/features/mcp-page/marketplace-card.cjs.map +1 -1
- package/dist/components/features/mcp-page/marketplace-card.d.ts +1 -1
- package/dist/components/features/mcp-page/marketplace-card.js +27 -25
- package/dist/components/features/mcp-page/marketplace-card.js.map +1 -1
- package/dist/components/features/mcp-page/marketplace-section.cjs +1 -1
- package/dist/components/features/mcp-page/marketplace-section.cjs.map +1 -1
- package/dist/components/features/mcp-page/marketplace-section.d.ts +1 -1
- package/dist/components/features/mcp-page/marketplace-section.js +1 -1
- package/dist/components/features/mcp-page/marketplace-section.js.map +1 -1
- package/dist/components/features/mcp-page/mcp-logo-stack-badge.d.ts +2 -2
- package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +7 -7
- package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.d.ts +8 -12
- package/dist/components/features/settings/mcp-settings/mcp-server-form.js +114 -87
- package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
- package/dist/context/scroll-context.cjs +1 -1
- package/dist/context/scroll-context.cjs.map +1 -1
- package/dist/context/scroll-context.d.ts +1 -0
- package/dist/context/scroll-context.js +4 -1
- package/dist/context/scroll-context.js.map +1 -1
- package/dist/favicon.svg +1 -0
- package/dist/hooks/mutation/use-switch-acp-model.cjs +2 -0
- package/dist/hooks/mutation/use-switch-acp-model.cjs.map +1 -0
- package/dist/hooks/mutation/use-switch-acp-model.d.ts +23 -0
- package/dist/hooks/mutation/use-switch-acp-model.js +26 -0
- package/dist/hooks/mutation/use-switch-acp-model.js.map +1 -0
- package/dist/hooks/mutation/use-test-mcp-server.cjs +2 -0
- package/dist/hooks/mutation/use-test-mcp-server.cjs.map +1 -0
- package/dist/hooks/mutation/use-test-mcp-server.d.ts +2 -0
- package/dist/hooks/mutation/use-test-mcp-server.js +10 -0
- package/dist/hooks/mutation/use-test-mcp-server.js.map +1 -0
- package/dist/hooks/query/use-automation-detail.d.ts +3 -2
- package/dist/hooks/use-acp-model-context.cjs.map +1 -1
- package/dist/hooks/use-acp-model-context.d.ts +3 -4
- package/dist/hooks/use-acp-model-context.js.map +1 -1
- package/dist/hooks/use-chat-input-model-state.cjs +2 -0
- package/dist/hooks/use-chat-input-model-state.cjs.map +1 -0
- package/dist/hooks/use-chat-input-model-state.d.ts +12 -0
- package/dist/hooks/use-chat-input-model-state.js +29 -0
- package/dist/hooks/use-chat-input-model-state.js.map +1 -0
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +8 -0
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +2 -2
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +136 -0
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +8 -0
- package/dist/locales/ca/openhands.json +8 -0
- package/dist/locales/de/openhands.json +8 -0
- package/dist/locales/en/openhands.json +8 -0
- package/dist/locales/es/openhands.json +8 -0
- package/dist/locales/fr/openhands.json +8 -0
- package/dist/locales/it/openhands.json +8 -0
- package/dist/locales/ja/openhands.json +8 -0
- package/dist/locales/ko-KR/openhands.json +8 -0
- package/dist/locales/no/openhands.json +8 -0
- package/dist/locales/pt/openhands.json +8 -0
- package/dist/locales/tr/openhands.json +8 -0
- package/dist/locales/uk/openhands.json +8 -0
- package/dist/locales/zh-CN/openhands.json +8 -0
- package/dist/locales/zh-TW/openhands.json +8 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js +37 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/atlassian.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/atlassian.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.js +31 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js +52 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-bindings.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-bindings.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-bindings.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-bindings.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-browser-rendering.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-browser-rendering.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-browser-rendering.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-browser-rendering.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-builds.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-builds.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-builds.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-builds.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-docs.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-docs.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-docs.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-docs.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-observability.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-observability.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-observability.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-observability.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/deepwiki.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/deepwiki.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/deepwiki.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/deepwiki.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/everything.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/everything.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/everything.js +13 -6
- package/dist/node_modules/@openhands/extensions/integrations/catalog/everything.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/fetch.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/fetch.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/fetch.js +13 -6
- package/dist/node_modules/@openhands/extensions/integrations/catalog/fetch.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js +40 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.js +39 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/git.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/git.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/git.js +40 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/git.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +47 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/huggingface.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/huggingface.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/huggingface.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/huggingface.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/linear.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/linear.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/memory.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/memory.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/memory.js +13 -6
- package/dist/node_modules/@openhands/extensions/integrations/catalog/memory.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js +36 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js +40 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +39 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js +38 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/paypal.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/paypal.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/paypal.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/paypal.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/playwright.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/playwright.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/playwright.js +13 -6
- package/dist/node_modules/@openhands/extensions/integrations/catalog/playwright.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js +43 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js +41 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/sentry.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/sentry.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/sentry.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/sentry.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/sequential-thinking.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/sequential-thinking.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/sequential-thinking.js +13 -6
- package/dist/node_modules/@openhands/extensions/integrations/catalog/sequential-thinking.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +45 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/stripe.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/stripe.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/stripe.js +15 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/stripe.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js +37 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/tavily.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js +39 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/time.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/time.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/time.js +13 -6
- package/dist/node_modules/@openhands/extensions/integrations/catalog/time.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/index.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/index.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/index.js +175 -0
- package/dist/node_modules/@openhands/extensions/integrations/index.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/logos.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/logos.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/{mcps → integrations}/logos.js +2 -2
- package/dist/node_modules/@openhands/extensions/integrations/logos.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.js +548 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.js +482 -0
- package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js +3 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.js +22 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/index.js +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js +3 -0
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +6 -4
- package/dist/package.js.map +1 -1
- package/dist/routes/mcp.cjs +1 -1
- package/dist/routes/mcp.cjs.map +1 -1
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/mcp.js.map +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
- package/dist/utils/mcp-marketplace-utils.d.ts +21 -1
- package/dist/utils/mcp-marketplace-utils.js +23 -13
- package/dist/utils/mcp-marketplace-utils.js.map +1 -1
- package/dist/utils/settings-utils.cjs.map +1 -1
- package/dist/utils/settings-utils.js.map +1 -1
- package/package.json +6 -4
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/dev-safe.mjs +25 -7
- package/scripts/dev-with-automation.mjs +6 -1
- package/tools/canvas_ui_tool.py +129 -0
- package/build/assets/add-backend-modal-CqjNjGqY.js +0 -1
- package/build/assets/conversation-COZAKz_K.js +0 -1
- package/build/assets/conversation-DWcvnmds.js +0 -19
- package/build/assets/conversation-panel-CZDStT0b.js +0 -1
- package/build/assets/declaration-C9nuq2Dj.js +0 -1
- package/build/assets/edit-automation-modal-C3bFxS2f.js +0 -1
- package/build/assets/git-control-bar-branch-button-Bm6rzSpo.js +0 -27
- package/build/assets/install-server-modal-VB5hOBpW.js +0 -1
- package/build/assets/llm-settings-CIdxmimN.js +0 -1
- package/build/assets/manifest-f041e61a.js +0 -1
- package/build/assets/mcp-BdfyCW1l.js +0 -9
- package/build/assets/messages-v-q35ObG.js +0 -36
- package/build/assets/recommended-automations-launcher-Cx7svuGE.js +0 -52
- package/build/assets/root-D2PVd51i.js +0 -2
- package/build/assets/root-DEotKI6b.css +0 -1
- package/build/assets/settings-service.api-Z6x0l0GU.js +0 -1
- package/build/assets/use-is-authed-BFoh8Ogh.js +0 -1
- package/build/assets/use-runtime-is-ready-BQWLEyqa.js +0 -1
- package/build/assets/use-user-conversation-BCYpbPT1.js +0 -1
- package/build/assets/vendor~home~mcp~automations-list-DRfWZRnF.js +0 -1
- package/build/assets/vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-BJm2mGIp.js +0 -48
- package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.js +0 -30
- package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/atlassian.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/atlassian.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.js +0 -24
- package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.js +0 -45
- package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-bindings.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-bindings.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-browser-rendering.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-browser-rendering.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-browser-rendering.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-builds.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-builds.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-docs.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-docs.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-observability.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-observability.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-observability.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/deepwiki.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/deepwiki.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/everything.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/everything.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/fetch.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/fetch.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.js +0 -33
- package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.js +0 -32
- package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/git.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/git.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/git.js +0 -33
- package/dist/node_modules/@openhands/extensions/mcps/catalog/git.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/github.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/github.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/github.js +0 -40
- package/dist/node_modules/@openhands/extensions/mcps/catalog/github.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/huggingface.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/huggingface.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/linear.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/linear.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/memory.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/memory.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/memory.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.js +0 -29
- package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.js +0 -33
- package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.js +0 -32
- package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.js +0 -31
- package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/paypal.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/paypal.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/paypal.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/playwright.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/playwright.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/playwright.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.js +0 -36
- package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.js +0 -34
- package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/sentry.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/sentry.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/sentry.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/sequential-thinking.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/sequential-thinking.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/sequential-thinking.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.js +0 -38
- package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/stripe.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/stripe.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/stripe.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.js +0 -30
- package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/tavily.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/tavily.js +0 -32
- package/dist/node_modules/@openhands/extensions/mcps/catalog/tavily.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/time.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/catalog/time.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/catalog/time.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/index.cjs +0 -2
- package/dist/node_modules/@openhands/extensions/mcps/index.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/index.js +0 -87
- package/dist/node_modules/@openhands/extensions/mcps/index.js.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/logos.cjs.map +0 -1
- package/dist/node_modules/@openhands/extensions/mcps/logos.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-control-bar.js","names":[],"sources":["../../../../src/components/features/chat/git-control-bar.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { GitControlBarRepoButton } from \"./git-control-bar-repo-button\";\nimport { GitControlBarBranchButton } from \"./git-control-bar-branch-button\";\nimport { GitControlBarPullButton } from \"./git-control-bar-pull-button\";\nimport { GitControlBarPushButton } from \"./git-control-bar-push-button\";\nimport { GitControlBarPrButton } from \"./git-control-bar-pr-button\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useLocalGitInfo } from \"#/hooks/query/use-local-git-info\";\nimport { useTaskPolling } from \"#/hooks/query/use-task-polling\";\nimport { useUnifiedWebSocketStatus } from \"#/hooks/use-unified-websocket-status\";\nimport { useSendMessage } from \"#/hooks/use-send-message\";\nimport { useUpdateConversationRepository } from \"#/hooks/mutation/use-update-conversation-repository\";\nimport { useCreateConversation } from \"#/hooks/mutation/use-create-conversation\";\nimport { Provider } from \"#/types/settings\";\nimport { Branch, GitRepository } from \"#/types/git\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { GitControlBarTooltipWrapper } from \"./git-control-bar-tooltip-wrapper\";\nimport { OpenRepositoryModal } from \"./open-repository-modal\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { displayErrorToast } from \"#/utils/custom-toast-handlers\";\nimport { useHomeStore } from \"#/stores/home-store\";\nimport { useOptimisticUserMessageStore } from \"#/stores/optimistic-user-message-store\";\nimport { getStoredConversationMetadata } from \"#/api/conversation-metadata-store\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useUserProviders } from \"#/hooks/use-user-providers\";\n\ninterface GitControlBarProps {\n onSuggestionsClick: (value: string) => void;\n}\n\nexport function GitControlBar({ onSuggestionsClick }: GitControlBarProps) {\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const [isOpenRepoModalOpen, setIsOpenRepoModalOpen] = useState(false);\n const [isWorkspaceMenuOpen, setIsWorkspaceMenuOpen] = useState(false);\n const workspaceMenuContainerRef = useRef<HTMLDivElement>(null);\n const { addRecentRepository } = useHomeStore();\n const enqueuePendingMessage = useOptimisticUserMessageStore(\n (state) => state.enqueuePendingMessage,\n );\n const markPendingMessageError = useOptimisticUserMessageStore(\n (state) => state.markPendingMessageError,\n );\n const { backend } = useActiveBackend();\n const isLocalBackend = backend.kind === \"local\";\n const { providers } = useUserProviders();\n const providerTokensReady = isLocalBackend || providers.length > 0;\n\n const { data: conversation } = useActiveConversation();\n const { repositoryInfo } = useTaskPolling();\n const { data: localGitInfo } = useLocalGitInfo();\n const webSocketStatus = useUnifiedWebSocketStatus();\n const webSocketStatusRef = useRef(webSocketStatus);\n useEffect(() => {\n webSocketStatusRef.current = webSocketStatus;\n }, [webSocketStatus]);\n const { send } = useSendMessage();\n const sendRef = useRef(send);\n useEffect(() => {\n sendRef.current = send;\n }, [send]);\n const { mutate: updateRepository } = useUpdateConversationRepository();\n const { mutate: _createConversation, isPending: _isCreatingConversation } =\n useCreateConversation();\n\n // Priority: conversation data > task data > locally-detected git info.\n // The local fallback runs `git remote get-url origin` / `git rev-parse --abbrev-ref HEAD`\n // in the conversation's working dir so local-workspace conversations can\n // still display a repo and branch in the control bar.\n const conversationRepository =\n conversation?.selected_repository || repositoryInfo?.selectedRepository;\n const conversationProvider = (conversation?.git_provider ||\n repositoryInfo?.gitProvider) as Provider | undefined;\n const conversationBranch =\n conversation?.selected_branch || repositoryInfo?.selectedBranch;\n\n const selectedRepository =\n conversationRepository || localGitInfo?.repository || undefined;\n const gitProvider = (conversationProvider ||\n localGitInfo?.provider) as Provider;\n const selectedBranch =\n conversationBranch || localGitInfo?.branch || undefined;\n\n // For folder-only conversations (no remote repo), surface the basename of\n // the originally attached workspace path so the button reads e.g. \"test\"\n // rather than \"No Repo Connected\". `selected_workspace` is recorded at\n // conversation creation; we prefer it over `workspace.working_dir` because\n // the latter may point at a worktree subdir.\n const storedMetadata = conversation?.id\n ? getStoredConversationMetadata(conversation.id)\n : null;\n const workspacePath = storedMetadata?.selected_workspace ?? null;\n const workspaceName = workspacePath\n ? workspacePath.replace(/\\/+$/, \"\").split(\"/\").pop() || null\n : null;\n\n // Enable git actions whenever a repository and provider are known, including\n // local conversations where repo metadata is inferred from git remotes.\n const hasRepository = !!selectedRepository && !!gitProvider;\n\n // Enable buttons only when conversation exists and WS is connected\n const isConversationReady = !!conversation && webSocketStatus === \"OPEN\";\n\n useEffect(() => {\n if (!isWorkspaceMenuOpen) return undefined;\n const onMouseDown = (event: MouseEvent) => {\n if (\n workspaceMenuContainerRef.current &&\n !workspaceMenuContainerRef.current.contains(event.target as Node)\n ) {\n setIsWorkspaceMenuOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n return () => document.removeEventListener(\"mousedown\", onMouseDown);\n }, [isWorkspaceMenuOpen]);\n\n useEffect(() => {\n if (!isWorkspaceMenuOpen) return undefined;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsWorkspaceMenuOpen(false);\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [isWorkspaceMenuOpen]);\n\n const handleLaunchRepository = (\n repository: GitRepository,\n branch: Branch,\n ) => {\n if (!conversationId) return;\n\n // Persist to recent repositories list (matches home page behavior)\n addRecentRepository(repository);\n\n // Note: We update repository metadata first, then send clone command.\n // The clone command is sent to the agent via WebSocket (fire-and-forget).\n // If cloning fails, the agent will report the error in the chat,\n // and the user can retry or change the repository.\n // This is a trade-off: immediate UI feedback vs. strict atomicity.\n updateRepository(\n {\n conversationId,\n repository: repository.full_name,\n branch: branch.name,\n gitProvider: repository.git_provider,\n },\n {\n onSuccess: () => {\n // Use ref to read the latest WebSocket status (avoids stale closure)\n if (webSocketStatusRef.current !== \"OPEN\") {\n displayErrorToast(\n t(I18nKey.CONVERSATION$CLONE_COMMAND_FAILED_DISCONNECTED),\n );\n return;\n }\n\n // Send clone command to agent after metadata is updated\n // Use ref to always call the latest send function (avoids stale closure\n // where V1 sendMessage holds a reference to a now-closed WebSocket)\n // Include git provider in prompt so agent clones from correct source\n const providerName =\n repository.git_provider.charAt(0).toUpperCase() +\n repository.git_provider.slice(1);\n const clonePrompt = `Clone ${repository.full_name} from ${providerName} and checkout branch ${branch.name}.`;\n const pendingId = conversationId\n ? enqueuePendingMessage({ conversationId, text: clonePrompt })\n : null;\n // `send` returns a Promise; surface a failed send by flipping the\n // matching pending entry to \"error\" so the user gets the retry link\n // rather than a perpetual \"Sending…\" bubble.\n Promise.resolve(\n sendRef.current({\n action: \"message\",\n args: {\n content: clonePrompt,\n timestamp: new Date().toISOString(),\n },\n }),\n ).catch((error) => {\n if (!pendingId) return;\n const errorMessage =\n error instanceof Error ? error.message : \"Failed to send message\";\n markPendingMessageError(pendingId, errorMessage);\n });\n },\n },\n );\n };\n\n // Local backends never use the remote-repo \"Connect Repo\" CTA, so suppress the\n // empty-state button there. A repo or workspace label inferred from local git\n // metadata is still informational and stays visible.\n const showRepoButton =\n !isLocalBackend || !!selectedRepository || !!workspaceName;\n // On a local backend the informational pill (e.g. workspace name, or a repo\n // detected without a recognized provider) should not open the remote-repo\n // modal — that flow is cloud-only. Disable the button in that case so the\n // click is a no-op. Linkable repos render as <a> and ignore `disabled`.\n const isRepoButtonInert = isLocalBackend && !hasRepository;\n\n // True when the bar will render at least one chip (cloud always shows\n // \"Open Repository\"; local needs a repo or a workspace name; selected\n // branch or push/pull/PR also count). When false, the bar has nothing to\n // show — return null so the wrapper above collapses to its natural padding\n // instead of leaving an empty DOM node below the chat input.\n const hasAnyContent = showRepoButton || !!selectedBranch || hasRepository;\n if (!hasAnyContent) return null;\n\n return (\n <div className=\"flex flex-row items-center\">\n <div className=\"flex flex-row gap-2.5 items-center overflow-x-auto flex-nowrap relative scrollbar-hide\">\n {showRepoButton ? (\n <GitControlBarRepoButton\n selectedRepository={selectedRepository}\n gitProvider={gitProvider}\n workspaceName={workspaceName}\n onClick={() => setIsOpenRepoModalOpen(true)}\n disabled={!isConversationReady || isRepoButtonInert}\n />\n ) : null}\n\n {selectedBranch ? (\n <GitControlBarBranchButton\n selectedBranch={selectedBranch}\n selectedRepository={selectedRepository}\n gitProvider={gitProvider}\n />\n ) : null}\n\n {hasRepository ? (\n <>\n <GitControlBarTooltipWrapper\n tooltipMessage={t(I18nKey.COMMON$GIT_TOOLS_DISABLED_CONTENT)}\n testId=\"git-control-bar-pull-button-tooltip\"\n shouldShowTooltip={!hasRepository}\n >\n <GitControlBarPullButton\n onSuggestionsClick={onSuggestionsClick}\n hasRepository={hasRepository}\n providerTokensReady={providerTokensReady}\n isConversationReady={isConversationReady}\n />\n </GitControlBarTooltipWrapper>\n\n <GitControlBarTooltipWrapper\n tooltipMessage={t(I18nKey.COMMON$GIT_TOOLS_DISABLED_CONTENT)}\n testId=\"git-control-bar-push-button-tooltip\"\n shouldShowTooltip={!hasRepository}\n >\n <GitControlBarPushButton\n onSuggestionsClick={onSuggestionsClick}\n hasRepository={hasRepository}\n providerTokensReady={providerTokensReady}\n currentGitProvider={gitProvider}\n isConversationReady={isConversationReady}\n />\n </GitControlBarTooltipWrapper>\n\n <GitControlBarTooltipWrapper\n tooltipMessage={t(I18nKey.COMMON$GIT_TOOLS_DISABLED_CONTENT)}\n testId=\"git-control-bar-pr-button-tooltip\"\n shouldShowTooltip={!hasRepository}\n >\n <GitControlBarPrButton\n onSuggestionsClick={onSuggestionsClick}\n hasRepository={hasRepository}\n providerTokensReady={providerTokensReady}\n currentGitProvider={gitProvider}\n isConversationReady={isConversationReady}\n />\n </GitControlBarTooltipWrapper>\n </>\n ) : null}\n </div>\n\n <OpenRepositoryModal\n isOpen={isOpenRepoModalOpen}\n onClose={() => setIsOpenRepoModalOpen(false)}\n onLaunch={handleLaunchRepository}\n defaultProvider={gitProvider}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"git-control-bar.js","names":[],"sources":["../../../../src/components/features/chat/git-control-bar.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { GitControlBarRepoButton } from \"./git-control-bar-repo-button\";\nimport { GitControlBarBranchButton } from \"./git-control-bar-branch-button\";\nimport { GitControlBarPullButton } from \"./git-control-bar-pull-button\";\nimport { GitControlBarPushButton } from \"./git-control-bar-push-button\";\nimport { GitControlBarPrButton } from \"./git-control-bar-pr-button\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useLocalGitInfo } from \"#/hooks/query/use-local-git-info\";\nimport { useTaskPolling } from \"#/hooks/query/use-task-polling\";\nimport { useUnifiedWebSocketStatus } from \"#/hooks/use-unified-websocket-status\";\nimport { useSendMessage } from \"#/hooks/use-send-message\";\nimport { useUpdateConversationRepository } from \"#/hooks/mutation/use-update-conversation-repository\";\nimport { useCreateConversation } from \"#/hooks/mutation/use-create-conversation\";\nimport { Provider } from \"#/types/settings\";\nimport { Branch, GitRepository } from \"#/types/git\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { GitControlBarTooltipWrapper } from \"./git-control-bar-tooltip-wrapper\";\nimport { OpenRepositoryModal } from \"./open-repository-modal\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { displayErrorToast } from \"#/utils/custom-toast-handlers\";\nimport { useHomeStore } from \"#/stores/home-store\";\nimport { useOptimisticUserMessageStore } from \"#/stores/optimistic-user-message-store\";\nimport { getStoredConversationMetadata } from \"#/api/conversation-metadata-store\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useUserProviders } from \"#/hooks/use-user-providers\";\nimport { useOptionalScrollContext } from \"#/context/scroll-context\";\n\ninterface GitControlBarProps {\n onSuggestionsClick: (value: string) => void;\n}\n\nexport function GitControlBar({ onSuggestionsClick }: GitControlBarProps) {\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const [isOpenRepoModalOpen, setIsOpenRepoModalOpen] = useState(false);\n const [isWorkspaceMenuOpen, setIsWorkspaceMenuOpen] = useState(false);\n const workspaceMenuContainerRef = useRef<HTMLDivElement>(null);\n const { addRecentRepository } = useHomeStore();\n const enqueuePendingMessage = useOptimisticUserMessageStore(\n (state) => state.enqueuePendingMessage,\n );\n const markPendingMessageError = useOptimisticUserMessageStore(\n (state) => state.markPendingMessageError,\n );\n const { backend } = useActiveBackend();\n const isLocalBackend = backend.kind === \"local\";\n const { providers } = useUserProviders();\n const providerTokensReady = isLocalBackend || providers.length > 0;\n\n const { data: conversation } = useActiveConversation();\n const { repositoryInfo } = useTaskPolling();\n const { data: localGitInfo } = useLocalGitInfo();\n const webSocketStatus = useUnifiedWebSocketStatus();\n const webSocketStatusRef = useRef(webSocketStatus);\n useEffect(() => {\n webSocketStatusRef.current = webSocketStatus;\n }, [webSocketStatus]);\n const { send } = useSendMessage();\n const sendRef = useRef(send);\n useEffect(() => {\n sendRef.current = send;\n }, [send]);\n const scrollContext = useOptionalScrollContext();\n const { mutate: updateRepository } = useUpdateConversationRepository();\n const { mutate: _createConversation, isPending: _isCreatingConversation } =\n useCreateConversation();\n\n // Priority: conversation data > task data > locally-detected git info.\n // The local fallback runs `git remote get-url origin` / `git rev-parse --abbrev-ref HEAD`\n // in the conversation's working dir so local-workspace conversations can\n // still display a repo and branch in the control bar.\n const conversationRepository =\n conversation?.selected_repository || repositoryInfo?.selectedRepository;\n const conversationProvider = (conversation?.git_provider ||\n repositoryInfo?.gitProvider) as Provider | undefined;\n const conversationBranch =\n conversation?.selected_branch || repositoryInfo?.selectedBranch;\n\n const selectedRepository =\n conversationRepository || localGitInfo?.repository || undefined;\n const gitProvider = (conversationProvider ||\n localGitInfo?.provider) as Provider;\n const selectedBranch =\n conversationBranch || localGitInfo?.branch || undefined;\n\n // For folder-only conversations (no remote repo), surface the basename of\n // the originally attached workspace path so the button reads e.g. \"test\"\n // rather than \"No Repo Connected\". `selected_workspace` is recorded at\n // conversation creation; we prefer it over `workspace.working_dir` because\n // the latter may point at a worktree subdir.\n const storedMetadata = conversation?.id\n ? getStoredConversationMetadata(conversation.id)\n : null;\n const workspacePath = storedMetadata?.selected_workspace ?? null;\n const workspaceName = workspacePath\n ? workspacePath.replace(/\\/+$/, \"\").split(\"/\").pop() || null\n : null;\n\n // Enable git actions whenever a repository and provider are known, including\n // local conversations where repo metadata is inferred from git remotes.\n const hasRepository = !!selectedRepository && !!gitProvider;\n\n // Enable buttons only when conversation exists and WS is connected\n const isConversationReady = !!conversation && webSocketStatus === \"OPEN\";\n\n useEffect(() => {\n if (!isWorkspaceMenuOpen) return undefined;\n const onMouseDown = (event: MouseEvent) => {\n if (\n workspaceMenuContainerRef.current &&\n !workspaceMenuContainerRef.current.contains(event.target as Node)\n ) {\n setIsWorkspaceMenuOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n return () => document.removeEventListener(\"mousedown\", onMouseDown);\n }, [isWorkspaceMenuOpen]);\n\n useEffect(() => {\n if (!isWorkspaceMenuOpen) return undefined;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsWorkspaceMenuOpen(false);\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [isWorkspaceMenuOpen]);\n\n const handleLaunchRepository = (\n repository: GitRepository,\n branch: Branch,\n ) => {\n if (!conversationId) return;\n\n // Persist to recent repositories list (matches home page behavior)\n addRecentRepository(repository);\n\n // Note: We update repository metadata first, then send clone command.\n // The clone command is sent to the agent via WebSocket (fire-and-forget).\n // If cloning fails, the agent will report the error in the chat,\n // and the user can retry or change the repository.\n // This is a trade-off: immediate UI feedback vs. strict atomicity.\n updateRepository(\n {\n conversationId,\n repository: repository.full_name,\n branch: branch.name,\n gitProvider: repository.git_provider,\n },\n {\n onSuccess: () => {\n // Use ref to read the latest WebSocket status (avoids stale closure)\n if (webSocketStatusRef.current !== \"OPEN\") {\n displayErrorToast(\n t(I18nKey.CONVERSATION$CLONE_COMMAND_FAILED_DISCONNECTED),\n );\n return;\n }\n\n // Send clone command to agent after metadata is updated\n // Use ref to always call the latest send function (avoids stale closure\n // where V1 sendMessage holds a reference to a now-closed WebSocket)\n // Include git provider in prompt so agent clones from correct source\n const providerName =\n repository.git_provider.charAt(0).toUpperCase() +\n repository.git_provider.slice(1);\n const clonePrompt = `Clone ${repository.full_name} from ${providerName} and checkout branch ${branch.name}.`;\n const pendingId = conversationId\n ? enqueuePendingMessage({ conversationId, text: clonePrompt })\n : null;\n // Pull chat back to the bottom so the optimistic \"Clone …\" bubble\n // is visible even if the user had scrolled up.\n scrollContext?.scrollDomToBottom();\n // `send` returns a Promise; surface a failed send by flipping the\n // matching pending entry to \"error\" so the user gets the retry link\n // rather than a perpetual \"Sending…\" bubble.\n Promise.resolve(\n sendRef.current({\n action: \"message\",\n args: {\n content: clonePrompt,\n timestamp: new Date().toISOString(),\n },\n }),\n ).catch((error) => {\n if (!pendingId) return;\n const errorMessage =\n error instanceof Error ? error.message : \"Failed to send message\";\n markPendingMessageError(pendingId, errorMessage);\n });\n },\n },\n );\n };\n\n // Local backends never use the remote-repo \"Connect Repo\" CTA, so suppress the\n // empty-state button there. A repo or workspace label inferred from local git\n // metadata is still informational and stays visible.\n const showRepoButton =\n !isLocalBackend || !!selectedRepository || !!workspaceName;\n // On a local backend the informational pill (e.g. workspace name, or a repo\n // detected without a recognized provider) should not open the remote-repo\n // modal — that flow is cloud-only. Disable the button in that case so the\n // click is a no-op. Linkable repos render as <a> and ignore `disabled`.\n const isRepoButtonInert = isLocalBackend && !hasRepository;\n\n // True when the bar will render at least one chip (cloud always shows\n // \"Open Repository\"; local needs a repo or a workspace name; selected\n // branch or push/pull/PR also count). When false, the bar has nothing to\n // show — return null so the wrapper above collapses to its natural padding\n // instead of leaving an empty DOM node below the chat input.\n const hasAnyContent = showRepoButton || !!selectedBranch || hasRepository;\n if (!hasAnyContent) return null;\n\n return (\n <div className=\"flex flex-row items-center\">\n <div className=\"flex flex-row gap-2.5 items-center overflow-x-auto flex-nowrap relative scrollbar-hide\">\n {showRepoButton ? (\n <GitControlBarRepoButton\n selectedRepository={selectedRepository}\n gitProvider={gitProvider}\n workspaceName={workspaceName}\n onClick={() => setIsOpenRepoModalOpen(true)}\n disabled={!isConversationReady || isRepoButtonInert}\n />\n ) : null}\n\n {selectedBranch ? (\n <GitControlBarBranchButton\n selectedBranch={selectedBranch}\n selectedRepository={selectedRepository}\n gitProvider={gitProvider}\n />\n ) : null}\n\n {hasRepository ? (\n <>\n <GitControlBarTooltipWrapper\n tooltipMessage={t(I18nKey.COMMON$GIT_TOOLS_DISABLED_CONTENT)}\n testId=\"git-control-bar-pull-button-tooltip\"\n shouldShowTooltip={!hasRepository}\n >\n <GitControlBarPullButton\n onSuggestionsClick={onSuggestionsClick}\n hasRepository={hasRepository}\n providerTokensReady={providerTokensReady}\n isConversationReady={isConversationReady}\n />\n </GitControlBarTooltipWrapper>\n\n <GitControlBarTooltipWrapper\n tooltipMessage={t(I18nKey.COMMON$GIT_TOOLS_DISABLED_CONTENT)}\n testId=\"git-control-bar-push-button-tooltip\"\n shouldShowTooltip={!hasRepository}\n >\n <GitControlBarPushButton\n onSuggestionsClick={onSuggestionsClick}\n hasRepository={hasRepository}\n providerTokensReady={providerTokensReady}\n currentGitProvider={gitProvider}\n isConversationReady={isConversationReady}\n />\n </GitControlBarTooltipWrapper>\n\n <GitControlBarTooltipWrapper\n tooltipMessage={t(I18nKey.COMMON$GIT_TOOLS_DISABLED_CONTENT)}\n testId=\"git-control-bar-pr-button-tooltip\"\n shouldShowTooltip={!hasRepository}\n >\n <GitControlBarPrButton\n onSuggestionsClick={onSuggestionsClick}\n hasRepository={hasRepository}\n providerTokensReady={providerTokensReady}\n currentGitProvider={gitProvider}\n isConversationReady={isConversationReady}\n />\n </GitControlBarTooltipWrapper>\n </>\n ) : null}\n </div>\n\n <OpenRepositoryModal\n isOpen={isOpenRepoModalOpen}\n onClose={() => setIsOpenRepoModalOpen(false)}\n onLaunch={handleLaunchRepository}\n defaultProvider={gitProvider}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../types/agent-state.cjs`),n=require(`../../../utils/utils.cjs`),r=require(`../../../hooks/use-conversation-id.cjs`),i=require(`../../../hooks/query/use-active-conversation.cjs`),a=require(`../../../hooks/use-agent-state.cjs`),o=require(`../../../hooks/query/use-task-polling.cjs`),s=require(`../../../utils/status.cjs`),c=require(`../../../hooks/mutation/use-unified-stop-conversation.cjs`),l=require(`../../../hooks/use-user-providers.cjs`),u=require(`../../../icons/debug-stackframe-dot.cjs`),d=require(`../../../hooks/mutation/use-unified-start-conversation.cjs`),f=require(`../controls/server-status-context-menu.cjs`),p=require(`./conversation-name.cjs`),m=require(`./right-panel-toggle.cjs`);let h=require(`react`);h=e.__toESM(h,1);let g=require(`react/jsx-runtime`);function _(){let{conversationId:e}=r.useConversationId(),{data:h}=i.useActiveConversation(),{curAgentState:_}=a.useAgentState(),{isTask:v,taskStatus:y}=o.useTaskPolling(),{mutate:b}=c.useUnifiedPauseConversation(),{mutate:x}=d.useUnifiedResumeConversation(),{providers:S}=l.useUserProviders(),C=h?.execution_status??null,w=n.getStatusColor({isPausing:!1,isTask:v,taskStatus:y,isStartingStatus:_===t.AgentState.LOADING||_===t.AgentState.INIT,isStopStatus:s.isExecutionErrored(C),curAgentState:_});return(0,g.jsxs)(`div`,{className:`flex items-center justify-between w-full`,children:[(0,g.jsxs)(`div`,{className:`flex items-center`,children:[(0,g.jsxs)(`div`,{className:`group relative`,children:[(0,g.jsx)(u.default,{className:`ml-[3.5px] w-6 h-6 cursor-pointer`,color:w}),(0,g.jsx)(f.ServerStatusContextMenu,{onClose:()=>{},onStopServer:s.isExecutionActive(C)?t=>{t.preventDefault(),t.stopPropagation(),e&&b({conversationId:e})}:void 0,onStartServer:s.isExecutionPaused(C)?t=>{t.preventDefault(),t.stopPropagation(),e&&x({conversationId:e,providers:S})}:void 0,executionStatus:C,position:`bottom`,className:`opacity-0 invisible pointer-events-none group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto bottom-full left-0 mt-0 min-h-fit`,isPausing:!1})]}),(0,g.jsx)(p.ConversationName,{})]}),(0,g.jsx)(m.RightPanelToggle,{className:`mr-2`})]})}exports.ConversationNameWithStatus=_;
|
|
1
|
+
const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../types/agent-state.cjs`),n=require(`../../../utils/utils.cjs`),r=require(`../../../hooks/use-conversation-id.cjs`),i=require(`../../../hooks/query/use-active-conversation.cjs`),a=require(`../../../hooks/use-agent-state.cjs`),o=require(`../../../hooks/query/use-task-polling.cjs`),s=require(`../../../utils/status.cjs`),c=require(`../../../hooks/mutation/use-unified-stop-conversation.cjs`),l=require(`../../../hooks/use-user-providers.cjs`),u=require(`../../../icons/debug-stackframe-dot.cjs`),d=require(`../../../hooks/mutation/use-unified-start-conversation.cjs`),f=require(`../controls/server-status-context-menu.cjs`),p=require(`./conversation-name.cjs`),m=require(`./right-panel-toggle.cjs`);let h=require(`react`);h=e.__toESM(h,1);let g=require(`react/jsx-runtime`);function _(){let{conversationId:e}=r.useConversationId(),{data:h}=i.useActiveConversation(),{curAgentState:_}=a.useAgentState(),{isTask:v,taskStatus:y}=o.useTaskPolling(),{mutate:b}=c.useUnifiedPauseConversation(),{mutate:x}=d.useUnifiedResumeConversation(),{providers:S}=l.useUserProviders(),C=h?.execution_status??null,w=n.getStatusColor({isPausing:!1,isTask:v,taskStatus:y,isStartingStatus:_===t.AgentState.LOADING||_===t.AgentState.INIT,isStopStatus:s.isExecutionErrored(C),curAgentState:_});return(0,g.jsxs)(`div`,{className:`flex items-center justify-between w-full`,children:[(0,g.jsxs)(`div`,{className:`flex items-center min-w-0`,children:[(0,g.jsxs)(`div`,{className:`group relative shrink-0`,children:[(0,g.jsx)(u.default,{className:`ml-[3.5px] w-6 h-6 cursor-pointer`,color:w}),(0,g.jsx)(f.ServerStatusContextMenu,{onClose:()=>{},onStopServer:s.isExecutionActive(C)?t=>{t.preventDefault(),t.stopPropagation(),e&&b({conversationId:e})}:void 0,onStartServer:s.isExecutionPaused(C)?t=>{t.preventDefault(),t.stopPropagation(),e&&x({conversationId:e,providers:S})}:void 0,executionStatus:C,position:`bottom`,className:`opacity-0 invisible pointer-events-none group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto bottom-full left-0 mt-0 min-h-fit`,isPausing:!1})]}),(0,g.jsx)(p.ConversationName,{})]}),(0,g.jsx)(m.RightPanelToggle,{className:`mr-2`})]})}exports.ConversationNameWithStatus=_;
|
|
2
2
|
//# sourceMappingURL=conversation-name-with-status.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-name-with-status.cjs","names":[],"sources":["../../../../src/components/features/conversation/conversation-name-with-status.tsx"],"sourcesContent":["import React from \"react\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useTaskPolling } from \"#/hooks/query/use-task-polling\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUnifiedPauseConversation } from \"#/hooks/mutation/use-unified-stop-conversation\";\nimport { useUnifiedResumeConversation } from \"#/hooks/mutation/use-unified-start-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useUserProviders } from \"#/hooks/use-user-providers\";\nimport { getStatusColor } from \"#/utils/utils\";\nimport { AgentState } from \"#/types/agent-state\";\nimport DebugStackframeDot from \"#/icons/debug-stackframe-dot.svg?react\";\nimport { ServerStatusContextMenu } from \"../controls/server-status-context-menu\";\nimport { ConversationName } from \"./conversation-name\";\nimport { RightPanelToggle } from \"./right-panel-toggle\";\nimport {\n isExecutionActive,\n isExecutionErrored,\n isExecutionPaused,\n} from \"#/utils/status\";\n\nexport function ConversationNameWithStatus() {\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { curAgentState } = useAgentState();\n const { isTask, taskStatus } = useTaskPolling();\n const { mutate: pauseConversation } = useUnifiedPauseConversation();\n const { mutate: resumeConversation } = useUnifiedResumeConversation();\n const { providers } = useUserProviders();\n\n const executionStatus = conversation?.execution_status ?? null;\n const isStartingStatus =\n curAgentState === AgentState.LOADING || curAgentState === AgentState.INIT;\n const isStopStatus = isExecutionErrored(executionStatus);\n\n const statusColor = getStatusColor({\n isPausing: false,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n });\n\n const handleStopServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n pauseConversation({ conversationId });\n }\n };\n\n const handleStartServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n resumeConversation({ conversationId, providers });\n }\n };\n\n return (\n <div className=\"flex items-center justify-between w-full\">\n <div className=\"flex items-center\">\n <div className=\"group relative\">\n <DebugStackframeDot\n className=\"ml-[3.5px] w-6 h-6 cursor-pointer\"\n color={statusColor}\n />\n <ServerStatusContextMenu\n onClose={() => {}}\n onStopServer={\n isExecutionActive(executionStatus) ? handleStopServer : undefined\n }\n onStartServer={\n isExecutionPaused(executionStatus) ? handleStartServer : undefined\n }\n executionStatus={executionStatus}\n position=\"bottom\"\n className=\"opacity-0 invisible pointer-events-none group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto bottom-full left-0 mt-0 min-h-fit\"\n isPausing={false}\n />\n </div>\n <ConversationName />\n </div>\n <RightPanelToggle className=\"mr-2\" />\n </div>\n );\n}\n"],"mappings":"k1BAoBA,SAAgB,GAA6B,CAC3C,GAAM,CAAE,kBAAmB,EAAA,mBAAmB,CACxC,CAAE,KAAM,GAAiB,EAAA,uBAAuB,CAChD,CAAE,iBAAkB,EAAA,eAAe,CACnC,CAAE,SAAQ,cAAe,EAAA,gBAAgB,CACzC,CAAE,OAAQ,GAAsB,EAAA,6BAA6B,CAC7D,CAAE,OAAQ,GAAuB,EAAA,8BAA8B,CAC/D,CAAE,aAAc,EAAA,kBAAkB,CAElC,EAAkB,GAAc,kBAAoB,KAKpD,EAAc,EAAA,eAAe,CACjC,UAAW,GACX,SACA,aACA,iBAPA,IAAkB,EAAA,WAAW,SAAW,IAAkB,EAAA,WAAW,KAQrE,aAPmB,EAAA,mBAAmB,EAOtC,CACA,gBACD,CAAC,CAkBF,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,oDAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"conversation-name-with-status.cjs","names":[],"sources":["../../../../src/components/features/conversation/conversation-name-with-status.tsx"],"sourcesContent":["import React from \"react\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useTaskPolling } from \"#/hooks/query/use-task-polling\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUnifiedPauseConversation } from \"#/hooks/mutation/use-unified-stop-conversation\";\nimport { useUnifiedResumeConversation } from \"#/hooks/mutation/use-unified-start-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useUserProviders } from \"#/hooks/use-user-providers\";\nimport { getStatusColor } from \"#/utils/utils\";\nimport { AgentState } from \"#/types/agent-state\";\nimport DebugStackframeDot from \"#/icons/debug-stackframe-dot.svg?react\";\nimport { ServerStatusContextMenu } from \"../controls/server-status-context-menu\";\nimport { ConversationName } from \"./conversation-name\";\nimport { RightPanelToggle } from \"./right-panel-toggle\";\nimport {\n isExecutionActive,\n isExecutionErrored,\n isExecutionPaused,\n} from \"#/utils/status\";\n\nexport function ConversationNameWithStatus() {\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { curAgentState } = useAgentState();\n const { isTask, taskStatus } = useTaskPolling();\n const { mutate: pauseConversation } = useUnifiedPauseConversation();\n const { mutate: resumeConversation } = useUnifiedResumeConversation();\n const { providers } = useUserProviders();\n\n const executionStatus = conversation?.execution_status ?? null;\n const isStartingStatus =\n curAgentState === AgentState.LOADING || curAgentState === AgentState.INIT;\n const isStopStatus = isExecutionErrored(executionStatus);\n\n const statusColor = getStatusColor({\n isPausing: false,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n });\n\n const handleStopServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n pauseConversation({ conversationId });\n }\n };\n\n const handleStartServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n resumeConversation({ conversationId, providers });\n }\n };\n\n return (\n <div className=\"flex items-center justify-between w-full\">\n <div className=\"flex items-center min-w-0\">\n <div className=\"group relative shrink-0\">\n <DebugStackframeDot\n className=\"ml-[3.5px] w-6 h-6 cursor-pointer\"\n color={statusColor}\n />\n <ServerStatusContextMenu\n onClose={() => {}}\n onStopServer={\n isExecutionActive(executionStatus) ? handleStopServer : undefined\n }\n onStartServer={\n isExecutionPaused(executionStatus) ? handleStartServer : undefined\n }\n executionStatus={executionStatus}\n position=\"bottom\"\n className=\"opacity-0 invisible pointer-events-none group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto bottom-full left-0 mt-0 min-h-fit\"\n isPausing={false}\n />\n </div>\n <ConversationName />\n </div>\n <RightPanelToggle className=\"mr-2\" />\n </div>\n );\n}\n"],"mappings":"k1BAoBA,SAAgB,GAA6B,CAC3C,GAAM,CAAE,kBAAmB,EAAA,mBAAmB,CACxC,CAAE,KAAM,GAAiB,EAAA,uBAAuB,CAChD,CAAE,iBAAkB,EAAA,eAAe,CACnC,CAAE,SAAQ,cAAe,EAAA,gBAAgB,CACzC,CAAE,OAAQ,GAAsB,EAAA,6BAA6B,CAC7D,CAAE,OAAQ,GAAuB,EAAA,8BAA8B,CAC/D,CAAE,aAAc,EAAA,kBAAkB,CAElC,EAAkB,GAAc,kBAAoB,KAKpD,EAAc,EAAA,eAAe,CACjC,UAAW,GACX,SACA,aACA,iBAPA,IAAkB,EAAA,WAAW,SAAW,IAAkB,EAAA,WAAW,KAQrE,aAPmB,EAAA,mBAAmB,EAOtC,CACA,gBACD,CAAC,CAkBF,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,oDAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,UAAU,oCACV,MAAO,EACP,CAAA,EACF,EAAA,EAAA,KAAC,EAAA,wBAAD,CACE,YAAe,GACf,aACE,EAAA,kBAAkB,EAAgB,CA3BpB,GAA+C,CACvE,EAAM,gBAAgB,CACtB,EAAM,iBAAiB,CACnB,GACF,EAAkB,CAAE,iBAAgB,CAAC,EAuB2B,IAAA,GAE1D,cACE,EAAA,kBAAkB,EAAgB,CAtBnB,GAA+C,CACxE,EAAM,gBAAgB,CACtB,EAAM,iBAAiB,CACnB,GACF,EAAmB,CAAE,iBAAgB,YAAW,CAAC,EAkBgB,IAAA,GAE1C,kBACjB,SAAS,SACT,UAAU,wJACV,UAAW,GACX,CAAA,CACE,IACN,EAAA,EAAA,KAAC,EAAA,iBAAD,EAAoB,CAAA,CAChB,IACN,EAAA,EAAA,KAAC,EAAA,iBAAD,CAAkB,UAAU,OAAS,CAAA,CACjC"}
|
|
@@ -20,9 +20,9 @@ function v() {
|
|
|
20
20
|
return /* @__PURE__ */ _("div", {
|
|
21
21
|
className: "flex items-center justify-between w-full",
|
|
22
22
|
children: [/* @__PURE__ */ _("div", {
|
|
23
|
-
className: "flex items-center",
|
|
23
|
+
className: "flex items-center min-w-0",
|
|
24
24
|
children: [/* @__PURE__ */ _("div", {
|
|
25
|
-
className: "group relative",
|
|
25
|
+
className: "group relative shrink-0",
|
|
26
26
|
children: [/* @__PURE__ */ g(d, {
|
|
27
27
|
className: "ml-[3.5px] w-6 h-6 cursor-pointer",
|
|
28
28
|
color: t({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-name-with-status.js","names":[],"sources":["../../../../src/components/features/conversation/conversation-name-with-status.tsx"],"sourcesContent":["import React from \"react\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useTaskPolling } from \"#/hooks/query/use-task-polling\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUnifiedPauseConversation } from \"#/hooks/mutation/use-unified-stop-conversation\";\nimport { useUnifiedResumeConversation } from \"#/hooks/mutation/use-unified-start-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useUserProviders } from \"#/hooks/use-user-providers\";\nimport { getStatusColor } from \"#/utils/utils\";\nimport { AgentState } from \"#/types/agent-state\";\nimport DebugStackframeDot from \"#/icons/debug-stackframe-dot.svg?react\";\nimport { ServerStatusContextMenu } from \"../controls/server-status-context-menu\";\nimport { ConversationName } from \"./conversation-name\";\nimport { RightPanelToggle } from \"./right-panel-toggle\";\nimport {\n isExecutionActive,\n isExecutionErrored,\n isExecutionPaused,\n} from \"#/utils/status\";\n\nexport function ConversationNameWithStatus() {\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { curAgentState } = useAgentState();\n const { isTask, taskStatus } = useTaskPolling();\n const { mutate: pauseConversation } = useUnifiedPauseConversation();\n const { mutate: resumeConversation } = useUnifiedResumeConversation();\n const { providers } = useUserProviders();\n\n const executionStatus = conversation?.execution_status ?? null;\n const isStartingStatus =\n curAgentState === AgentState.LOADING || curAgentState === AgentState.INIT;\n const isStopStatus = isExecutionErrored(executionStatus);\n\n const statusColor = getStatusColor({\n isPausing: false,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n });\n\n const handleStopServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n pauseConversation({ conversationId });\n }\n };\n\n const handleStartServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n resumeConversation({ conversationId, providers });\n }\n };\n\n return (\n <div className=\"flex items-center justify-between w-full\">\n <div className=\"flex items-center\">\n <div className=\"group relative\">\n <DebugStackframeDot\n className=\"ml-[3.5px] w-6 h-6 cursor-pointer\"\n color={statusColor}\n />\n <ServerStatusContextMenu\n onClose={() => {}}\n onStopServer={\n isExecutionActive(executionStatus) ? handleStopServer : undefined\n }\n onStartServer={\n isExecutionPaused(executionStatus) ? handleStartServer : undefined\n }\n executionStatus={executionStatus}\n position=\"bottom\"\n className=\"opacity-0 invisible pointer-events-none group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto bottom-full left-0 mt-0 min-h-fit\"\n isPausing={false}\n />\n </div>\n <ConversationName />\n </div>\n <RightPanelToggle className=\"mr-2\" />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,SAAgB,IAA6B;CAC3C,IAAM,EAAE,sBAAmB,GAAmB,EACxC,EAAE,MAAM,MAAiB,GAAuB,EAChD,EAAE,qBAAkB,GAAe,EACnC,EAAE,WAAQ,kBAAe,GAAgB,EACzC,EAAE,QAAQ,MAAsB,GAA6B,EAC7D,EAAE,QAAQ,MAAuB,GAA8B,EAC/D,EAAE,iBAAc,GAAkB,EAElC,IAAkB,GAAc,oBAAoB;AA8B1D,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,WAAU;KACV,OA/BU,EAAe;MACjC,WAAW;MACX;MACA;MACA,kBAPA,MAAkB,EAAW,WAAW,MAAkB,EAAW;MAQrE,cAPmB,EAAmB,EAOtC;MACA;MACD,CAwBgB;KACP,CAAA,EACF,kBAAC,GAAD;KACE,eAAe;KACf,cACE,EAAkB,EAAgB,IA3BpB,MAA+C;AAGvE,MAFA,EAAM,gBAAgB,EACtB,EAAM,iBAAiB,EACnB,KACF,EAAkB,EAAE,mBAAgB,CAAC;SAuB2B,KAAA;KAE1D,eACE,EAAkB,EAAgB,IAtBnB,MAA+C;AAGxE,MAFA,EAAM,gBAAgB,EACtB,EAAM,iBAAiB,EACnB,KACF,EAAmB;OAAE;OAAgB;OAAW,CAAC;SAkBgB,KAAA;KAE1C;KACjB,UAAS;KACT,WAAU;KACV,WAAW;KACX,CAAA,CACE;OACN,kBAAC,GAAD,EAAoB,CAAA,CAChB;MACN,kBAAC,GAAD,EAAkB,WAAU,QAAS,CAAA,CACjC"}
|
|
1
|
+
{"version":3,"file":"conversation-name-with-status.js","names":[],"sources":["../../../../src/components/features/conversation/conversation-name-with-status.tsx"],"sourcesContent":["import React from \"react\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useTaskPolling } from \"#/hooks/query/use-task-polling\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUnifiedPauseConversation } from \"#/hooks/mutation/use-unified-stop-conversation\";\nimport { useUnifiedResumeConversation } from \"#/hooks/mutation/use-unified-start-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useUserProviders } from \"#/hooks/use-user-providers\";\nimport { getStatusColor } from \"#/utils/utils\";\nimport { AgentState } from \"#/types/agent-state\";\nimport DebugStackframeDot from \"#/icons/debug-stackframe-dot.svg?react\";\nimport { ServerStatusContextMenu } from \"../controls/server-status-context-menu\";\nimport { ConversationName } from \"./conversation-name\";\nimport { RightPanelToggle } from \"./right-panel-toggle\";\nimport {\n isExecutionActive,\n isExecutionErrored,\n isExecutionPaused,\n} from \"#/utils/status\";\n\nexport function ConversationNameWithStatus() {\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { curAgentState } = useAgentState();\n const { isTask, taskStatus } = useTaskPolling();\n const { mutate: pauseConversation } = useUnifiedPauseConversation();\n const { mutate: resumeConversation } = useUnifiedResumeConversation();\n const { providers } = useUserProviders();\n\n const executionStatus = conversation?.execution_status ?? null;\n const isStartingStatus =\n curAgentState === AgentState.LOADING || curAgentState === AgentState.INIT;\n const isStopStatus = isExecutionErrored(executionStatus);\n\n const statusColor = getStatusColor({\n isPausing: false,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n });\n\n const handleStopServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n pauseConversation({ conversationId });\n }\n };\n\n const handleStartServer = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (conversationId) {\n resumeConversation({ conversationId, providers });\n }\n };\n\n return (\n <div className=\"flex items-center justify-between w-full\">\n <div className=\"flex items-center min-w-0\">\n <div className=\"group relative shrink-0\">\n <DebugStackframeDot\n className=\"ml-[3.5px] w-6 h-6 cursor-pointer\"\n color={statusColor}\n />\n <ServerStatusContextMenu\n onClose={() => {}}\n onStopServer={\n isExecutionActive(executionStatus) ? handleStopServer : undefined\n }\n onStartServer={\n isExecutionPaused(executionStatus) ? handleStartServer : undefined\n }\n executionStatus={executionStatus}\n position=\"bottom\"\n className=\"opacity-0 invisible pointer-events-none group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto bottom-full left-0 mt-0 min-h-fit\"\n isPausing={false}\n />\n </div>\n <ConversationName />\n </div>\n <RightPanelToggle className=\"mr-2\" />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,SAAgB,IAA6B;CAC3C,IAAM,EAAE,sBAAmB,GAAmB,EACxC,EAAE,MAAM,MAAiB,GAAuB,EAChD,EAAE,qBAAkB,GAAe,EACnC,EAAE,WAAQ,kBAAe,GAAgB,EACzC,EAAE,QAAQ,MAAsB,GAA6B,EAC7D,EAAE,QAAQ,MAAuB,GAA8B,EAC/D,EAAE,iBAAc,GAAkB,EAElC,IAAkB,GAAc,oBAAoB;AA8B1D,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,WAAU;KACV,OA/BU,EAAe;MACjC,WAAW;MACX;MACA;MACA,kBAPA,MAAkB,EAAW,WAAW,MAAkB,EAAW;MAQrE,cAPmB,EAAmB,EAOtC;MACA;MACD,CAwBgB;KACP,CAAA,EACF,kBAAC,GAAD;KACE,eAAe;KACf,cACE,EAAkB,EAAgB,IA3BpB,MAA+C;AAGvE,MAFA,EAAM,gBAAgB,EACtB,EAAM,iBAAiB,EACnB,KACF,EAAkB,EAAE,mBAAgB,CAAC;SAuB2B,KAAA;KAE1D,eACE,EAAkB,EAAgB,IAtBnB,MAA+C;AAGxE,MAFA,EAAM,gBAAgB,EACtB,EAAM,iBAAiB,EACnB,KACF,EAAmB;OAAE;OAAgB;OAAW,CAAC;SAkBgB,KAAA;KAE1C;KACjB,UAAS;KACT,WAAU;KACV,WAAW;KACX,CAAA,CACE;OACN,kBAAC,GAAD,EAAoB,CAAA,CAChB;MACN,kBAAC,GAAD,EAAkB,WAAU,QAAS,CAAA,CACjC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../i18n/declaration.cjs`),r=require(`../../../hooks/use-conversation-id.cjs`),i=require(`../../../utils/custom-toast-handlers.cjs`),a=require(`../../../hooks/query/use-active-conversation.cjs`),o=require(`../../../hooks/use-conversation-name-context-menu.cjs`),s=require(`../conversation-panel/system-message-modal.cjs`),c=require(`../conversation-panel/skills-modal.cjs`),l=require(`../conversation-panel/hooks-modal.cjs`),u=require(`../../../hooks/mutation/use-update-conversation.cjs`),d=require(`../conversation-panel/ellipsis-button.cjs`),f=require(`./conversation-name-context-menu.cjs`),p=require(`../conversation-panel/confirm-delete-modal.cjs`),m=require(`../conversation-panel/confirm-stop-modal.cjs`),h=require(`./metrics-modal/metrics-modal.cjs`);let g=require(`react`);g=e.__toESM(g,1);let _=require(`react/jsx-runtime`);function v(){let{t:e}=t.useTranslation(`openhands`),{conversationId:v}=r.useConversationId(),{data:y}=a.useActiveConversation(),{mutate:b}=u.useUpdateConversation(),[x,S]=g.default.useState(`view`),[C,w]=g.default.useState(!1),T=g.default.useRef(null),E=g.default.useRef(null),{handleDelete:D,handleStop:O,handleDownloadConversation:k,handleDisplayCost:A,handleShowAgentTools:j,handleShowSkills:M,handleShowHooks:ee,handleTogglePublic:N,handleCopyShareLink:P,shareUrl:F,handleConfirmDelete:I,handleConfirmStop:L,metricsModalVisible:R,setMetricsModalVisible:z,systemModalVisible:B,setSystemModalVisible:V,skillsModalVisible:H,setSkillsModalVisible:U,hooksModalVisible:W,setHooksModalVisible:G,confirmDeleteModalVisible:K,setConfirmDeleteModalVisible:q,confirmStopModalVisible:J,setConfirmStopModalVisible:Y,systemMessage:X,shouldShowStop:Z,shouldShowDownloadConversation:Q,shouldShowDisplayCost:$,shouldShowAgentTools:te,shouldShowSkills:ne,shouldShowHooks:re}=o.useConversationNameContextMenu({conversationId:v,executionStatus:y?.execution_status,showOptions:!0,onContextMenuToggle:w});return g.default.useEffect(()=>{x===`edit`&&T.current?.focus()},[x]),y?(0,_.jsxs)(_.Fragment,{children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1`,"data-testid":`conversation-name`,children:[x===`edit`?(0,_.jsx)(`input`,{ref:T,"data-testid":`conversation-name-input`,onClick:e=>{x===`edit`&&(e.preventDefault(),e.stopPropagation())},onBlur:()=>{if(T.current?.value&&v){let t=T.current.value.trim();t!==y?.title&&b({conversationId:v,newTitle:t},{onSuccess:()=>{i.displaySuccessToast(e(n.I18nKey.CONVERSATION$TITLE_UPDATED))}})}else T.current&&(T.current.value=y?.title??``);S(`view`)},onKeyUp:e=>{e.nativeEvent.isComposing||e.key===`Enter`&&e.currentTarget.blur()},type:`text`,defaultValue:y.title||``,className:`text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content`}):(0,_.jsx)(`div`,{className:`text-white leading-5
|
|
1
|
+
const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../i18n/declaration.cjs`),r=require(`../../../hooks/use-conversation-id.cjs`),i=require(`../../../utils/custom-toast-handlers.cjs`),a=require(`../../../hooks/query/use-active-conversation.cjs`),o=require(`../../../hooks/use-conversation-name-context-menu.cjs`),s=require(`../conversation-panel/system-message-modal.cjs`),c=require(`../conversation-panel/skills-modal.cjs`),l=require(`../conversation-panel/hooks-modal.cjs`),u=require(`../../../hooks/mutation/use-update-conversation.cjs`),d=require(`../conversation-panel/ellipsis-button.cjs`),f=require(`./conversation-name-context-menu.cjs`),p=require(`../conversation-panel/confirm-delete-modal.cjs`),m=require(`../conversation-panel/confirm-stop-modal.cjs`),h=require(`./metrics-modal/metrics-modal.cjs`);let g=require(`react`);g=e.__toESM(g,1);let _=require(`react/jsx-runtime`);function v(){let{t:e}=t.useTranslation(`openhands`),{conversationId:v}=r.useConversationId(),{data:y}=a.useActiveConversation(),{mutate:b}=u.useUpdateConversation(),[x,S]=g.default.useState(`view`),[C,w]=g.default.useState(!1),T=g.default.useRef(null),E=g.default.useRef(null),{handleDelete:D,handleStop:O,handleDownloadConversation:k,handleDisplayCost:A,handleShowAgentTools:j,handleShowSkills:M,handleShowHooks:ee,handleTogglePublic:N,handleCopyShareLink:P,shareUrl:F,handleConfirmDelete:I,handleConfirmStop:L,metricsModalVisible:R,setMetricsModalVisible:z,systemModalVisible:B,setSystemModalVisible:V,skillsModalVisible:H,setSkillsModalVisible:U,hooksModalVisible:W,setHooksModalVisible:G,confirmDeleteModalVisible:K,setConfirmDeleteModalVisible:q,confirmStopModalVisible:J,setConfirmStopModalVisible:Y,systemMessage:X,shouldShowStop:Z,shouldShowDownloadConversation:Q,shouldShowDisplayCost:$,shouldShowAgentTools:te,shouldShowSkills:ne,shouldShowHooks:re}=o.useConversationNameContextMenu({conversationId:v,executionStatus:y?.execution_status,showOptions:!0,onContextMenuToggle:w});return g.default.useEffect(()=>{x===`edit`&&T.current?.focus()},[x]),y?(0,_.jsxs)(_.Fragment,{children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1 min-w-0`,"data-testid":`conversation-name`,children:[x===`edit`?(0,_.jsx)(`input`,{ref:T,"data-testid":`conversation-name-input`,onClick:e=>{x===`edit`&&(e.preventDefault(),e.stopPropagation())},onBlur:()=>{if(T.current?.value&&v){let t=T.current.value.trim();t!==y?.title&&b({conversationId:v,newTitle:t},{onSuccess:()=>{i.displaySuccessToast(e(n.I18nKey.CONVERSATION$TITLE_UPDATED))}})}else T.current&&(T.current.value=y?.title??``);S(`view`)},onKeyUp:e=>{e.nativeEvent.isComposing||e.key===`Enter`&&e.currentTarget.blur()},type:`text`,defaultValue:y.title||``,className:`text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content`}):(0,_.jsx)(`div`,{className:`text-white leading-5 truncate`,"data-testid":`conversation-name-title`,onDoubleClick:()=>{S(`edit`)},title:y.title||``,children:y.title}),x!==`edit`&&(0,_.jsxs)(`div`,{ref:E,className:`relative flex items-center shrink-0`,children:[(0,_.jsx)(d.EllipsisButton,{onClick:e=>{e.preventDefault(),e.stopPropagation(),w(!C)}}),C&&(0,_.jsx)(f.ConversationNameContextMenu,{onClose:()=>w(!1),onRename:e=>{e.preventDefault(),e.stopPropagation(),S(`edit`),w(!1)},onDelete:D,onStop:Z?O:void 0,onDisplayCost:$?A:void 0,onShowAgentTools:te?j:void 0,onShowSkills:ne?M:void 0,onShowHooks:re?ee:void 0,onTogglePublic:N,onCopyShareLink:P,shareUrl:F,onDownloadConversation:Q?k:void 0,position:`bottom`,anchorRef:E})]})]}),(0,_.jsx)(h.MetricsModal,{isOpen:R,onOpenChange:z}),(0,_.jsx)(s.SystemMessageModal,{isOpen:B,onClose:()=>V(!1),systemMessage:X||null}),H&&(0,_.jsx)(c.SkillsModal,{onClose:()=>U(!1)}),W&&(0,_.jsx)(l.HooksModal,{onClose:()=>G(!1)}),K&&(0,_.jsx)(p.ConfirmDeleteModal,{onConfirm:I,onCancel:()=>q(!1),conversationTitle:y?.title||``}),J&&(0,_.jsx)(m.ConfirmStopModal,{onConfirm:L,onCancel:()=>Y(!1)})]}):null}exports.ConversationName=v;
|
|
2
2
|
//# sourceMappingURL=conversation-name.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-name.cjs","names":[],"sources":["../../../../src/components/features/conversation/conversation-name.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUpdateConversation } from \"#/hooks/mutation/use-update-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationNameContextMenu } from \"#/hooks/use-conversation-name-context-menu\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { EllipsisButton } from \"../conversation-panel/ellipsis-button\";\nimport { ConversationNameContextMenu } from \"./conversation-name-context-menu\";\nimport { SystemMessageModal } from \"../conversation-panel/system-message-modal\";\nimport { SkillsModal } from \"../conversation-panel/skills-modal\";\nimport { HooksModal } from \"../conversation-panel/hooks-modal\";\nimport { ConfirmDeleteModal } from \"../conversation-panel/confirm-delete-modal\";\nimport { ConfirmStopModal } from \"../conversation-panel/confirm-stop-modal\";\nimport { MetricsModal } from \"./metrics-modal/metrics-modal\";\n\nexport function ConversationName() {\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { mutate: updateConversation } = useUpdateConversation();\n\n const [titleMode, setTitleMode] = React.useState<\"view\" | \"edit\">(\"view\");\n const [contextMenuOpen, setContextMenuOpen] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const ellipsisAnchorRef = React.useRef<HTMLDivElement>(null);\n\n // Use the custom hook for context menu handlers\n const {\n handleDelete,\n handleStop,\n handleDownloadConversation,\n handleDisplayCost,\n handleShowAgentTools,\n handleShowSkills,\n handleShowHooks,\n handleTogglePublic,\n handleCopyShareLink,\n shareUrl,\n handleConfirmDelete,\n handleConfirmStop,\n metricsModalVisible,\n setMetricsModalVisible,\n systemModalVisible,\n setSystemModalVisible,\n skillsModalVisible,\n setSkillsModalVisible,\n hooksModalVisible,\n setHooksModalVisible,\n confirmDeleteModalVisible,\n setConfirmDeleteModalVisible,\n confirmStopModalVisible,\n setConfirmStopModalVisible,\n systemMessage,\n shouldShowStop,\n shouldShowDownloadConversation,\n shouldShowDisplayCost,\n shouldShowAgentTools,\n shouldShowSkills,\n shouldShowHooks,\n } = useConversationNameContextMenu({\n conversationId,\n executionStatus: conversation?.execution_status,\n showOptions: true,\n onContextMenuToggle: setContextMenuOpen,\n });\n\n const handleDoubleClick = () => {\n setTitleMode(\"edit\");\n };\n\n const handleBlur = () => {\n if (inputRef.current?.value && conversationId) {\n const trimmed = inputRef.current.value.trim();\n if (trimmed !== conversation?.title) {\n updateConversation(\n { conversationId, newTitle: trimmed },\n {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.CONVERSATION$TITLE_UPDATED));\n },\n },\n );\n }\n } else if (inputRef.current) {\n // reset the value if it's empty\n inputRef.current.value = conversation?.title ?? \"\";\n }\n\n setTitleMode(\"view\");\n };\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {\n // Ignore Enter key during IME composition (e.g., Chinese, Japanese, Korean input)\n if (event.nativeEvent.isComposing) {\n return;\n }\n if (event.key === \"Enter\") {\n event.currentTarget.blur();\n }\n };\n\n const handleInputClick = (event: React.MouseEvent<HTMLInputElement>) => {\n if (titleMode === \"edit\") {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n const handleEllipsisClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setContextMenuOpen(!contextMenuOpen);\n };\n\n const handleRename = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setTitleMode(\"edit\");\n setContextMenuOpen(false);\n };\n\n React.useEffect(() => {\n if (titleMode === \"edit\") {\n inputRef.current?.focus();\n }\n }, [titleMode]);\n\n if (!conversation) {\n return null;\n }\n\n return (\n <>\n <div\n className=\"flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1\"\n data-testid=\"conversation-name\"\n >\n {titleMode === \"edit\" ? (\n <input\n ref={inputRef}\n data-testid=\"conversation-name-input\"\n onClick={handleInputClick}\n onBlur={handleBlur}\n onKeyUp={handleKeyUp}\n type=\"text\"\n defaultValue={conversation.title || \"\"}\n className=\"text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content\"\n />\n ) : (\n <div\n className=\"text-white leading-5 w-fit max-w-fit truncate\"\n data-testid=\"conversation-name-title\"\n onDoubleClick={handleDoubleClick}\n title={conversation.title || \"\"}\n >\n {conversation.title}\n </div>\n )}\n\n {titleMode !== \"edit\" && (\n <div ref={ellipsisAnchorRef} className=\"relative flex items-center\">\n <EllipsisButton onClick={handleEllipsisClick} />\n {contextMenuOpen && (\n <ConversationNameContextMenu\n onClose={() => setContextMenuOpen(false)}\n onRename={handleRename}\n onDelete={handleDelete}\n onStop={shouldShowStop ? handleStop : undefined}\n onDisplayCost={\n shouldShowDisplayCost ? handleDisplayCost : undefined\n }\n onShowAgentTools={\n shouldShowAgentTools ? handleShowAgentTools : undefined\n }\n onShowSkills={shouldShowSkills ? handleShowSkills : undefined}\n onShowHooks={shouldShowHooks ? handleShowHooks : undefined}\n onTogglePublic={handleTogglePublic}\n onCopyShareLink={handleCopyShareLink}\n shareUrl={shareUrl}\n onDownloadConversation={\n shouldShowDownloadConversation\n ? handleDownloadConversation\n : undefined\n }\n position=\"bottom\"\n anchorRef={ellipsisAnchorRef}\n />\n )}\n </div>\n )}\n </div>\n\n {/* Metrics Modal */}\n <MetricsModal\n isOpen={metricsModalVisible}\n onOpenChange={setMetricsModalVisible}\n />\n\n {/* System Message Modal */}\n <SystemMessageModal\n isOpen={systemModalVisible}\n onClose={() => setSystemModalVisible(false)}\n systemMessage={systemMessage || null}\n />\n\n {/* Skills Modal */}\n {skillsModalVisible && (\n <SkillsModal onClose={() => setSkillsModalVisible(false)} />\n )}\n\n {/* Hooks Modal */}\n {hooksModalVisible && (\n <HooksModal onClose={() => setHooksModalVisible(false)} />\n )}\n\n {/* Confirm Delete Modal */}\n {confirmDeleteModalVisible && (\n <ConfirmDeleteModal\n onConfirm={handleConfirmDelete}\n onCancel={() => setConfirmDeleteModalVisible(false)}\n conversationTitle={conversation?.title || \"\"}\n />\n )}\n\n {confirmStopModalVisible && (\n <ConfirmStopModal\n onConfirm={handleConfirmStop}\n onCancel={() => setConfirmStopModalVisible(false)}\n />\n )}\n </>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conversation-name.cjs","names":[],"sources":["../../../../src/components/features/conversation/conversation-name.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUpdateConversation } from \"#/hooks/mutation/use-update-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationNameContextMenu } from \"#/hooks/use-conversation-name-context-menu\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { EllipsisButton } from \"../conversation-panel/ellipsis-button\";\nimport { ConversationNameContextMenu } from \"./conversation-name-context-menu\";\nimport { SystemMessageModal } from \"../conversation-panel/system-message-modal\";\nimport { SkillsModal } from \"../conversation-panel/skills-modal\";\nimport { HooksModal } from \"../conversation-panel/hooks-modal\";\nimport { ConfirmDeleteModal } from \"../conversation-panel/confirm-delete-modal\";\nimport { ConfirmStopModal } from \"../conversation-panel/confirm-stop-modal\";\nimport { MetricsModal } from \"./metrics-modal/metrics-modal\";\n\nexport function ConversationName() {\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { mutate: updateConversation } = useUpdateConversation();\n\n const [titleMode, setTitleMode] = React.useState<\"view\" | \"edit\">(\"view\");\n const [contextMenuOpen, setContextMenuOpen] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const ellipsisAnchorRef = React.useRef<HTMLDivElement>(null);\n\n // Use the custom hook for context menu handlers\n const {\n handleDelete,\n handleStop,\n handleDownloadConversation,\n handleDisplayCost,\n handleShowAgentTools,\n handleShowSkills,\n handleShowHooks,\n handleTogglePublic,\n handleCopyShareLink,\n shareUrl,\n handleConfirmDelete,\n handleConfirmStop,\n metricsModalVisible,\n setMetricsModalVisible,\n systemModalVisible,\n setSystemModalVisible,\n skillsModalVisible,\n setSkillsModalVisible,\n hooksModalVisible,\n setHooksModalVisible,\n confirmDeleteModalVisible,\n setConfirmDeleteModalVisible,\n confirmStopModalVisible,\n setConfirmStopModalVisible,\n systemMessage,\n shouldShowStop,\n shouldShowDownloadConversation,\n shouldShowDisplayCost,\n shouldShowAgentTools,\n shouldShowSkills,\n shouldShowHooks,\n } = useConversationNameContextMenu({\n conversationId,\n executionStatus: conversation?.execution_status,\n showOptions: true,\n onContextMenuToggle: setContextMenuOpen,\n });\n\n const handleDoubleClick = () => {\n setTitleMode(\"edit\");\n };\n\n const handleBlur = () => {\n if (inputRef.current?.value && conversationId) {\n const trimmed = inputRef.current.value.trim();\n if (trimmed !== conversation?.title) {\n updateConversation(\n { conversationId, newTitle: trimmed },\n {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.CONVERSATION$TITLE_UPDATED));\n },\n },\n );\n }\n } else if (inputRef.current) {\n // reset the value if it's empty\n inputRef.current.value = conversation?.title ?? \"\";\n }\n\n setTitleMode(\"view\");\n };\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {\n // Ignore Enter key during IME composition (e.g., Chinese, Japanese, Korean input)\n if (event.nativeEvent.isComposing) {\n return;\n }\n if (event.key === \"Enter\") {\n event.currentTarget.blur();\n }\n };\n\n const handleInputClick = (event: React.MouseEvent<HTMLInputElement>) => {\n if (titleMode === \"edit\") {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n const handleEllipsisClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setContextMenuOpen(!contextMenuOpen);\n };\n\n const handleRename = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setTitleMode(\"edit\");\n setContextMenuOpen(false);\n };\n\n React.useEffect(() => {\n if (titleMode === \"edit\") {\n inputRef.current?.focus();\n }\n }, [titleMode]);\n\n if (!conversation) {\n return null;\n }\n\n return (\n <>\n <div\n className=\"flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1 min-w-0\"\n data-testid=\"conversation-name\"\n >\n {titleMode === \"edit\" ? (\n <input\n ref={inputRef}\n data-testid=\"conversation-name-input\"\n onClick={handleInputClick}\n onBlur={handleBlur}\n onKeyUp={handleKeyUp}\n type=\"text\"\n defaultValue={conversation.title || \"\"}\n className=\"text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content\"\n />\n ) : (\n <div\n className=\"text-white leading-5 truncate\"\n data-testid=\"conversation-name-title\"\n onDoubleClick={handleDoubleClick}\n title={conversation.title || \"\"}\n >\n {conversation.title}\n </div>\n )}\n\n {titleMode !== \"edit\" && (\n <div\n ref={ellipsisAnchorRef}\n className=\"relative flex items-center shrink-0\"\n >\n <EllipsisButton onClick={handleEllipsisClick} />\n {contextMenuOpen && (\n <ConversationNameContextMenu\n onClose={() => setContextMenuOpen(false)}\n onRename={handleRename}\n onDelete={handleDelete}\n onStop={shouldShowStop ? handleStop : undefined}\n onDisplayCost={\n shouldShowDisplayCost ? handleDisplayCost : undefined\n }\n onShowAgentTools={\n shouldShowAgentTools ? handleShowAgentTools : undefined\n }\n onShowSkills={shouldShowSkills ? handleShowSkills : undefined}\n onShowHooks={shouldShowHooks ? handleShowHooks : undefined}\n onTogglePublic={handleTogglePublic}\n onCopyShareLink={handleCopyShareLink}\n shareUrl={shareUrl}\n onDownloadConversation={\n shouldShowDownloadConversation\n ? handleDownloadConversation\n : undefined\n }\n position=\"bottom\"\n anchorRef={ellipsisAnchorRef}\n />\n )}\n </div>\n )}\n </div>\n\n {/* Metrics Modal */}\n <MetricsModal\n isOpen={metricsModalVisible}\n onOpenChange={setMetricsModalVisible}\n />\n\n {/* System Message Modal */}\n <SystemMessageModal\n isOpen={systemModalVisible}\n onClose={() => setSystemModalVisible(false)}\n systemMessage={systemMessage || null}\n />\n\n {/* Skills Modal */}\n {skillsModalVisible && (\n <SkillsModal onClose={() => setSkillsModalVisible(false)} />\n )}\n\n {/* Hooks Modal */}\n {hooksModalVisible && (\n <HooksModal onClose={() => setHooksModalVisible(false)} />\n )}\n\n {/* Confirm Delete Modal */}\n {confirmDeleteModalVisible && (\n <ConfirmDeleteModal\n onConfirm={handleConfirmDelete}\n onCancel={() => setConfirmDeleteModalVisible(false)}\n conversationTitle={conversation?.title || \"\"}\n />\n )}\n\n {confirmStopModalVisible && (\n <ConfirmStopModal\n onConfirm={handleConfirmStop}\n onCancel={() => setConfirmStopModalVisible(false)}\n />\n )}\n </>\n );\n}\n"],"mappings":"09BAiBA,SAAgB,GAAmB,CACjC,GAAM,CAAE,KAAM,EAAA,eAAe,YAAY,CACnC,CAAE,kBAAmB,EAAA,mBAAmB,CACxC,CAAE,KAAM,GAAiB,EAAA,uBAAuB,CAChD,CAAE,OAAQ,GAAuB,EAAA,uBAAuB,CAExD,CAAC,EAAW,GAAgB,EAAA,QAAM,SAA0B,OAAO,CACnE,CAAC,EAAiB,GAAsB,EAAA,QAAM,SAAS,GAAM,CAC7D,EAAW,EAAA,QAAM,OAAyB,KAAK,CAC/C,EAAoB,EAAA,QAAM,OAAuB,KAAK,CAGtD,CACJ,eACA,aACA,6BACA,oBACA,uBACA,mBACA,mBACA,qBACA,sBACA,WACA,sBACA,oBACA,sBACA,yBACA,qBACA,wBACA,qBACA,wBACA,oBACA,uBACA,4BACA,+BACA,0BACA,6BACA,gBACA,iBACA,iCACA,wBACA,wBACA,oBACA,oBACE,EAAA,+BAA+B,CACjC,iBACA,gBAAiB,GAAc,iBAC/B,YAAa,GACb,oBAAqB,EACtB,CAAC,CAmEF,OAVA,EAAA,QAAM,cAAgB,CAChB,IAAc,QAChB,EAAS,SAAS,OAAO,EAE1B,CAAC,EAAU,CAAC,CAEV,GAKH,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,MAAC,MAAD,CACE,UAAU,wFACV,cAAY,6BAFd,CAIG,IAAc,QACb,EAAA,EAAA,KAAC,QAAD,CACE,IAAK,EACL,cAAY,0BACZ,QAxCgB,GAA8C,CAClE,IAAc,SAChB,EAAM,gBAAgB,CACtB,EAAM,iBAAiB,GAsCjB,WAxEe,CACvB,GAAI,EAAS,SAAS,OAAS,EAAgB,CAC7C,IAAM,EAAU,EAAS,QAAQ,MAAM,MAAM,CACzC,IAAY,GAAc,OAC5B,EACE,CAAE,iBAAgB,SAAU,EAAS,CACrC,CACE,cAAiB,CACf,EAAA,oBAAoB,EAAE,EAAA,QAAQ,2BAA2B,CAAC,EAE7D,CACF,MAEM,EAAS,UAElB,EAAS,QAAQ,MAAQ,GAAc,OAAS,IAGlD,EAAa,OAAO,EAuDZ,QApDW,GAAiD,CAEhE,EAAM,YAAY,aAGlB,EAAM,MAAQ,SAChB,EAAM,cAAc,MAAM,EA+CpB,KAAK,OACL,aAAc,EAAa,OAAS,GACpC,UAAU,0HACV,CAAA,EAEF,EAAA,EAAA,KAAC,MAAD,CACE,UAAU,gCACV,cAAY,0BACZ,kBAtFsB,CAC9B,EAAa,OAAO,EAsFZ,MAAO,EAAa,OAAS,YAE5B,EAAa,MACV,CAAA,CAGP,IAAc,SACb,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,UAAU,+CAFZ,EAIE,EAAA,EAAA,KAAC,EAAA,eAAD,CAAgB,QAxDG,GAA+C,CAC1E,EAAM,gBAAgB,CACtB,EAAM,iBAAiB,CACvB,EAAmB,CAAC,EAAgB,EAqDoB,CAAA,CAC/C,IACC,EAAA,EAAA,KAAC,EAAA,4BAAD,CACE,YAAe,EAAmB,GAAM,CACxC,SAtDQ,GAA+C,CACnE,EAAM,gBAAgB,CACtB,EAAM,iBAAiB,CACvB,EAAa,OAAO,CACpB,EAAmB,GAAM,EAmDb,SAAU,EACV,OAAQ,EAAiB,EAAa,IAAA,GACtC,cACE,EAAwB,EAAoB,IAAA,GAE9C,iBACE,GAAuB,EAAuB,IAAA,GAEhD,aAAc,GAAmB,EAAmB,IAAA,GACpD,YAAa,GAAkB,GAAkB,IAAA,GACjD,eAAgB,EAChB,gBAAiB,EACP,WACV,uBACE,EACI,EACA,IAAA,GAEN,SAAS,SACT,UAAW,EACX,CAAA,CAEA,GAEJ,IAGN,EAAA,EAAA,KAAC,EAAA,aAAD,CACE,OAAQ,EACR,aAAc,EACd,CAAA,EAGF,EAAA,EAAA,KAAC,EAAA,mBAAD,CACE,OAAQ,EACR,YAAe,EAAsB,GAAM,CAC3C,cAAe,GAAiB,KAChC,CAAA,CAGD,IACC,EAAA,EAAA,KAAC,EAAA,YAAD,CAAa,YAAe,EAAsB,GAAM,CAAI,CAAA,CAI7D,IACC,EAAA,EAAA,KAAC,EAAA,WAAD,CAAY,YAAe,EAAqB,GAAM,CAAI,CAAA,CAI3D,IACC,EAAA,EAAA,KAAC,EAAA,mBAAD,CACE,UAAW,EACX,aAAgB,EAA6B,GAAM,CACnD,kBAAmB,GAAc,OAAS,GAC1C,CAAA,CAGH,IACC,EAAA,EAAA,KAAC,EAAA,iBAAD,CACE,UAAW,EACX,aAAgB,EAA2B,GAAM,CACjD,CAAA,CAEH,CAAA,CAAA,CAzGI"}
|
|
@@ -27,7 +27,7 @@ function y() {
|
|
|
27
27
|
C === "edit" && D.current?.focus();
|
|
28
28
|
}, [C]), x ? /* @__PURE__ */ v(g, { children: [
|
|
29
29
|
/* @__PURE__ */ v("div", {
|
|
30
|
-
className: "flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1",
|
|
30
|
+
className: "flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1 min-w-0",
|
|
31
31
|
"data-testid": "conversation-name",
|
|
32
32
|
children: [C === "edit" ? /* @__PURE__ */ _("input", {
|
|
33
33
|
ref: D,
|
|
@@ -54,7 +54,7 @@ function y() {
|
|
|
54
54
|
defaultValue: x.title || "",
|
|
55
55
|
className: "text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content"
|
|
56
56
|
}) : /* @__PURE__ */ _("div", {
|
|
57
|
-
className: "text-white leading-5
|
|
57
|
+
className: "text-white leading-5 truncate",
|
|
58
58
|
"data-testid": "conversation-name-title",
|
|
59
59
|
onDoubleClick: () => {
|
|
60
60
|
w("edit");
|
|
@@ -63,7 +63,7 @@ function y() {
|
|
|
63
63
|
children: x.title
|
|
64
64
|
}), C !== "edit" && /* @__PURE__ */ v("div", {
|
|
65
65
|
ref: O,
|
|
66
|
-
className: "relative flex items-center",
|
|
66
|
+
className: "relative flex items-center shrink-0",
|
|
67
67
|
children: [/* @__PURE__ */ _(u, { onClick: (e) => {
|
|
68
68
|
e.preventDefault(), e.stopPropagation(), E(!T);
|
|
69
69
|
} }), T && /* @__PURE__ */ _(d, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-name.js","names":[],"sources":["../../../../src/components/features/conversation/conversation-name.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUpdateConversation } from \"#/hooks/mutation/use-update-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationNameContextMenu } from \"#/hooks/use-conversation-name-context-menu\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { EllipsisButton } from \"../conversation-panel/ellipsis-button\";\nimport { ConversationNameContextMenu } from \"./conversation-name-context-menu\";\nimport { SystemMessageModal } from \"../conversation-panel/system-message-modal\";\nimport { SkillsModal } from \"../conversation-panel/skills-modal\";\nimport { HooksModal } from \"../conversation-panel/hooks-modal\";\nimport { ConfirmDeleteModal } from \"../conversation-panel/confirm-delete-modal\";\nimport { ConfirmStopModal } from \"../conversation-panel/confirm-stop-modal\";\nimport { MetricsModal } from \"./metrics-modal/metrics-modal\";\n\nexport function ConversationName() {\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { mutate: updateConversation } = useUpdateConversation();\n\n const [titleMode, setTitleMode] = React.useState<\"view\" | \"edit\">(\"view\");\n const [contextMenuOpen, setContextMenuOpen] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const ellipsisAnchorRef = React.useRef<HTMLDivElement>(null);\n\n // Use the custom hook for context menu handlers\n const {\n handleDelete,\n handleStop,\n handleDownloadConversation,\n handleDisplayCost,\n handleShowAgentTools,\n handleShowSkills,\n handleShowHooks,\n handleTogglePublic,\n handleCopyShareLink,\n shareUrl,\n handleConfirmDelete,\n handleConfirmStop,\n metricsModalVisible,\n setMetricsModalVisible,\n systemModalVisible,\n setSystemModalVisible,\n skillsModalVisible,\n setSkillsModalVisible,\n hooksModalVisible,\n setHooksModalVisible,\n confirmDeleteModalVisible,\n setConfirmDeleteModalVisible,\n confirmStopModalVisible,\n setConfirmStopModalVisible,\n systemMessage,\n shouldShowStop,\n shouldShowDownloadConversation,\n shouldShowDisplayCost,\n shouldShowAgentTools,\n shouldShowSkills,\n shouldShowHooks,\n } = useConversationNameContextMenu({\n conversationId,\n executionStatus: conversation?.execution_status,\n showOptions: true,\n onContextMenuToggle: setContextMenuOpen,\n });\n\n const handleDoubleClick = () => {\n setTitleMode(\"edit\");\n };\n\n const handleBlur = () => {\n if (inputRef.current?.value && conversationId) {\n const trimmed = inputRef.current.value.trim();\n if (trimmed !== conversation?.title) {\n updateConversation(\n { conversationId, newTitle: trimmed },\n {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.CONVERSATION$TITLE_UPDATED));\n },\n },\n );\n }\n } else if (inputRef.current) {\n // reset the value if it's empty\n inputRef.current.value = conversation?.title ?? \"\";\n }\n\n setTitleMode(\"view\");\n };\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {\n // Ignore Enter key during IME composition (e.g., Chinese, Japanese, Korean input)\n if (event.nativeEvent.isComposing) {\n return;\n }\n if (event.key === \"Enter\") {\n event.currentTarget.blur();\n }\n };\n\n const handleInputClick = (event: React.MouseEvent<HTMLInputElement>) => {\n if (titleMode === \"edit\") {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n const handleEllipsisClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setContextMenuOpen(!contextMenuOpen);\n };\n\n const handleRename = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setTitleMode(\"edit\");\n setContextMenuOpen(false);\n };\n\n React.useEffect(() => {\n if (titleMode === \"edit\") {\n inputRef.current?.focus();\n }\n }, [titleMode]);\n\n if (!conversation) {\n return null;\n }\n\n return (\n <>\n <div\n className=\"flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1\"\n data-testid=\"conversation-name\"\n >\n {titleMode === \"edit\" ? (\n <input\n ref={inputRef}\n data-testid=\"conversation-name-input\"\n onClick={handleInputClick}\n onBlur={handleBlur}\n onKeyUp={handleKeyUp}\n type=\"text\"\n defaultValue={conversation.title || \"\"}\n className=\"text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content\"\n />\n ) : (\n <div\n className=\"text-white leading-5 w-fit max-w-fit truncate\"\n data-testid=\"conversation-name-title\"\n onDoubleClick={handleDoubleClick}\n title={conversation.title || \"\"}\n >\n {conversation.title}\n </div>\n )}\n\n {titleMode !== \"edit\" && (\n <div ref={ellipsisAnchorRef} className=\"relative flex items-center\">\n <EllipsisButton onClick={handleEllipsisClick} />\n {contextMenuOpen && (\n <ConversationNameContextMenu\n onClose={() => setContextMenuOpen(false)}\n onRename={handleRename}\n onDelete={handleDelete}\n onStop={shouldShowStop ? handleStop : undefined}\n onDisplayCost={\n shouldShowDisplayCost ? handleDisplayCost : undefined\n }\n onShowAgentTools={\n shouldShowAgentTools ? handleShowAgentTools : undefined\n }\n onShowSkills={shouldShowSkills ? handleShowSkills : undefined}\n onShowHooks={shouldShowHooks ? handleShowHooks : undefined}\n onTogglePublic={handleTogglePublic}\n onCopyShareLink={handleCopyShareLink}\n shareUrl={shareUrl}\n onDownloadConversation={\n shouldShowDownloadConversation\n ? handleDownloadConversation\n : undefined\n }\n position=\"bottom\"\n anchorRef={ellipsisAnchorRef}\n />\n )}\n </div>\n )}\n </div>\n\n {/* Metrics Modal */}\n <MetricsModal\n isOpen={metricsModalVisible}\n onOpenChange={setMetricsModalVisible}\n />\n\n {/* System Message Modal */}\n <SystemMessageModal\n isOpen={systemModalVisible}\n onClose={() => setSystemModalVisible(false)}\n systemMessage={systemMessage || null}\n />\n\n {/* Skills Modal */}\n {skillsModalVisible && (\n <SkillsModal onClose={() => setSkillsModalVisible(false)} />\n )}\n\n {/* Hooks Modal */}\n {hooksModalVisible && (\n <HooksModal onClose={() => setHooksModalVisible(false)} />\n )}\n\n {/* Confirm Delete Modal */}\n {confirmDeleteModalVisible && (\n <ConfirmDeleteModal\n onConfirm={handleConfirmDelete}\n onCancel={() => setConfirmDeleteModalVisible(false)}\n conversationTitle={conversation?.title || \"\"}\n />\n )}\n\n {confirmStopModalVisible && (\n <ConfirmStopModal\n onConfirm={handleConfirmStop}\n onCancel={() => setConfirmStopModalVisible(false)}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,SAAgB,IAAmB;CACjC,IAAM,EAAE,SAAM,EAAe,YAAY,EACnC,EAAE,sBAAmB,GAAmB,EACxC,EAAE,MAAM,MAAiB,GAAuB,EAChD,EAAE,QAAQ,MAAuB,GAAuB,EAExD,CAAC,GAAW,KAAgB,EAAM,SAA0B,OAAO,EACnE,CAAC,GAAiB,KAAsB,EAAM,SAAS,GAAM,EAC7D,IAAW,EAAM,OAAyB,KAAK,EAC/C,IAAoB,EAAM,OAAuB,KAAK,EAGtD,EACJ,iBACA,eACA,+BACA,sBACA,yBACA,sBACA,oBACA,uBACA,wBACA,aACA,wBACA,sBACA,wBACA,2BACA,uBACA,0BACA,uBACA,0BACA,sBACA,yBACA,8BACA,iCACA,4BACA,+BACA,kBACA,mBACA,oCACA,2BACA,0BACA,sBACA,wBACE,EAA+B;EACjC;EACA,iBAAiB,GAAc;EAC/B,aAAa;EACb,qBAAqB;EACtB,CAAC;AAmEF,QAVA,EAAM,gBAAgB;AACpB,EAAI,MAAc,UAChB,EAAS,SAAS,OAAO;IAE1B,CAAC,EAAU,CAAC,EAEV,IAKH,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,OAAD;GACE,WAAU;GACV,eAAY;aAFd,CAIG,MAAc,SACb,kBAAC,SAAD;IACE,KAAK;IACL,eAAY;IACZ,UAxCgB,MAA8C;AACtE,KAAI,MAAc,WAChB,EAAM,gBAAgB,EACtB,EAAM,iBAAiB;;IAsCjB,cAxEe;AACvB,SAAI,EAAS,SAAS,SAAS,GAAgB;MAC7C,IAAM,IAAU,EAAS,QAAQ,MAAM,MAAM;AAC7C,MAAI,MAAY,GAAc,SAC5B,EACE;OAAE;OAAgB,UAAU;OAAS,EACrC,EACE,iBAAiB;AACf,SAAoB,EAAE,EAAQ,2BAA2B,CAAC;SAE7D,CACF;YAEM,EAAS,YAElB,EAAS,QAAQ,QAAQ,GAAc,SAAS;AAGlD,OAAa,OAAO;;IAuDZ,UApDW,MAAiD;AAEhE,OAAM,YAAY,eAGlB,EAAM,QAAQ,WAChB,EAAM,cAAc,MAAM;;IA+CpB,MAAK;IACL,cAAc,EAAa,SAAS;IACpC,WAAU;IACV,CAAA,GAEF,kBAAC,OAAD;IACE,WAAU;IACV,eAAY;IACZ,qBAtFsB;AAC9B,OAAa,OAAO;;IAsFZ,OAAO,EAAa,SAAS;cAE5B,EAAa;IACV,CAAA,EAGP,MAAc,UACb,kBAAC,OAAD;IAAK,KAAK;IAAmB,WAAU;cAAvC,CACE,kBAAC,GAAD,EAAgB,UArDG,MAA+C;AAG1E,KAFA,EAAM,gBAAgB,EACtB,EAAM,iBAAiB,EACvB,EAAmB,CAAC,EAAgB;OAkDoB,CAAA,EAC/C,KACC,kBAAC,GAAD;KACE,eAAe,EAAmB,GAAM;KACxC,WAnDQ,MAA+C;AAInE,MAHA,EAAM,gBAAgB,EACtB,EAAM,iBAAiB,EACvB,EAAa,OAAO,EACpB,EAAmB,GAAM;;KAgDb,UAAU;KACV,QAAQ,IAAiB,IAAa,KAAA;KACtC,eACE,KAAwB,IAAoB,KAAA;KAE9C,kBACE,KAAuB,IAAuB,KAAA;KAEhD,cAAc,KAAmB,KAAmB,KAAA;KACpD,aAAa,KAAkB,IAAkB,KAAA;KACjD,gBAAgB;KAChB,iBAAiB;KACP;KACV,wBACE,KACI,IACA,KAAA;KAEN,UAAS;KACT,WAAW;KACX,CAAA,CAEA;MAEJ;;EAGN,kBAAC,GAAD;GACE,QAAQ;GACR,cAAc;GACd,CAAA;EAGF,kBAAC,GAAD;GACE,QAAQ;GACR,eAAe,EAAsB,GAAM;GAC3C,eAAe,KAAiB;GAChC,CAAA;EAGD,KACC,kBAAC,GAAD,EAAa,eAAe,EAAsB,GAAM,EAAI,CAAA;EAI7D,KACC,kBAAC,GAAD,EAAY,eAAe,EAAqB,GAAM,EAAI,CAAA;EAI3D,KACC,kBAAC,GAAD;GACE,WAAW;GACX,gBAAgB,EAA6B,GAAM;GACnD,mBAAmB,GAAc,SAAS;GAC1C,CAAA;EAGH,KACC,kBAAC,GAAD;GACE,WAAW;GACX,gBAAgB,EAA2B,GAAM;GACjD,CAAA;EAEH,EAAA,CAAA,GAtGI"}
|
|
1
|
+
{"version":3,"file":"conversation-name.js","names":[],"sources":["../../../../src/components/features/conversation/conversation-name.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useUpdateConversation } from \"#/hooks/mutation/use-update-conversation\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationNameContextMenu } from \"#/hooks/use-conversation-name-context-menu\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { EllipsisButton } from \"../conversation-panel/ellipsis-button\";\nimport { ConversationNameContextMenu } from \"./conversation-name-context-menu\";\nimport { SystemMessageModal } from \"../conversation-panel/system-message-modal\";\nimport { SkillsModal } from \"../conversation-panel/skills-modal\";\nimport { HooksModal } from \"../conversation-panel/hooks-modal\";\nimport { ConfirmDeleteModal } from \"../conversation-panel/confirm-delete-modal\";\nimport { ConfirmStopModal } from \"../conversation-panel/confirm-stop-modal\";\nimport { MetricsModal } from \"./metrics-modal/metrics-modal\";\n\nexport function ConversationName() {\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const { data: conversation } = useActiveConversation();\n const { mutate: updateConversation } = useUpdateConversation();\n\n const [titleMode, setTitleMode] = React.useState<\"view\" | \"edit\">(\"view\");\n const [contextMenuOpen, setContextMenuOpen] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const ellipsisAnchorRef = React.useRef<HTMLDivElement>(null);\n\n // Use the custom hook for context menu handlers\n const {\n handleDelete,\n handleStop,\n handleDownloadConversation,\n handleDisplayCost,\n handleShowAgentTools,\n handleShowSkills,\n handleShowHooks,\n handleTogglePublic,\n handleCopyShareLink,\n shareUrl,\n handleConfirmDelete,\n handleConfirmStop,\n metricsModalVisible,\n setMetricsModalVisible,\n systemModalVisible,\n setSystemModalVisible,\n skillsModalVisible,\n setSkillsModalVisible,\n hooksModalVisible,\n setHooksModalVisible,\n confirmDeleteModalVisible,\n setConfirmDeleteModalVisible,\n confirmStopModalVisible,\n setConfirmStopModalVisible,\n systemMessage,\n shouldShowStop,\n shouldShowDownloadConversation,\n shouldShowDisplayCost,\n shouldShowAgentTools,\n shouldShowSkills,\n shouldShowHooks,\n } = useConversationNameContextMenu({\n conversationId,\n executionStatus: conversation?.execution_status,\n showOptions: true,\n onContextMenuToggle: setContextMenuOpen,\n });\n\n const handleDoubleClick = () => {\n setTitleMode(\"edit\");\n };\n\n const handleBlur = () => {\n if (inputRef.current?.value && conversationId) {\n const trimmed = inputRef.current.value.trim();\n if (trimmed !== conversation?.title) {\n updateConversation(\n { conversationId, newTitle: trimmed },\n {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.CONVERSATION$TITLE_UPDATED));\n },\n },\n );\n }\n } else if (inputRef.current) {\n // reset the value if it's empty\n inputRef.current.value = conversation?.title ?? \"\";\n }\n\n setTitleMode(\"view\");\n };\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {\n // Ignore Enter key during IME composition (e.g., Chinese, Japanese, Korean input)\n if (event.nativeEvent.isComposing) {\n return;\n }\n if (event.key === \"Enter\") {\n event.currentTarget.blur();\n }\n };\n\n const handleInputClick = (event: React.MouseEvent<HTMLInputElement>) => {\n if (titleMode === \"edit\") {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n const handleEllipsisClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setContextMenuOpen(!contextMenuOpen);\n };\n\n const handleRename = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n setTitleMode(\"edit\");\n setContextMenuOpen(false);\n };\n\n React.useEffect(() => {\n if (titleMode === \"edit\") {\n inputRef.current?.focus();\n }\n }, [titleMode]);\n\n if (!conversation) {\n return null;\n }\n\n return (\n <>\n <div\n className=\"flex items-center gap-2 h-[22px] text-base font-normal text-left pl-0 lg:pl-1 min-w-0\"\n data-testid=\"conversation-name\"\n >\n {titleMode === \"edit\" ? (\n <input\n ref={inputRef}\n data-testid=\"conversation-name-input\"\n onClick={handleInputClick}\n onBlur={handleBlur}\n onKeyUp={handleKeyUp}\n type=\"text\"\n defaultValue={conversation.title || \"\"}\n className=\"text-white leading-5 bg-transparent border-none outline-none text-base font-normal w-fit max-w-fit field-sizing-content\"\n />\n ) : (\n <div\n className=\"text-white leading-5 truncate\"\n data-testid=\"conversation-name-title\"\n onDoubleClick={handleDoubleClick}\n title={conversation.title || \"\"}\n >\n {conversation.title}\n </div>\n )}\n\n {titleMode !== \"edit\" && (\n <div\n ref={ellipsisAnchorRef}\n className=\"relative flex items-center shrink-0\"\n >\n <EllipsisButton onClick={handleEllipsisClick} />\n {contextMenuOpen && (\n <ConversationNameContextMenu\n onClose={() => setContextMenuOpen(false)}\n onRename={handleRename}\n onDelete={handleDelete}\n onStop={shouldShowStop ? handleStop : undefined}\n onDisplayCost={\n shouldShowDisplayCost ? handleDisplayCost : undefined\n }\n onShowAgentTools={\n shouldShowAgentTools ? handleShowAgentTools : undefined\n }\n onShowSkills={shouldShowSkills ? handleShowSkills : undefined}\n onShowHooks={shouldShowHooks ? handleShowHooks : undefined}\n onTogglePublic={handleTogglePublic}\n onCopyShareLink={handleCopyShareLink}\n shareUrl={shareUrl}\n onDownloadConversation={\n shouldShowDownloadConversation\n ? handleDownloadConversation\n : undefined\n }\n position=\"bottom\"\n anchorRef={ellipsisAnchorRef}\n />\n )}\n </div>\n )}\n </div>\n\n {/* Metrics Modal */}\n <MetricsModal\n isOpen={metricsModalVisible}\n onOpenChange={setMetricsModalVisible}\n />\n\n {/* System Message Modal */}\n <SystemMessageModal\n isOpen={systemModalVisible}\n onClose={() => setSystemModalVisible(false)}\n systemMessage={systemMessage || null}\n />\n\n {/* Skills Modal */}\n {skillsModalVisible && (\n <SkillsModal onClose={() => setSkillsModalVisible(false)} />\n )}\n\n {/* Hooks Modal */}\n {hooksModalVisible && (\n <HooksModal onClose={() => setHooksModalVisible(false)} />\n )}\n\n {/* Confirm Delete Modal */}\n {confirmDeleteModalVisible && (\n <ConfirmDeleteModal\n onConfirm={handleConfirmDelete}\n onCancel={() => setConfirmDeleteModalVisible(false)}\n conversationTitle={conversation?.title || \"\"}\n />\n )}\n\n {confirmStopModalVisible && (\n <ConfirmStopModal\n onConfirm={handleConfirmStop}\n onCancel={() => setConfirmStopModalVisible(false)}\n />\n )}\n </>\n );\n}\n"],"mappings":"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"}
|
package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../../i18n/declaration.cjs`),r=require(`../../../../utils/utils.cjs`),i=require(`../../../../hooks/use-conversation-id.cjs`),a=require(`../../../../utils/conversation-local-storage.cjs`),o=require(`../../../../stores/conversation-store.cjs`),s=require(`../../../../contexts/active-backend-context.cjs`),c=require(`../../../../icons/lesson-plan.cjs`),l=require(`../../../../ui/context-menu.cjs`),u=require(`../../../../hooks/use-click-outside-element.cjs`),d=require(`../../../../icons/document.cjs`),f=require(`../../../../hooks/use-select-conversation-tab.cjs`),p=require(`../../../../icons/terminal.cjs`),m=require(`../../../../icons/globe.cjs`),h=require(`../../../../icons/vscode.cjs`),g=require(`../../../../icons/double-check.cjs`),_=require(`../../../../icons/pill.cjs`),v=require(`../../../../icons/pill-fill.cjs`),y=require(`../../../../hooks/use-task-list.cjs`);let b=require(`react`);b=e.__toESM(b,1);let x=require(`react/jsx-runtime`);function S({isOpen:e,onClose:b,ignoreOutsideClickRef:S}){let C=u.useClickOutsideElement(b,S),{t:w}=t.useTranslation(`openhands`),{conversationId:T}=i.useConversationId(),{state:E,setUnpinnedTabs:D,setSelectedTab:O}=a.useConversationLocalStorageState(T),{selectedTab:k,isRightPanelShown:A,setSelectedTab:j}=o.useConversationStore(),{navigateToTab:M}=f.useSelectConversationTab(),{hasTaskList:N}=y.useTaskList(),{backend:P}=s.useActiveBackend(),F=[{tab:`planner`,icon:c.default,i18nKey:n.I18nKey.COMMON$PLANNER},{tab:`files`,icon:d.default,i18nKey:n.I18nKey.COMMON$FILES},{tab:`vscode`,icon:h.default,i18nKey:n.I18nKey.COMMON$CODE},{tab:`terminal`,icon:p.default,i18nKey:n.I18nKey.COMMON$TERMINAL},{tab:`browser`,icon:m.default,i18nKey:n.I18nKey.COMMON$BROWSER}];N&&F.unshift({tab:`tasklist`,icon:g.default,i18nKey:n.I18nKey.COMMON$TASK_LIST});let I=F.filter(({tab:e})=>e!==`vscode`||P.kind===`cloud`);if(!e)return null;let L=e=>{M(e),b()},R=(e,t)=>{if(t.preventDefault(),t.stopPropagation(),E.unpinnedTabs.includes(e))D(E.unpinnedTabs.filter(t=>t!==e));else{let t=[...E.unpinnedTabs,e];if(D(t),k===e&&A){let n=I.find(({tab:n})=>n!==e&&!t.includes(n));n&&(j(n.tab),O(n.tab))}}};return(0,x.jsx)(l.ContextMenu,{ref:C,alignment:`right`,position:`bottom`,className:`z-[9999] mt-2 w-fit`,children:I.map(({tab:e,icon:t,i18nKey:n})=>{let i=!E.unpinnedTabs.includes(e);return(0,x.jsx)(`li`,{className:`list-none`,children:(0,x.jsxs)(`div`,{className:r.cn(`flex h-[30px] w-full min-w-0 items-stretch rounded`,`hover:bg-[var(--oh-interactive-hover)]`),children:[(0,x.jsxs)(`button`,{type:`button`,"data-testid":`conversation-tabs-menu-open-${e}`,className:r.cn(`flex min-w-0 flex-1 cursor-pointer items-center gap-2 rounded-l p-2 text-start`,`text-white transition-colors`),onClick:()=>L(e),children:[(0,x.jsx)(t,{className:`h-4 w-4 shrink-0`}),(0,x.jsx)(`span`,{className:`text-sm`,children:w(n)})]}),(0,x.jsx)(`button`,{type:`button`,"data-testid":`conversation-tabs-menu-pin-${e}`,className:r.cn(`flex shrink-0 cursor-pointer items-center justify-center rounded-r px-2`,`text-white transition-colors hover:bg-white/10`),"aria-pressed":i,"aria-label":i?`Unpin tab from bar`:`Pin tab to bar`,onClick:t=>R(e,t),children:i?(0,x.jsx)(v.default,{className:`-mr-[5px] ml-auto h-7 w-7`}):(0,x.jsx)(_.default,{className:`ml-auto h-4.5 w-4.5`})})]})},e)})})}exports.ConversationTabsContextMenu=S;
|
|
1
|
+
const e=require(`../../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../../i18n/declaration.cjs`),r=require(`../../../../utils/utils.cjs`),i=require(`../../../../hooks/use-conversation-id.cjs`),a=require(`../../../../utils/conversation-local-storage.cjs`),o=require(`../../../../stores/conversation-store.cjs`),s=require(`../../../../contexts/active-backend-context.cjs`),c=require(`../../../../icons/lesson-plan.cjs`),l=require(`../../../../ui/context-menu.cjs`),u=require(`../../../../hooks/use-click-outside-element.cjs`),d=require(`../../../../icons/document.cjs`),f=require(`../../../../hooks/use-select-conversation-tab.cjs`),p=require(`../../../../icons/terminal.cjs`),m=require(`../../../../icons/globe.cjs`),h=require(`../../../../icons/vscode.cjs`),g=require(`../../../../icons/double-check.cjs`),_=require(`../../../../icons/pill.cjs`),v=require(`../../../../icons/pill-fill.cjs`),y=require(`../../../../hooks/use-task-list.cjs`);let b=require(`react`);b=e.__toESM(b,1);let x=require(`react/jsx-runtime`);function S({isOpen:e,onClose:b,ignoreOutsideClickRef:S}){let C=u.useClickOutsideElement(b,S),{t:w}=t.useTranslation(`openhands`),{conversationId:T}=i.useConversationId(),{state:E,setUnpinnedTabs:D,setSelectedTab:O}=a.useConversationLocalStorageState(T),{selectedTab:k,isRightPanelShown:A,setSelectedTab:j}=o.useConversationStore(),{navigateToTab:M}=f.useSelectConversationTab(),{hasTaskList:N}=y.useTaskList(),{backend:P}=s.useActiveBackend(),F=[{tab:`planner`,icon:c.default,i18nKey:n.I18nKey.COMMON$PLANNER},{tab:`files`,icon:d.default,i18nKey:n.I18nKey.COMMON$FILES},{tab:`vscode`,icon:h.default,i18nKey:n.I18nKey.COMMON$CODE},{tab:`terminal`,icon:p.default,i18nKey:n.I18nKey.COMMON$TERMINAL},{tab:`browser`,icon:m.default,i18nKey:n.I18nKey.COMMON$BROWSER}];N&&F.unshift({tab:`tasklist`,icon:g.default,i18nKey:n.I18nKey.COMMON$TASK_LIST});let I=F.filter(({tab:e})=>e!==`vscode`&&e!==`planner`||P.kind===`cloud`);if(!e)return null;let L=e=>{M(e),b()},R=(e,t)=>{if(t.preventDefault(),t.stopPropagation(),E.unpinnedTabs.includes(e))D(E.unpinnedTabs.filter(t=>t!==e));else{let t=[...E.unpinnedTabs,e];if(D(t),k===e&&A){let n=I.find(({tab:n})=>n!==e&&!t.includes(n));n&&(j(n.tab),O(n.tab))}}};return(0,x.jsx)(l.ContextMenu,{ref:C,alignment:`right`,position:`bottom`,className:`z-[9999] mt-2 w-fit`,children:I.map(({tab:e,icon:t,i18nKey:n})=>{let i=!E.unpinnedTabs.includes(e);return(0,x.jsx)(`li`,{className:`list-none`,children:(0,x.jsxs)(`div`,{className:r.cn(`flex h-[30px] w-full min-w-0 items-stretch rounded`,`hover:bg-[var(--oh-interactive-hover)]`),children:[(0,x.jsxs)(`button`,{type:`button`,"data-testid":`conversation-tabs-menu-open-${e}`,className:r.cn(`flex min-w-0 flex-1 cursor-pointer items-center gap-2 rounded-l p-2 text-start`,`text-white transition-colors`),onClick:()=>L(e),children:[(0,x.jsx)(t,{className:`h-4 w-4 shrink-0`}),(0,x.jsx)(`span`,{className:`text-sm`,children:w(n)})]}),(0,x.jsx)(`button`,{type:`button`,"data-testid":`conversation-tabs-menu-pin-${e}`,className:r.cn(`flex shrink-0 cursor-pointer items-center justify-center rounded-r px-2`,`text-white transition-colors hover:bg-white/10`),"aria-pressed":i,"aria-label":i?`Unpin tab from bar`:`Pin tab to bar`,onClick:t=>R(e,t),children:i?(0,x.jsx)(v.default,{className:`-mr-[5px] ml-auto h-7 w-7`}):(0,x.jsx)(_.default,{className:`ml-auto h-4.5 w-4.5`})})]})},e)})})}exports.ConversationTabsContextMenu=S;
|
|
2
2
|
//# sourceMappingURL=conversation-tabs-context-menu.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-tabs-context-menu.cjs","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useConversationStore,\n type ConversationTab,\n} from \"#/stores/conversation-store\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport TerminalIcon from \"#/icons/terminal.svg?react\";\nimport GlobeIcon from \"#/icons/globe.svg?react\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport PillIcon from \"#/icons/pill.svg?react\";\nimport PillFillIcon from \"#/icons/pill-fill.svg?react\";\nimport LessonPlanIcon from \"#/icons/lesson-plan.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { cn } from \"#/utils/utils\";\n\ninterface ConversationTabsContextMenuProps {\n isOpen: boolean;\n onClose: () => void;\n ignoreOutsideClickRef?: React.RefObject<HTMLElement | null>;\n}\n\nexport function ConversationTabsContextMenu({\n isOpen,\n onClose,\n ignoreOutsideClickRef,\n}: ConversationTabsContextMenuProps) {\n const ref = useClickOutsideElement<HTMLUListElement>(\n onClose,\n ignoreOutsideClickRef,\n );\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const {\n state,\n setUnpinnedTabs,\n setSelectedTab: setPersistedSelectedTab,\n } = useConversationLocalStorageState(conversationId);\n const { selectedTab, isRightPanelShown, setSelectedTab } =\n useConversationStore();\n\n const { navigateToTab } = useSelectConversationTab();\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const tabConfig = [\n {\n tab: \"planner\",\n icon: LessonPlanIcon,\n i18nKey: I18nKey.COMMON$PLANNER,\n },\n { tab: \"files\", icon: DocumentIcon, i18nKey: I18nKey.COMMON$FILES },\n { tab: \"vscode\", icon: VSCodeIcon, i18nKey: I18nKey.COMMON$CODE },\n { tab: \"terminal\", icon: TerminalIcon, i18nKey: I18nKey.COMMON$TERMINAL },\n { tab: \"browser\", icon: GlobeIcon, i18nKey: I18nKey.COMMON$BROWSER },\n ];\n\n if (hasTaskList) {\n tabConfig.unshift({\n tab: \"tasklist\",\n icon: DoubleCheckIcon,\n i18nKey: I18nKey.COMMON$TASK_LIST,\n });\n }\n\n const visibleTabConfig = tabConfig.filter(\n ({ tab })
|
|
1
|
+
{"version":3,"file":"conversation-tabs-context-menu.cjs","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useConversationStore,\n type ConversationTab,\n} from \"#/stores/conversation-store\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport TerminalIcon from \"#/icons/terminal.svg?react\";\nimport GlobeIcon from \"#/icons/globe.svg?react\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport PillIcon from \"#/icons/pill.svg?react\";\nimport PillFillIcon from \"#/icons/pill-fill.svg?react\";\nimport LessonPlanIcon from \"#/icons/lesson-plan.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { cn } from \"#/utils/utils\";\n\ninterface ConversationTabsContextMenuProps {\n isOpen: boolean;\n onClose: () => void;\n ignoreOutsideClickRef?: React.RefObject<HTMLElement | null>;\n}\n\nexport function ConversationTabsContextMenu({\n isOpen,\n onClose,\n ignoreOutsideClickRef,\n}: ConversationTabsContextMenuProps) {\n const ref = useClickOutsideElement<HTMLUListElement>(\n onClose,\n ignoreOutsideClickRef,\n );\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const {\n state,\n setUnpinnedTabs,\n setSelectedTab: setPersistedSelectedTab,\n } = useConversationLocalStorageState(conversationId);\n const { selectedTab, isRightPanelShown, setSelectedTab } =\n useConversationStore();\n\n const { navigateToTab } = useSelectConversationTab();\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const tabConfig = [\n {\n tab: \"planner\",\n icon: LessonPlanIcon,\n i18nKey: I18nKey.COMMON$PLANNER,\n },\n { tab: \"files\", icon: DocumentIcon, i18nKey: I18nKey.COMMON$FILES },\n { tab: \"vscode\", icon: VSCodeIcon, i18nKey: I18nKey.COMMON$CODE },\n { tab: \"terminal\", icon: TerminalIcon, i18nKey: I18nKey.COMMON$TERMINAL },\n { tab: \"browser\", icon: GlobeIcon, i18nKey: I18nKey.COMMON$BROWSER },\n ];\n\n if (hasTaskList) {\n tabConfig.unshift({\n tab: \"tasklist\",\n icon: DoubleCheckIcon,\n i18nKey: I18nKey.COMMON$TASK_LIST,\n });\n }\n\n const visibleTabConfig = tabConfig.filter(\n ({ tab }) =>\n (tab !== \"vscode\" && tab !== \"planner\") || backend.kind === \"cloud\",\n );\n\n if (!isOpen) return null;\n\n const handleOpenTab = (tab: string) => {\n navigateToTab(tab as ConversationTab);\n onClose();\n };\n\n const handlePinToggle = (tab: string, e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (state.unpinnedTabs.includes(tab)) {\n setUnpinnedTabs(state.unpinnedTabs.filter((item) => item !== tab));\n } else {\n const newUnpinnedTabs = [...state.unpinnedTabs, tab];\n setUnpinnedTabs(newUnpinnedTabs);\n\n if (selectedTab === tab && isRightPanelShown) {\n const nextPinnedTab = visibleTabConfig.find(\n ({ tab: tabKey }) =>\n tabKey !== tab && !newUnpinnedTabs.includes(tabKey),\n );\n\n if (nextPinnedTab) {\n setSelectedTab(nextPinnedTab.tab as ConversationTab);\n setPersistedSelectedTab(nextPinnedTab.tab as ConversationTab);\n }\n }\n }\n };\n\n return (\n <ContextMenu\n ref={ref}\n alignment=\"right\"\n position=\"bottom\"\n className=\"z-[9999] mt-2 w-fit\"\n >\n {visibleTabConfig.map(({ tab, icon: Icon, i18nKey }) => {\n const pinned = !state.unpinnedTabs.includes(tab);\n return (\n <li key={tab} className=\"list-none\">\n <div\n className={cn(\n \"flex h-[30px] w-full min-w-0 items-stretch rounded\",\n \"hover:bg-[var(--oh-interactive-hover)]\",\n )}\n >\n <button\n type=\"button\"\n data-testid={`conversation-tabs-menu-open-${tab}`}\n className={cn(\n \"flex min-w-0 flex-1 cursor-pointer items-center gap-2 rounded-l p-2 text-start\",\n \"text-white transition-colors\",\n )}\n onClick={() => handleOpenTab(tab)}\n >\n <Icon className=\"h-4 w-4 shrink-0\" />\n <span className=\"text-sm\">{t(i18nKey)}</span>\n </button>\n <button\n type=\"button\"\n data-testid={`conversation-tabs-menu-pin-${tab}`}\n className={cn(\n \"flex shrink-0 cursor-pointer items-center justify-center rounded-r px-2\",\n \"text-white transition-colors hover:bg-white/10\",\n )}\n aria-pressed={pinned}\n aria-label={pinned ? \"Unpin tab from bar\" : \"Pin tab to bar\"}\n onClick={(e) => handlePinToggle(tab, e)}\n >\n {pinned ? (\n <PillFillIcon className=\"-mr-[5px] ml-auto h-7 w-7\" />\n ) : (\n <PillIcon className=\"ml-auto h-4.5 w-4.5\" />\n )}\n </button>\n </div>\n </li>\n );\n })}\n </ContextMenu>\n );\n}\n"],"mappings":"ilCA8BA,SAAgB,EAA4B,CAC1C,SACA,UACA,yBACmC,CACnC,IAAM,EAAM,EAAA,uBACV,EACA,EACD,CACK,CAAE,KAAM,EAAA,eAAe,YAAY,CACnC,CAAE,kBAAmB,EAAA,mBAAmB,CACxC,CACJ,QACA,kBACA,eAAgB,GACd,EAAA,iCAAiC,EAAe,CAC9C,CAAE,cAAa,oBAAmB,kBACtC,EAAA,sBAAsB,CAElB,CAAE,iBAAkB,EAAA,0BAA0B,CAE9C,CAAE,eAAgB,EAAA,aAAa,CAC/B,CAAE,WAAY,EAAA,kBAAkB,CAEhC,EAAY,CAChB,CACE,IAAK,UACL,KAAM,EAAA,QACN,QAAS,EAAA,QAAQ,eAClB,CACD,CAAE,IAAK,QAAS,KAAM,EAAA,QAAc,QAAS,EAAA,QAAQ,aAAc,CACnE,CAAE,IAAK,SAAU,KAAM,EAAA,QAAY,QAAS,EAAA,QAAQ,YAAa,CACjE,CAAE,IAAK,WAAY,KAAM,EAAA,QAAc,QAAS,EAAA,QAAQ,gBAAiB,CACzE,CAAE,IAAK,UAAW,KAAM,EAAA,QAAW,QAAS,EAAA,QAAQ,eAAgB,CACrE,CAEG,GACF,EAAU,QAAQ,CAChB,IAAK,WACL,KAAM,EAAA,QACN,QAAS,EAAA,QAAQ,iBAClB,CAAC,CAGJ,IAAM,EAAmB,EAAU,QAChC,CAAE,SACA,IAAQ,UAAY,IAAQ,WAAc,EAAQ,OAAS,QAC/D,CAED,GAAI,CAAC,EAAQ,OAAO,KAEpB,IAAM,EAAiB,GAAgB,CACrC,EAAc,EAAuB,CACrC,GAAS,EAGL,GAAmB,EAAa,IAAwB,CAG5D,GAFA,EAAE,gBAAgB,CAClB,EAAE,iBAAiB,CACf,EAAM,aAAa,SAAS,EAAI,CAClC,EAAgB,EAAM,aAAa,OAAQ,GAAS,IAAS,EAAI,CAAC,KAC7D,CACL,IAAM,EAAkB,CAAC,GAAG,EAAM,aAAc,EAAI,CAGpD,GAFA,EAAgB,EAAgB,CAE5B,IAAgB,GAAO,EAAmB,CAC5C,IAAM,EAAgB,EAAiB,MACpC,CAAE,IAAK,KACN,IAAW,GAAO,CAAC,EAAgB,SAAS,EAAO,CACtD,CAEG,IACF,EAAe,EAAc,IAAuB,CACpD,EAAwB,EAAc,IAAuB,KAMrE,OACE,EAAA,EAAA,KAAC,EAAA,YAAD,CACO,MACL,UAAU,QACV,SAAS,SACT,UAAU,+BAET,EAAiB,KAAK,CAAE,MAAK,KAAM,EAAM,aAAc,CACtD,IAAM,EAAS,CAAC,EAAM,aAAa,SAAS,EAAI,CAChD,OACE,EAAA,EAAA,KAAC,KAAD,CAAc,UAAU,sBACtB,EAAA,EAAA,MAAC,MAAD,CACE,UAAW,EAAA,GACT,qDACA,yCACD,UAJH,EAME,EAAA,EAAA,MAAC,SAAD,CACE,KAAK,SACL,cAAa,+BAA+B,IAC5C,UAAW,EAAA,GACT,iFACA,+BACD,CACD,YAAe,EAAc,EAAI,UAPnC,EASE,EAAA,EAAA,KAAC,EAAD,CAAM,UAAU,mBAAqB,CAAA,EACrC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,mBAAW,EAAE,EAAQ,CAAQ,CAAA,CACtC,IACT,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,cAAa,8BAA8B,IAC3C,UAAW,EAAA,GACT,0EACA,iDACD,CACD,eAAc,EACd,aAAY,EAAS,qBAAuB,iBAC5C,QAAU,GAAM,EAAgB,EAAK,EAAE,UAEtC,GACC,EAAA,EAAA,KAAC,EAAA,QAAD,CAAc,UAAU,4BAA8B,CAAA,EAEtD,EAAA,EAAA,KAAC,EAAA,QAAD,CAAU,UAAU,sBAAwB,CAAA,CAEvC,CAAA,CACL,GACH,CArCI,EAqCJ,EAEP,CACU,CAAA"}
|
package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js
CHANGED
|
@@ -53,7 +53,7 @@ function x({ isOpen: x, onClose: S, ignoreOutsideClickRef: C }) {
|
|
|
53
53
|
icon: h,
|
|
54
54
|
i18nKey: t.COMMON$TASK_LIST
|
|
55
55
|
});
|
|
56
|
-
let L = I.filter(({ tab: e }) => e !== "vscode" || F.kind === "cloud");
|
|
56
|
+
let L = I.filter(({ tab: e }) => e !== "vscode" && e !== "planner" || F.kind === "cloud");
|
|
57
57
|
if (!x) return null;
|
|
58
58
|
let R = (e) => {
|
|
59
59
|
N(e), S();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-tabs-context-menu.js","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useConversationStore,\n type ConversationTab,\n} from \"#/stores/conversation-store\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport TerminalIcon from \"#/icons/terminal.svg?react\";\nimport GlobeIcon from \"#/icons/globe.svg?react\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport PillIcon from \"#/icons/pill.svg?react\";\nimport PillFillIcon from \"#/icons/pill-fill.svg?react\";\nimport LessonPlanIcon from \"#/icons/lesson-plan.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { cn } from \"#/utils/utils\";\n\ninterface ConversationTabsContextMenuProps {\n isOpen: boolean;\n onClose: () => void;\n ignoreOutsideClickRef?: React.RefObject<HTMLElement | null>;\n}\n\nexport function ConversationTabsContextMenu({\n isOpen,\n onClose,\n ignoreOutsideClickRef,\n}: ConversationTabsContextMenuProps) {\n const ref = useClickOutsideElement<HTMLUListElement>(\n onClose,\n ignoreOutsideClickRef,\n );\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const {\n state,\n setUnpinnedTabs,\n setSelectedTab: setPersistedSelectedTab,\n } = useConversationLocalStorageState(conversationId);\n const { selectedTab, isRightPanelShown, setSelectedTab } =\n useConversationStore();\n\n const { navigateToTab } = useSelectConversationTab();\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const tabConfig = [\n {\n tab: \"planner\",\n icon: LessonPlanIcon,\n i18nKey: I18nKey.COMMON$PLANNER,\n },\n { tab: \"files\", icon: DocumentIcon, i18nKey: I18nKey.COMMON$FILES },\n { tab: \"vscode\", icon: VSCodeIcon, i18nKey: I18nKey.COMMON$CODE },\n { tab: \"terminal\", icon: TerminalIcon, i18nKey: I18nKey.COMMON$TERMINAL },\n { tab: \"browser\", icon: GlobeIcon, i18nKey: I18nKey.COMMON$BROWSER },\n ];\n\n if (hasTaskList) {\n tabConfig.unshift({\n tab: \"tasklist\",\n icon: DoubleCheckIcon,\n i18nKey: I18nKey.COMMON$TASK_LIST,\n });\n }\n\n const visibleTabConfig = tabConfig.filter(\n ({ tab })
|
|
1
|
+
{"version":3,"file":"conversation-tabs-context-menu.js","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useConversationStore,\n type ConversationTab,\n} from \"#/stores/conversation-store\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport TerminalIcon from \"#/icons/terminal.svg?react\";\nimport GlobeIcon from \"#/icons/globe.svg?react\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport PillIcon from \"#/icons/pill.svg?react\";\nimport PillFillIcon from \"#/icons/pill-fill.svg?react\";\nimport LessonPlanIcon from \"#/icons/lesson-plan.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { cn } from \"#/utils/utils\";\n\ninterface ConversationTabsContextMenuProps {\n isOpen: boolean;\n onClose: () => void;\n ignoreOutsideClickRef?: React.RefObject<HTMLElement | null>;\n}\n\nexport function ConversationTabsContextMenu({\n isOpen,\n onClose,\n ignoreOutsideClickRef,\n}: ConversationTabsContextMenuProps) {\n const ref = useClickOutsideElement<HTMLUListElement>(\n onClose,\n ignoreOutsideClickRef,\n );\n const { t } = useTranslation(\"openhands\");\n const { conversationId } = useConversationId();\n const {\n state,\n setUnpinnedTabs,\n setSelectedTab: setPersistedSelectedTab,\n } = useConversationLocalStorageState(conversationId);\n const { selectedTab, isRightPanelShown, setSelectedTab } =\n useConversationStore();\n\n const { navigateToTab } = useSelectConversationTab();\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const tabConfig = [\n {\n tab: \"planner\",\n icon: LessonPlanIcon,\n i18nKey: I18nKey.COMMON$PLANNER,\n },\n { tab: \"files\", icon: DocumentIcon, i18nKey: I18nKey.COMMON$FILES },\n { tab: \"vscode\", icon: VSCodeIcon, i18nKey: I18nKey.COMMON$CODE },\n { tab: \"terminal\", icon: TerminalIcon, i18nKey: I18nKey.COMMON$TERMINAL },\n { tab: \"browser\", icon: GlobeIcon, i18nKey: I18nKey.COMMON$BROWSER },\n ];\n\n if (hasTaskList) {\n tabConfig.unshift({\n tab: \"tasklist\",\n icon: DoubleCheckIcon,\n i18nKey: I18nKey.COMMON$TASK_LIST,\n });\n }\n\n const visibleTabConfig = tabConfig.filter(\n ({ tab }) =>\n (tab !== \"vscode\" && tab !== \"planner\") || backend.kind === \"cloud\",\n );\n\n if (!isOpen) return null;\n\n const handleOpenTab = (tab: string) => {\n navigateToTab(tab as ConversationTab);\n onClose();\n };\n\n const handlePinToggle = (tab: string, e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (state.unpinnedTabs.includes(tab)) {\n setUnpinnedTabs(state.unpinnedTabs.filter((item) => item !== tab));\n } else {\n const newUnpinnedTabs = [...state.unpinnedTabs, tab];\n setUnpinnedTabs(newUnpinnedTabs);\n\n if (selectedTab === tab && isRightPanelShown) {\n const nextPinnedTab = visibleTabConfig.find(\n ({ tab: tabKey }) =>\n tabKey !== tab && !newUnpinnedTabs.includes(tabKey),\n );\n\n if (nextPinnedTab) {\n setSelectedTab(nextPinnedTab.tab as ConversationTab);\n setPersistedSelectedTab(nextPinnedTab.tab as ConversationTab);\n }\n }\n }\n };\n\n return (\n <ContextMenu\n ref={ref}\n alignment=\"right\"\n position=\"bottom\"\n className=\"z-[9999] mt-2 w-fit\"\n >\n {visibleTabConfig.map(({ tab, icon: Icon, i18nKey }) => {\n const pinned = !state.unpinnedTabs.includes(tab);\n return (\n <li key={tab} className=\"list-none\">\n <div\n className={cn(\n \"flex h-[30px] w-full min-w-0 items-stretch rounded\",\n \"hover:bg-[var(--oh-interactive-hover)]\",\n )}\n >\n <button\n type=\"button\"\n data-testid={`conversation-tabs-menu-open-${tab}`}\n className={cn(\n \"flex min-w-0 flex-1 cursor-pointer items-center gap-2 rounded-l p-2 text-start\",\n \"text-white transition-colors\",\n )}\n onClick={() => handleOpenTab(tab)}\n >\n <Icon className=\"h-4 w-4 shrink-0\" />\n <span className=\"text-sm\">{t(i18nKey)}</span>\n </button>\n <button\n type=\"button\"\n data-testid={`conversation-tabs-menu-pin-${tab}`}\n className={cn(\n \"flex shrink-0 cursor-pointer items-center justify-center rounded-r px-2\",\n \"text-white transition-colors hover:bg-white/10\",\n )}\n aria-pressed={pinned}\n aria-label={pinned ? \"Unpin tab from bar\" : \"Pin tab to bar\"}\n onClick={(e) => handlePinToggle(tab, e)}\n >\n {pinned ? (\n <PillFillIcon className=\"-mr-[5px] ml-auto h-7 w-7\" />\n ) : (\n <PillIcon className=\"ml-auto h-4.5 w-4.5\" />\n )}\n </button>\n </div>\n </li>\n );\n })}\n </ContextMenu>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,EAA4B,EAC1C,WACA,YACA,4BACmC;CACnC,IAAM,IAAM,EACV,GACA,EACD,EACK,EAAE,SAAM,EAAe,YAAY,EACnC,EAAE,sBAAmB,GAAmB,EACxC,EACJ,UACA,oBACA,gBAAgB,MACd,EAAiC,EAAe,EAC9C,EAAE,gBAAa,sBAAmB,sBACtC,GAAsB,EAElB,EAAE,qBAAkB,GAA0B,EAE9C,EAAE,mBAAgB,GAAa,EAC/B,EAAE,eAAY,GAAkB,EAEhC,IAAY;EAChB;GACE,KAAK;GACL,MAAM;GACN,SAAS,EAAQ;GAClB;EACD;GAAE,KAAK;GAAS,MAAM;GAAc,SAAS,EAAQ;GAAc;EACnE;GAAE,KAAK;GAAU,MAAM;GAAY,SAAS,EAAQ;GAAa;EACjE;GAAE,KAAK;GAAY,MAAM;GAAc,SAAS,EAAQ;GAAiB;EACzE;GAAE,KAAK;GAAW,MAAM;GAAW,SAAS,EAAQ;GAAgB;EACrE;AAED,CAAI,KACF,EAAU,QAAQ;EAChB,KAAK;EACL,MAAM;EACN,SAAS,EAAQ;EAClB,CAAC;CAGJ,IAAM,IAAmB,EAAU,QAChC,EAAE,aACA,MAAQ,YAAY,MAAQ,aAAc,EAAQ,SAAS,QAC/D;AAED,KAAI,CAAC,EAAQ,QAAO;CAEpB,IAAM,KAAiB,MAAgB;AAErC,EADA,EAAc,EAAuB,EACrC,GAAS;IAGL,KAAmB,GAAa,MAAwB;AAG5D,MAFA,EAAE,gBAAgB,EAClB,EAAE,iBAAiB,EACf,EAAM,aAAa,SAAS,EAAI,CAClC,GAAgB,EAAM,aAAa,QAAQ,MAAS,MAAS,EAAI,CAAC;OAC7D;GACL,IAAM,IAAkB,CAAC,GAAG,EAAM,cAAc,EAAI;AAGpD,OAFA,EAAgB,EAAgB,EAE5B,MAAgB,KAAO,GAAmB;IAC5C,IAAM,IAAgB,EAAiB,MACpC,EAAE,KAAK,QACN,MAAW,KAAO,CAAC,EAAgB,SAAS,EAAO,CACtD;AAED,IAAI,MACF,EAAe,EAAc,IAAuB,EACpD,EAAwB,EAAc,IAAuB;;;;AAMrE,QACE,kBAAC,GAAD;EACO;EACL,WAAU;EACV,UAAS;EACT,WAAU;YAET,EAAiB,KAAK,EAAE,QAAK,MAAM,GAAM,iBAAc;GACtD,IAAM,IAAS,CAAC,EAAM,aAAa,SAAS,EAAI;AAChD,UACE,kBAAC,MAAD;IAAc,WAAU;cACtB,kBAAC,OAAD;KACE,WAAW,EACT,sDACA,yCACD;eAJH,CAME,kBAAC,UAAD;MACE,MAAK;MACL,eAAa,+BAA+B;MAC5C,WAAW,EACT,kFACA,+BACD;MACD,eAAe,EAAc,EAAI;gBAPnC,CASE,kBAAC,GAAD,EAAM,WAAU,oBAAqB,CAAA,EACrC,kBAAC,QAAD;OAAM,WAAU;iBAAW,EAAE,EAAQ;OAAQ,CAAA,CACtC;SACT,kBAAC,UAAD;MACE,MAAK;MACL,eAAa,8BAA8B;MAC3C,WAAW,EACT,2EACA,iDACD;MACD,gBAAc;MACd,cAAY,IAAS,uBAAuB;MAC5C,UAAU,MAAM,EAAgB,GAAK,EAAE;gBAEtC,IACC,kBAAC,GAAD,EAAc,WAAU,6BAA8B,CAAA,GAEtD,kBAAC,GAAD,EAAU,WAAU,uBAAwB,CAAA;MAEvC,CAAA,CACL;;IACH,EArCI,EAqCJ;IAEP;EACU,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),t=require(`../../../../i18n/declaration.cjs`),n=require(`../../../../types/agent-state.cjs`),r=require(`../../../../utils/utils.cjs`),i=require(`../../../../hooks/use-conversation-id.cjs`),a=require(`../../../../utils/conversation-local-storage.cjs`),o=require(`../../../../stores/conversation-store.cjs`),s=require(`../../../../contexts/active-backend-context.cjs`),c=require(`../../../../hooks/use-agent-state.cjs`),l=require(`../../../../utils/mobile-top-bar-icon-button-classes.cjs`),u=require(`../../../../ui/typography.cjs`),d=require(`../../../../icons/lesson-plan.cjs`),f=require(`../../../../icons/document.cjs`),p=require(`../../../../hooks/use-handle-build-plan-click.cjs`),m=require(`../../../../hooks/use-select-conversation-tab.cjs`),h=require(`../../conversation-panel/ellipsis-button.cjs`),g=require(`../../chat/chat-action-tooltip.cjs`),_=require(`../../../../icons/terminal.cjs`),v=require(`../../../../icons/globe.cjs`),y=require(`../../../../icons/vscode.cjs`),b=require(`../../../../icons/double-check.cjs`),x=require(`./conversation-tab-nav.cjs`),
|
|
1
|
+
require(`../../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),t=require(`../../../../i18n/declaration.cjs`),n=require(`../../../../types/agent-state.cjs`),r=require(`../../../../utils/utils.cjs`),i=require(`../../../../hooks/use-conversation-id.cjs`),a=require(`../../../../utils/conversation-local-storage.cjs`),o=require(`../../../../stores/conversation-store.cjs`),s=require(`../../../../contexts/active-backend-context.cjs`),c=require(`../../../../hooks/use-agent-state.cjs`),l=require(`../../../../utils/mobile-top-bar-icon-button-classes.cjs`),u=require(`../../../../ui/typography.cjs`),d=require(`../../../../icons/lesson-plan.cjs`),f=require(`../../../../icons/document.cjs`),p=require(`../../../../hooks/use-handle-build-plan-click.cjs`),m=require(`../../../../hooks/use-select-conversation-tab.cjs`),h=require(`../../conversation-panel/ellipsis-button.cjs`),g=require(`../../chat/chat-action-tooltip.cjs`),_=require(`../../../../icons/terminal.cjs`),v=require(`../../../../icons/globe.cjs`),y=require(`../../../../icons/vscode.cjs`),b=require(`../../../../icons/double-check.cjs`),x=require(`./conversation-tab-nav.cjs`),S=require(`./vscode-tooltip-content.cjs`),ee=require(`../../../../hooks/use-task-list.cjs`),C=require(`./conversation-tabs-context-menu.cjs`);let w=require(`react`),T=require(`react/jsx-runtime`);function E({variant:E=`default`}){let{conversationId:D}=i.useConversationId(),{setSelectedTab:O,planContent:k}=o.useConversationStore(),[A,j]=(0,w.useState)(!1),{state:M}=a.useConversationLocalStorageState(D),{hasTaskList:N}=ee.useTaskList(),{backend:P}=s.useActiveBackend(),{handleBuildPlanClick:F}=p.useHandleBuildPlanClick(),{curAgentState:I}=c.useAgentState(),{selectTab:L,isTabActive:R,onTabChange:z,selectedTab:B,isRightPanelShown:V}=m.useSelectConversationTab();(0,w.useEffect)(()=>{O(M.selectedTab)},[O,M.selectedTab]),(0,w.useEffect)(()=>{V&&(B||z(`files`))},[V,B,z]);let{t:H,i18n:U}=e.useTranslation(`openhands`),W=[{tabValue:`files`,isActive:R(`files`),icon:f.default,onClick:()=>L(`files`),tooltipContent:H(t.I18nKey.COMMON$FILES),tooltipAriaLabel:H(t.I18nKey.COMMON$FILES),label:H(t.I18nKey.COMMON$FILES)},{tabValue:`planner`,isActive:R(`planner`),icon:d.default,onClick:()=>L(`planner`),tooltipContent:H(t.I18nKey.COMMON$PLANNER),tooltipAriaLabel:H(t.I18nKey.COMMON$PLANNER),label:H(t.I18nKey.COMMON$PLANNER)},{tabValue:`vscode`,isActive:R(`vscode`),icon:y.default,onClick:()=>L(`vscode`),tooltipContent:(0,T.jsx)(S.VSCodeTooltipContent,{}),tooltipAriaLabel:H(t.I18nKey.COMMON$CODE),label:H(t.I18nKey.COMMON$CODE)},{tabValue:`terminal`,isActive:R(`terminal`),icon:_.default,onClick:()=>L(`terminal`),tooltipContent:H(t.I18nKey.COMMON$TERMINAL),tooltipAriaLabel:H(t.I18nKey.COMMON$TERMINAL),label:H(t.I18nKey.COMMON$TERMINAL),className:`pl-2`},{tabValue:`browser`,isActive:R(`browser`),icon:v.default,onClick:()=>L(`browser`),tooltipContent:H(t.I18nKey.COMMON$BROWSER),tooltipAriaLabel:H(t.I18nKey.COMMON$BROWSER),label:H(t.I18nKey.COMMON$BROWSER)}];N&&W.splice(1,0,{tabValue:`tasklist`,isActive:R(`tasklist`),icon:b.default,onClick:()=>L(`tasklist`),tooltipContent:H(t.I18nKey.COMMON$TASK_LIST),tooltipAriaLabel:H(t.I18nKey.COMMON$TASK_LIST),label:H(t.I18nKey.COMMON$TASK_LIST)});let G=W.filter(e=>e.tabValue===`vscode`&&P.kind!==`cloud`||e.tabValue===`planner`&&P.kind!==`cloud`?!1:M.unpinnedTabs.includes(e.tabValue)?B===e.tabValue:!0),K=M.unpinnedTabs.join(`,`),q=I===n.AgentState.RUNNING||I===n.AgentState.LOADING||!k,J=(0,w.useRef)(null),Y=(0,w.useRef)(null),X=(0,w.useRef)(null),Z=(0,w.useRef)(null),[Q,$]=(0,w.useState)(G.length);(0,w.useLayoutEffect)(()=>{let e=J.current,t=Y.current,n=X.current;if(!e||!t||!n)return;let r=()=>{let r=t.querySelectorAll(`[data-tab-measure="true"]`),i=r.length,a=e.getBoundingClientRect().width;if(a===0){$(i);return}let o=Array.from(r).map(e=>e.getBoundingClientRect().width);if(o.length!==i||i===0){$(Math.max(0,i));return}let s=n.getBoundingClientRect().width,c=getComputedStyle(e).columnGap||getComputedStyle(e).gap,l=parseFloat(c)||6,u=0;for(let e=i;e>=0;--e){let t=s;for(let n=0;n<e;n+=1)t+=o[n]??0;if(e>0&&(t+=e*l),t<=a+.5){u=e;break}}$(e=>e===u?e:u)};if(r(),typeof ResizeObserver>`u`)return;let i=new ResizeObserver(r);return i.observe(e),()=>i.disconnect()},[K,G.length,N,P.kind,B,V,U.language]);let te=Math.min(Q,G.length);return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsxs)(`div`,{className:r.cn(`relative w-full min-w-0`,E===`compact`?`flex h-full min-h-0 items-center py-0 pl-0 pr-1`:`min-h-10 p-1`),children:[(0,T.jsx)(`div`,{ref:Y,"aria-hidden":!0,className:`pointer-events-none absolute top-0 left-[-10000px] flex flex-nowrap items-center gap-1.5`,children:G.map(({tabValue:e,icon:t,isActive:n,tooltipContent:i,tooltipAriaLabel:a,label:o,className:s},c)=>(0,T.jsx)(g.ChatActionTooltip,{tooltip:i,ariaLabel:a,children:(0,T.jsx)(x.ConversationTabNav,{tabValue:e,icon:t,onClick:()=>{},isActive:n,label:o,className:r.cn(s,`shrink-0`),measureOnly:!0})},`measure-${e}-${c}`))}),(0,T.jsx)(`div`,{ref:J,className:`flex w-full min-w-0 flex-nowrap items-center justify-start`,children:(0,T.jsxs)(`div`,{className:`flex w-fit max-w-full min-w-0 flex-nowrap items-center gap-1.5`,children:[(0,T.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-nowrap items-center gap-1.5 overflow-x-hidden`,children:G.slice(0,te).map(({tabValue:e,icon:t,onClick:n,isActive:i,tooltipContent:a,tooltipAriaLabel:o,label:s,className:c},l)=>(0,T.jsx)(g.ChatActionTooltip,{tooltip:a,ariaLabel:o,children:(0,T.jsx)(x.ConversationTabNav,{tabValue:e,icon:t,onClick:n,isActive:i,label:s,className:r.cn(c,`shrink-0`)})},`${e}-${l}`))}),(0,T.jsxs)(`div`,{ref:X,className:`relative shrink-0`,children:[(0,T.jsx)(h.EllipsisButton,{ref:Z,onClick:()=>j(!A),ariaLabel:H(t.I18nKey.COMMON$MORE_OPTIONS),iconClassName:E===`compact`?l.mobileTopBarIconClassName:void 0}),(0,T.jsx)(C.ConversationTabsContextMenu,{isOpen:A,onClose:()=>j(!1),ignoreOutsideClickRef:Z})]})]})})]}),R(`planner`)&&(0,T.jsx)(`div`,{className:r.cn(`flex h-10 min-h-10 shrink-0 items-center border-t border-[var(--oh-border)] pl-[10px] pr-1`),children:(0,T.jsx)(`button`,{type:`button`,onClick:F,disabled:q,className:r.cn(`flex h-5 min-w-17 items-center justify-center rounded bg-white px-2 transition-opacity`,q?`cursor-not-allowed opacity-50`:`cursor-pointer hover:opacity-90`),"data-testid":`planner-tab-build-button`,children:(0,T.jsxs)(u.Typography.Text,{className:`text-[11px] font-normal leading-5 text-black`,children:[H(t.I18nKey.COMMON$BUILD),` ⌘↩`]})})})]})}exports.ConversationTabs=E;
|
|
2
2
|
//# sourceMappingURL=conversation-tabs.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-tabs.cjs","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport TerminalIcon from \"#/icons/terminal.svg?react\";\nimport GlobeIcon from \"#/icons/globe.svg?react\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport LessonPlanIcon from \"#/icons/lesson-plan.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { EllipsisButton } from \"#/components/features/conversation-panel/ellipsis-button\";\nimport { cn } from \"#/utils/utils\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport { ConversationTabNav } from \"./conversation-tab-nav\";\nimport { ChatActionTooltip } from \"../../chat/chat-action-tooltip\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { VSCodeTooltipContent } from \"./vscode-tooltip-content\";\nimport { useConversationStore } from \"#/stores/conversation-store\";\nimport { ConversationTabsContextMenu } from \"./conversation-tabs-context-menu\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useHandleBuildPlanClick } from \"#/hooks/use-handle-build-plan-click\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { Typography } from \"#/ui/typography\";\nimport { mobileTopBarIconClassName } from \"#/utils/mobile-top-bar-icon-button-classes\";\n\nexport function ConversationTabs({\n variant = \"default\",\n}: {\n variant?: \"default\" | \"compact\";\n}) {\n const { conversationId } = useConversationId();\n const { setSelectedTab, planContent } = useConversationStore();\n\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const { state: persistedState } =\n useConversationLocalStorageState(conversationId);\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const { handleBuildPlanClick } = useHandleBuildPlanClick();\n const { curAgentState } = useAgentState();\n\n const {\n selectTab,\n isTabActive,\n onTabChange,\n selectedTab,\n isRightPanelShown,\n } = useSelectConversationTab();\n\n // Restore the most-recently-used tab from localStorage so users don't\n // lose their tab selection across reloads.\n //\n // Note: we deliberately do NOT mirror `rightPanelShown` from\n // localStorage. The drawer's open/closed state is session-only — see\n // the comment in `useConversationStore` and the schema note in\n // `conversation-local-storage.ts` for the rationale.\n useEffect(() => {\n setSelectedTab(persistedState.selectedTab);\n }, [setSelectedTab, persistedState.selectedTab]);\n\n useEffect(() => {\n const handlePanelVisibilityChange = () => {\n if (isRightPanelShown) {\n // If no tab is selected, default to files tab\n if (!selectedTab) {\n onTabChange(\"files\");\n }\n }\n };\n\n handlePanelVisibilityChange();\n }, [isRightPanelShown, selectedTab, onTabChange]);\n\n const { t, i18n } = useTranslation(\"openhands\");\n\n // `files` is intentionally the leftmost tab — it's the primary entry\n // point for inspecting agent output (workspace files + git diff).\n const tabs = [\n {\n tabValue: \"files\",\n isActive: isTabActive(\"files\"),\n icon: DocumentIcon,\n onClick: () => selectTab(\"files\"),\n tooltipContent: t(I18nKey.COMMON$FILES),\n tooltipAriaLabel: t(I18nKey.COMMON$FILES),\n label: t(I18nKey.COMMON$FILES),\n },\n {\n tabValue: \"planner\",\n isActive: isTabActive(\"planner\"),\n icon: LessonPlanIcon,\n onClick: () => selectTab(\"planner\"),\n tooltipContent: t(I18nKey.COMMON$PLANNER),\n tooltipAriaLabel: t(I18nKey.COMMON$PLANNER),\n label: t(I18nKey.COMMON$PLANNER),\n },\n {\n tabValue: \"vscode\",\n isActive: isTabActive(\"vscode\"),\n icon: VSCodeIcon,\n onClick: () => selectTab(\"vscode\"),\n tooltipContent: <VSCodeTooltipContent />,\n tooltipAriaLabel: t(I18nKey.COMMON$CODE),\n label: t(I18nKey.COMMON$CODE),\n },\n {\n tabValue: \"terminal\",\n isActive: isTabActive(\"terminal\"),\n icon: TerminalIcon,\n onClick: () => selectTab(\"terminal\"),\n tooltipContent: t(I18nKey.COMMON$TERMINAL),\n tooltipAriaLabel: t(I18nKey.COMMON$TERMINAL),\n label: t(I18nKey.COMMON$TERMINAL),\n className: \"pl-2\",\n },\n {\n tabValue: \"browser\",\n isActive: isTabActive(\"browser\"),\n icon: GlobeIcon,\n onClick: () => selectTab(\"browser\"),\n tooltipContent: t(I18nKey.COMMON$BROWSER),\n tooltipAriaLabel: t(I18nKey.COMMON$BROWSER),\n label: t(I18nKey.COMMON$BROWSER),\n },\n ];\n\n if (hasTaskList) {\n // Insert after `files` so the leftmost slot stays Files.\n tabs.splice(1, 0, {\n tabValue: \"tasklist\",\n isActive: isTabActive(\"tasklist\"),\n icon: DoubleCheckIcon,\n onClick: () => selectTab(\"tasklist\"),\n tooltipContent: t(I18nKey.COMMON$TASK_LIST),\n tooltipAriaLabel: t(I18nKey.COMMON$TASK_LIST),\n label: t(I18nKey.COMMON$TASK_LIST),\n });\n }\n\n // Pinned tabs always show in the bar. Unpinned tabs stay hidden unless the\n // user has that tab selected — then it appears while active so the bar\n // matches the open panel. Hide VS Code on local backends (cloud-only URL).\n const visibleTabs = tabs.filter((tab) => {\n if (tab.tabValue === \"vscode\" && backend.kind !== \"cloud\") return false;\n if (!persistedState.unpinnedTabs.includes(tab.tabValue)) return true;\n return selectedTab === tab.tabValue;\n });\n\n const unpinnedSignature = persistedState.unpinnedTabs.join(\",\");\n\n const isAgentRunning =\n curAgentState === AgentState.RUNNING ||\n curAgentState === AgentState.LOADING;\n const isBuildDisabled = isAgentRunning || !planContent;\n\n const tabsRowInnerRef = useRef<HTMLDivElement>(null);\n const measureRowRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [inlineTabCount, setInlineTabCount] = useState(visibleTabs.length);\n\n useLayoutEffect(() => {\n const rowInner = tabsRowInnerRef.current;\n const measureRow = measureRowRef.current;\n const menuEl = menuRef.current;\n if (!rowInner || !measureRow || !menuEl) return undefined;\n\n const measure = () => {\n const measureButtons = measureRow.querySelectorAll<HTMLButtonElement>(\n '[data-tab-measure=\"true\"]',\n );\n const tabCount = measureButtons.length;\n\n const rowWidth = rowInner.getBoundingClientRect().width;\n if (rowWidth === 0) {\n setInlineTabCount(tabCount);\n return;\n }\n\n const widths = Array.from(measureButtons).map(\n (button) => button.getBoundingClientRect().width,\n );\n\n if (widths.length !== tabCount || tabCount === 0) {\n setInlineTabCount(Math.max(0, tabCount));\n return;\n }\n\n const menuWidth = menuEl.getBoundingClientRect().width;\n const gapCss =\n getComputedStyle(rowInner).columnGap || getComputedStyle(rowInner).gap;\n const gapPx = parseFloat(gapCss) || 6;\n\n let nextCount = 0;\n for (let k = tabCount; k >= 0; k -= 1) {\n let total = menuWidth;\n for (let i = 0; i < k; i += 1) {\n total += widths[i] ?? 0;\n }\n if (k > 0) {\n total += k * gapPx;\n }\n if (total <= rowWidth + 0.5) {\n nextCount = k;\n break;\n }\n }\n\n setInlineTabCount((prev) => (prev === nextCount ? prev : nextCount));\n };\n\n measure();\n if (typeof ResizeObserver === \"undefined\") return undefined;\n const ro = new ResizeObserver(measure);\n ro.observe(rowInner);\n return () => ro.disconnect();\n }, [\n unpinnedSignature,\n visibleTabs.length,\n hasTaskList,\n backend.kind,\n selectedTab,\n isRightPanelShown,\n i18n.language,\n ]);\n\n const safeInlineTabCount = Math.min(inlineTabCount, visibleTabs.length);\n\n return (\n <>\n <div\n className={cn(\n \"relative w-full min-w-0\",\n variant === \"compact\"\n ? \"flex h-full min-h-0 items-center py-0 pl-0 pr-1\"\n : \"min-h-10 p-1\",\n )}\n >\n <div\n ref={measureRowRef}\n aria-hidden\n className=\"pointer-events-none absolute top-0 left-[-10000px] flex flex-nowrap items-center gap-1.5\"\n >\n {visibleTabs.map(\n (\n {\n tabValue,\n icon,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`measure-${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={() => {}}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n measureOnly\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n <div\n ref={tabsRowInnerRef}\n className=\"flex w-full min-w-0 flex-nowrap items-center justify-start\"\n >\n <div className=\"flex w-fit max-w-full min-w-0 flex-nowrap items-center gap-1.5\">\n <div className=\"flex min-w-0 flex-1 flex-nowrap items-center gap-1.5 overflow-x-hidden\">\n {visibleTabs\n .slice(0, safeInlineTabCount)\n .map(\n (\n {\n tabValue,\n icon,\n onClick,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={onClick}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n <div ref={menuRef} className=\"relative shrink-0\">\n <EllipsisButton\n ref={anchorRef}\n onClick={() => setIsMenuOpen(!isMenuOpen)}\n ariaLabel={t(I18nKey.COMMON$MORE_OPTIONS)}\n iconClassName={\n variant === \"compact\" ? mobileTopBarIconClassName : undefined\n }\n />\n <ConversationTabsContextMenu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n ignoreOutsideClickRef={anchorRef}\n />\n </div>\n </div>\n </div>\n </div>\n {isTabActive(\"planner\") && (\n <div\n className={cn(\n \"flex h-10 min-h-10 shrink-0 items-center border-t border-[var(--oh-border)] pl-[10px] pr-1\",\n )}\n >\n <button\n type=\"button\"\n onClick={handleBuildPlanClick}\n disabled={isBuildDisabled}\n className={cn(\n \"flex h-5 min-w-17 items-center justify-center rounded bg-white px-2 transition-opacity\",\n isBuildDisabled\n ? \"cursor-not-allowed opacity-50\"\n : \"cursor-pointer hover:opacity-90\",\n )}\n data-testid=\"planner-tab-build-button\"\n >\n <Typography.Text className=\"text-[11px] font-normal leading-5 text-black\">\n {/* eslint-disable-next-line i18next/no-literal-string */}\n {t(I18nKey.COMMON$BUILD)} ⌘↩\n </Typography.Text>\n </button>\n </div>\n )}\n </>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conversation-tabs.cjs","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport TerminalIcon from \"#/icons/terminal.svg?react\";\nimport GlobeIcon from \"#/icons/globe.svg?react\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport LessonPlanIcon from \"#/icons/lesson-plan.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { EllipsisButton } from \"#/components/features/conversation-panel/ellipsis-button\";\nimport { cn } from \"#/utils/utils\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport { ConversationTabNav } from \"./conversation-tab-nav\";\nimport { ChatActionTooltip } from \"../../chat/chat-action-tooltip\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { VSCodeTooltipContent } from \"./vscode-tooltip-content\";\nimport { useConversationStore } from \"#/stores/conversation-store\";\nimport { ConversationTabsContextMenu } from \"./conversation-tabs-context-menu\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useHandleBuildPlanClick } from \"#/hooks/use-handle-build-plan-click\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { Typography } from \"#/ui/typography\";\nimport { mobileTopBarIconClassName } from \"#/utils/mobile-top-bar-icon-button-classes\";\n\nexport function ConversationTabs({\n variant = \"default\",\n}: {\n variant?: \"default\" | \"compact\";\n}) {\n const { conversationId } = useConversationId();\n const { setSelectedTab, planContent } = useConversationStore();\n\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const { state: persistedState } =\n useConversationLocalStorageState(conversationId);\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const { handleBuildPlanClick } = useHandleBuildPlanClick();\n const { curAgentState } = useAgentState();\n\n const {\n selectTab,\n isTabActive,\n onTabChange,\n selectedTab,\n isRightPanelShown,\n } = useSelectConversationTab();\n\n // Restore the most-recently-used tab from localStorage so users don't\n // lose their tab selection across reloads.\n //\n // Note: we deliberately do NOT mirror `rightPanelShown` from\n // localStorage. The drawer's open/closed state is session-only — see\n // the comment in `useConversationStore` and the schema note in\n // `conversation-local-storage.ts` for the rationale.\n useEffect(() => {\n setSelectedTab(persistedState.selectedTab);\n }, [setSelectedTab, persistedState.selectedTab]);\n\n useEffect(() => {\n const handlePanelVisibilityChange = () => {\n if (isRightPanelShown) {\n // If no tab is selected, default to files tab\n if (!selectedTab) {\n onTabChange(\"files\");\n }\n }\n };\n\n handlePanelVisibilityChange();\n }, [isRightPanelShown, selectedTab, onTabChange]);\n\n const { t, i18n } = useTranslation(\"openhands\");\n\n // `files` is intentionally the leftmost tab — it's the primary entry\n // point for inspecting agent output (workspace files + git diff).\n const tabs = [\n {\n tabValue: \"files\",\n isActive: isTabActive(\"files\"),\n icon: DocumentIcon,\n onClick: () => selectTab(\"files\"),\n tooltipContent: t(I18nKey.COMMON$FILES),\n tooltipAriaLabel: t(I18nKey.COMMON$FILES),\n label: t(I18nKey.COMMON$FILES),\n },\n {\n tabValue: \"planner\",\n isActive: isTabActive(\"planner\"),\n icon: LessonPlanIcon,\n onClick: () => selectTab(\"planner\"),\n tooltipContent: t(I18nKey.COMMON$PLANNER),\n tooltipAriaLabel: t(I18nKey.COMMON$PLANNER),\n label: t(I18nKey.COMMON$PLANNER),\n },\n {\n tabValue: \"vscode\",\n isActive: isTabActive(\"vscode\"),\n icon: VSCodeIcon,\n onClick: () => selectTab(\"vscode\"),\n tooltipContent: <VSCodeTooltipContent />,\n tooltipAriaLabel: t(I18nKey.COMMON$CODE),\n label: t(I18nKey.COMMON$CODE),\n },\n {\n tabValue: \"terminal\",\n isActive: isTabActive(\"terminal\"),\n icon: TerminalIcon,\n onClick: () => selectTab(\"terminal\"),\n tooltipContent: t(I18nKey.COMMON$TERMINAL),\n tooltipAriaLabel: t(I18nKey.COMMON$TERMINAL),\n label: t(I18nKey.COMMON$TERMINAL),\n className: \"pl-2\",\n },\n {\n tabValue: \"browser\",\n isActive: isTabActive(\"browser\"),\n icon: GlobeIcon,\n onClick: () => selectTab(\"browser\"),\n tooltipContent: t(I18nKey.COMMON$BROWSER),\n tooltipAriaLabel: t(I18nKey.COMMON$BROWSER),\n label: t(I18nKey.COMMON$BROWSER),\n },\n ];\n\n if (hasTaskList) {\n // Insert after `files` so the leftmost slot stays Files.\n tabs.splice(1, 0, {\n tabValue: \"tasklist\",\n isActive: isTabActive(\"tasklist\"),\n icon: DoubleCheckIcon,\n onClick: () => selectTab(\"tasklist\"),\n tooltipContent: t(I18nKey.COMMON$TASK_LIST),\n tooltipAriaLabel: t(I18nKey.COMMON$TASK_LIST),\n label: t(I18nKey.COMMON$TASK_LIST),\n });\n }\n\n // Pinned tabs always show in the bar. Unpinned tabs stay hidden unless the\n // user has that tab selected — then it appears while active so the bar\n // matches the open panel. Hide VS Code and Planner on local backends —\n // both are cloud-only (the planning agent isn't supported locally).\n const visibleTabs = tabs.filter((tab) => {\n if (tab.tabValue === \"vscode\" && backend.kind !== \"cloud\") return false;\n if (tab.tabValue === \"planner\" && backend.kind !== \"cloud\") return false;\n if (!persistedState.unpinnedTabs.includes(tab.tabValue)) return true;\n return selectedTab === tab.tabValue;\n });\n\n const unpinnedSignature = persistedState.unpinnedTabs.join(\",\");\n\n const isAgentRunning =\n curAgentState === AgentState.RUNNING ||\n curAgentState === AgentState.LOADING;\n const isBuildDisabled = isAgentRunning || !planContent;\n\n const tabsRowInnerRef = useRef<HTMLDivElement>(null);\n const measureRowRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [inlineTabCount, setInlineTabCount] = useState(visibleTabs.length);\n\n useLayoutEffect(() => {\n const rowInner = tabsRowInnerRef.current;\n const measureRow = measureRowRef.current;\n const menuEl = menuRef.current;\n if (!rowInner || !measureRow || !menuEl) return undefined;\n\n const measure = () => {\n const measureButtons = measureRow.querySelectorAll<HTMLButtonElement>(\n '[data-tab-measure=\"true\"]',\n );\n const tabCount = measureButtons.length;\n\n const rowWidth = rowInner.getBoundingClientRect().width;\n if (rowWidth === 0) {\n setInlineTabCount(tabCount);\n return;\n }\n\n const widths = Array.from(measureButtons).map(\n (button) => button.getBoundingClientRect().width,\n );\n\n if (widths.length !== tabCount || tabCount === 0) {\n setInlineTabCount(Math.max(0, tabCount));\n return;\n }\n\n const menuWidth = menuEl.getBoundingClientRect().width;\n const gapCss =\n getComputedStyle(rowInner).columnGap || getComputedStyle(rowInner).gap;\n const gapPx = parseFloat(gapCss) || 6;\n\n let nextCount = 0;\n for (let k = tabCount; k >= 0; k -= 1) {\n let total = menuWidth;\n for (let i = 0; i < k; i += 1) {\n total += widths[i] ?? 0;\n }\n if (k > 0) {\n total += k * gapPx;\n }\n if (total <= rowWidth + 0.5) {\n nextCount = k;\n break;\n }\n }\n\n setInlineTabCount((prev) => (prev === nextCount ? prev : nextCount));\n };\n\n measure();\n if (typeof ResizeObserver === \"undefined\") return undefined;\n const ro = new ResizeObserver(measure);\n ro.observe(rowInner);\n return () => ro.disconnect();\n }, [\n unpinnedSignature,\n visibleTabs.length,\n hasTaskList,\n backend.kind,\n selectedTab,\n isRightPanelShown,\n i18n.language,\n ]);\n\n const safeInlineTabCount = Math.min(inlineTabCount, visibleTabs.length);\n\n return (\n <>\n <div\n className={cn(\n \"relative w-full min-w-0\",\n variant === \"compact\"\n ? \"flex h-full min-h-0 items-center py-0 pl-0 pr-1\"\n : \"min-h-10 p-1\",\n )}\n >\n <div\n ref={measureRowRef}\n aria-hidden\n className=\"pointer-events-none absolute top-0 left-[-10000px] flex flex-nowrap items-center gap-1.5\"\n >\n {visibleTabs.map(\n (\n {\n tabValue,\n icon,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`measure-${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={() => {}}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n measureOnly\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n <div\n ref={tabsRowInnerRef}\n className=\"flex w-full min-w-0 flex-nowrap items-center justify-start\"\n >\n <div className=\"flex w-fit max-w-full min-w-0 flex-nowrap items-center gap-1.5\">\n <div className=\"flex min-w-0 flex-1 flex-nowrap items-center gap-1.5 overflow-x-hidden\">\n {visibleTabs\n .slice(0, safeInlineTabCount)\n .map(\n (\n {\n tabValue,\n icon,\n onClick,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={onClick}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n <div ref={menuRef} className=\"relative shrink-0\">\n <EllipsisButton\n ref={anchorRef}\n onClick={() => setIsMenuOpen(!isMenuOpen)}\n ariaLabel={t(I18nKey.COMMON$MORE_OPTIONS)}\n iconClassName={\n variant === \"compact\" ? mobileTopBarIconClassName : undefined\n }\n />\n <ConversationTabsContextMenu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n ignoreOutsideClickRef={anchorRef}\n />\n </div>\n </div>\n </div>\n </div>\n {isTabActive(\"planner\") && (\n <div\n className={cn(\n \"flex h-10 min-h-10 shrink-0 items-center border-t border-[var(--oh-border)] pl-[10px] pr-1\",\n )}\n >\n <button\n type=\"button\"\n onClick={handleBuildPlanClick}\n disabled={isBuildDisabled}\n className={cn(\n \"flex h-5 min-w-17 items-center justify-center rounded bg-white px-2 transition-opacity\",\n isBuildDisabled\n ? \"cursor-not-allowed opacity-50\"\n : \"cursor-pointer hover:opacity-90\",\n )}\n data-testid=\"planner-tab-build-button\"\n >\n <Typography.Text className=\"text-[11px] font-normal leading-5 text-black\">\n {/* eslint-disable-next-line i18next/no-literal-string */}\n {t(I18nKey.COMMON$BUILD)} ⌘↩\n </Typography.Text>\n </button>\n </div>\n )}\n </>\n );\n}\n"],"mappings":"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"}
|