@openhands/agent-canvas 1.4.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -12
- package/README.windows.md +4 -2
- package/build/assets/{Trans-Ch-OVWEA.js → Trans-DqF_OEZB.js} +1 -1
- package/build/assets/{acp-providers-Sy2LKyMa.js → acp-providers-DerAmTyY.js} +1 -1
- package/build/assets/active-backend-context-B8rMv0X9.js +1 -0
- package/build/assets/{add-backend-modal-Bgy8anoR.js → add-backend-modal-CxC7BNEc.js} +1 -1
- package/build/assets/{agent-profiles-settings-3mmXljZX.js → agent-profiles-settings-BJb8YXR1.js} +1 -1
- package/build/assets/agent-server-compatibility-BWN-EIQn.js +1 -0
- package/build/assets/agent-server-conversation-service.api-DSPIkMwJ.js +41 -0
- package/build/assets/{agent-settings-B-W10B4E.js → agent-settings-CgCnqaAA.js} +2 -2
- package/build/assets/agent-settings-DDkSavD7.js +1 -0
- package/build/assets/{alert-banner-Bpf2NQJq.js → alert-banner-Dh51WURQ.js} +1 -1
- package/build/assets/api-key-entry-screen-iZc7n8AI.js +1 -0
- package/build/assets/app-settings-B5zyipxJ.js +1 -0
- package/build/assets/automation-detail-CZsu2CoM.js +2 -0
- package/build/assets/automation-export-BwRX6H32.js +2 -0
- package/build/assets/automations-list-lHAVzMoA.js +1 -0
- package/build/assets/{back-nav-button-CUS2mi-U.js → back-nav-button-DVknCcSP.js} +1 -1
- package/build/assets/backend-form-modal-RGcu909r.js +1 -0
- package/build/assets/{backend-synced-settings-badge-D9hZx05w.js → backend-synced-settings-badge-BSfN0AZA.js} +1 -1
- package/build/assets/{base-modal-BuF2f0YL.js → base-modal-CIF_785P.js} +1 -1
- package/build/assets/{bot-D7eUAuSB.js → bot-C-EA6685.js} +1 -1
- package/build/assets/{brand-button-vMVuyDXu.js → brand-button-B1izLAdR.js} +1 -1
- package/build/assets/{browser-BifzWIBd.js → browser-DKaeq_sT.js} +3 -3
- package/build/assets/{browser-tab-CkkqJnqw.js → browser-tab-qb_ftCxW.js} +1 -1
- package/build/assets/canvas-ui-COgjltGz.js +1 -0
- package/build/assets/{chat-send-button-B_jc5z5C.js → chat-send-button-BZHG2hAW.js} +1 -1
- package/build/assets/check-TbOEtHKj.js +1 -0
- package/build/assets/{chevron-down-CI8A6tet.js → chevron-down-D7IvFMBM.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-C5YxjxvI.js → circle-plus-check-toggle-DoFIjVE0.js} +1 -1
- package/build/assets/client-source-BZK8vRs2.js +1 -0
- package/build/assets/cloud-funnel-analytics-Zcv57hfT.js +1 -0
- package/build/assets/{color-themes-DPBzNtVg.js → color-themes-CHizm1xF.js} +1 -1
- package/build/assets/{combobox-caret-DoObzqf4.js → combobox-caret-CxZpqoSR.js} +1 -1
- package/build/assets/{command-menu-D-JV3Wqm.js → command-menu-oTvKDU3Y.js} +1 -1
- package/build/assets/condenser-settings-BGlWn93P.js +1 -0
- package/build/assets/{confirmation-modal-BGLu6XJN.js → confirmation-modal-DGBWM2Ls.js} +1 -1
- package/build/assets/{context-menu-list-item-BD5_EaKN.js → context-menu-list-item-6psNyl7X.js} +1 -1
- package/build/assets/conversation-BoCYx8n2.js +89 -0
- package/build/assets/conversation-DgHqMjnY.js +1 -0
- package/build/assets/conversation-panel-78Rxh_-I.js +1 -0
- package/build/assets/conversation-service.api-_f9GlIEi.js +1 -0
- package/build/assets/{conversation-tab-empty-state-B2dDYEwf.js → conversation-tab-empty-state-CNUmIms2.js} +1 -1
- package/build/assets/{copy-3JCw_XFB.js → copy-D1YGjP-C.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-CaR52OnA.js → copy-to-clipboard-button-CFzH_NOX.js} +1 -1
- package/build/assets/declaration-BGsHjPEW.js +1 -0
- package/build/assets/{device-verify-Dj6I4Iqe.js → device-verify-WBSjJBLH.js} +1 -1
- package/build/assets/{dropdown-classes-DJSXeLqc.js → dropdown-classes-D3wMJlXT.js} +1 -1
- package/build/assets/{ellipsis-button-C5Z-tPFp.js → ellipsis-button-CbNnHlIq.js} +1 -1
- package/build/assets/{entry.client-2_3ePAm0.js → entry.client-DNlPGxsu.js} +2 -2
- package/build/assets/{enum-filter-dropdown-DXbVwiNZ.js → enum-filter-dropdown-JLYv1t8L.js} +1 -1
- package/build/assets/{environment-switch-overlay-DZQfRGTx.js → environment-switch-overlay-B1PFO8P8.js} +1 -1
- package/build/assets/{extensions-hub-CLjmOGqS.js → extensions-hub-CCbLA7IM.js} +1 -1
- package/build/assets/{extensions-navigation-B5MeUiMq.js → extensions-navigation-CPNjMNvR.js} +1 -1
- package/build/assets/{external-link-D2zJjE9G.js → external-link-lhdITPqq.js} +1 -1
- package/build/assets/files-tab-y4K7EXBO.js +1 -0
- package/build/assets/{form-control-classes-ChpNBe9n.js → form-control-classes-CbdN5aO3.js} +1 -1
- package/build/assets/format-time-delta-DhDbkD7V.js +1 -0
- package/build/assets/git-provider-icon-ITvsH4Ko.js +1 -0
- package/build/assets/home-BwbeOWwU.js +1 -0
- package/build/assets/home-DKPGQ5P3.js +1 -0
- package/build/assets/index-home-Bko2Itv5.js +1 -0
- package/build/assets/install-server-modal-Qk1gwyI8.js +1 -0
- package/build/assets/{launch-V_3Rp7WS.js → launch-CAGavYl-.js} +1 -1
- package/build/assets/lesson-plan-DMCPdtrf.js +4 -0
- package/build/assets/{list-todo-BfH6yYUK.js → list-todo-CAtvkzcy.js} +1 -1
- package/build/assets/llm-not-configured-banner-C1ktyb3C.js +27 -0
- package/build/assets/llm-settings-BBsZFi9l.js +1 -0
- package/build/assets/llm-settings-DFkJQr_w.js +1 -0
- package/build/assets/llm-subscription-service-Casyzgn1.js +1 -0
- package/build/assets/loader-circle-CsAsfLIs.js +1 -0
- package/build/assets/{loading-spinner-BLdswi6q.js → loading-spinner-BcdnT0mN.js} +1 -1
- package/build/assets/manage-backends-modal-CKQ46rvw.js +1 -0
- package/build/assets/manifest-03478bbf.js +1 -0
- package/build/assets/{map-provider-BM2SJarp.js → map-provider-BbIb12oh.js} +1 -1
- package/build/assets/{markdown-renderer-DMT7Zkpd.js → markdown-renderer-B4V2OMFP.js} +1 -1
- package/build/assets/{mcp-BQufNPZ6.js → mcp-BapoJsDc.js} +2 -2
- package/build/assets/{messages-BnJCqnFf.js → messages-CUBFMY5o.js} +26 -26
- package/build/assets/{modal-body-DouOE5KH.js → modal-body-Cc2zp0xb.js} +1 -1
- package/build/assets/{modal-classes-Cf-4tbHz.js → modal-classes-3qT9Ap7Q.js} +1 -1
- package/build/assets/{modal-close-button-B6CfxxJj.js → modal-close-button-BcIBUdSq.js} +1 -1
- package/build/assets/model-selector-DJrMrFAr.js +1 -0
- package/build/assets/onboarding-6NMkdNxV.js +1 -0
- package/build/assets/onboarding-modal-Q4AnpIdg.js +1 -0
- package/build/assets/organization-service.api-vrRNwOma.js +1 -0
- package/build/assets/path-utils-PNfCKQDV.js +1 -0
- package/build/assets/{pencil-Dj2XjKmI.js → pencil-CWhApFIT.js} +1 -1
- package/build/assets/{plan-components-CcCBmCzW.js → plan-components-BdZXPyZU.js} +1 -1
- package/build/assets/{planner-tab-Dhyqcqmb.js → planner-tab-ByOw1he8.js} +1 -1
- package/build/assets/plugins-management-service-B75jyC56.js +1 -0
- package/build/assets/profiles-service.api-BQTklD5D.js +1 -0
- package/build/assets/providers-DfTB2gPd.js +1 -0
- package/build/assets/proxy-B3tCGf0X.js +1 -0
- package/build/assets/{recommended-automations-launcher-CTcGTl4d.js → recommended-automations-launcher-Bj7PuHY1.js} +1 -1
- package/build/assets/{refresh-cw-DM82EIyx.js → refresh-cw-B9B7-vsy.js} +1 -1
- package/build/assets/root-CDnuTToz.js +2 -0
- package/build/assets/root-CYWeTrWE.css +1 -0
- package/build/assets/root-layout-DfYVlcRG.js +2 -0
- package/build/assets/{runtime-waiting-state-BsXLElvN.js → runtime-waiting-state-CnyVhX4T.js} +1 -1
- package/build/assets/schema-field-CUwk4wrQ.js +1 -0
- package/build/assets/sdk-section-page-DLLNrYjI.js +1 -0
- package/build/assets/{sdk-settings-schema-Cv7M9eSe.js → sdk-settings-schema-CLR01YIK.js} +1 -1
- package/build/assets/search-dIQ09UY2.js +1 -0
- package/build/assets/secrets-service-CvyPWJhg.js +1 -0
- package/build/assets/{secrets-settings-Cx6yJlyb.js → secrets-settings-CHy72A5C.js} +1 -1
- package/build/assets/{segmented-toggle-DyQqPhoD.js → segmented-toggle-kzwZkLaj.js} +1 -1
- package/build/assets/settings-B9S8UVQr.js +1 -0
- package/build/assets/{settings-dropdown-input-BjunGXJb.js → settings-dropdown-input-Dhx9ErGd.js} +1 -1
- package/build/assets/{settings-index-D6sxWSRk.js → settings-index-BKDl2CQ-.js} +1 -1
- package/build/assets/{settings-input-bD6npsDm.js → settings-input-BsgQWS5R.js} +1 -1
- package/build/assets/{settings-list-classes-Dp_OgzN0.js → settings-list-classes-DSJJX99U.js} +1 -1
- package/build/assets/settings-modal-DeK11CyT.js +1 -0
- package/build/assets/settings-service.api-DXk5TdeJ.js +1 -0
- package/build/assets/{settings-switch-5cuxl8Dc.js → settings-switch-Bes8dIlV.js} +1 -1
- package/build/assets/{settings-utils-BMdG65By.js → settings-utils-DzCVfiR3.js} +1 -1
- package/build/assets/shared-conversation-9atDzTR4.js +1 -0
- package/build/assets/{sidebar-layout-DuzJMMw-.js → sidebar-layout-Bm7pa3Vk.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-VvvX32iF.js → sidebar-mobile-menu-toggle-giMMZctn.js} +1 -1
- package/build/assets/{sidebar-nav-link-5AlTT5-j.js → sidebar-nav-link-CHqyFXwV.js} +1 -1
- package/build/assets/{sidebar-store-CZuE8AH5.js → sidebar-store-uiUXBU1N.js} +1 -1
- package/build/assets/{skill-card-pill-row-eTIkE4nz.js → skill-card-pill-row-BPYKQ3IN.js} +1 -1
- package/build/assets/skills-plugins-Tropusio.js +1 -0
- package/build/assets/{skills-settings-BUv04tSc.js → skills-settings-BvzBBCWk.js} +2 -2
- package/build/assets/{square-chevron-right-Czw3FFWc.js → square-chevron-right-DE-JN-2Z.js} +1 -1
- package/build/assets/{styled-tooltip-CgX2oRaK.js → styled-tooltip-B14i_Uac.js} +1 -1
- package/build/assets/{suspense-BO1Tl_Vf.js → suspense-DmZ3MSSh.js} +1 -1
- package/build/assets/{task-list-tab-0k9PhuqO.js → task-list-tab-DyfgG4MC.js} +1 -1
- package/build/assets/telemetry-C5JMEfqB.js +2 -0
- package/build/assets/{terminal-B61WrJdS.js → terminal-DRXt2Lr4.js} +1 -1
- package/build/assets/{toggle-switch-2j5wwR85.js → toggle-switch-DX_k418f.js} +1 -1
- package/build/assets/{trash-2-Be_7y3Mn.js → trash-2-BU6BlW4i.js} +1 -1
- package/build/assets/{typography-D8mHDeNG.js → typography-CzfoD9DY.js} +1 -1
- package/build/assets/use-acp-credential-form-Bm8qXdlc.js +1 -0
- package/build/assets/{use-activate-agent-profile-20v1xU0H.js → use-activate-agent-profile-DlykqEfN.js} +1 -1
- package/build/assets/{use-active-agent-profile-BkJN7Xsy.js → use-active-agent-profile-hI-x-UBa.js} +1 -1
- package/build/assets/{use-active-conversation-DOZVSVtU.js → use-active-conversation-2qeez40F.js} +1 -1
- package/build/assets/use-agent-profiles-0pr5bLS7.js +1 -0
- package/build/assets/{use-agent-state-DHZO1obC.js → use-agent-state-C6peDXUm.js} +1 -1
- package/build/assets/use-backends-health-CLHPitJM.js +1 -0
- package/build/assets/{use-can-manage-org-profiles-C-OhWVBS.js → use-can-manage-org-profiles-Ck_bsNbH.js} +1 -1
- package/build/assets/use-cloud-current-user-id-DUCSxNjY.js +1 -0
- package/build/assets/use-config-B5r8erYt.js +1 -0
- package/build/assets/use-create-conversation-r1JHfKO5.js +1 -0
- package/build/assets/{use-create-secret-D0HCOZFu.js → use-create-secret-Cf2N11d2.js} +1 -1
- package/build/assets/{use-event-store-DjgU4wfO.js → use-event-store-Bbaz51GR.js} +1 -1
- package/build/assets/{use-handle-plan-click-DyRASKMC.js → use-handle-plan-click-CsAW3FlH.js} +1 -1
- package/build/assets/use-is-authed-BezEyfeh.js +1 -0
- package/build/assets/use-llm-profiles-Dr5__SlZ.js +1 -0
- package/build/assets/use-plugins-marketplace-BplU65ae.js +1 -0
- package/build/assets/use-runtime-is-ready-vCFOcLFa.js +1 -0
- package/build/assets/use-save-agent-profile-RqUGqTv6.js +1 -0
- package/build/assets/use-save-settings-Chvzeu2s.js +1 -0
- package/build/assets/use-settings-CyxSlyTQ.js +1 -0
- package/build/assets/use-settings-nav-items-zEkSO_Bf.js +16 -0
- package/build/assets/use-skills-xrVoKYrF.js +1 -0
- package/build/assets/{use-task-list-AVBLbbcR.js → use-task-list-CfisapBW.js} +1 -1
- package/build/assets/use-tracking-D2Qg5Lpd.js +1 -0
- package/build/assets/{use-user-conversation-zpx7I18x.js → use-user-conversation-CnE4zhOA.js} +1 -1
- package/build/assets/{useMutation-DrCAVg5w.js → useMutation-u8UgRgDK.js} +1 -1
- package/build/assets/{useMutationState-D8QN0ZCy.js → useMutationState-OnAsCLA_.js} +1 -1
- package/build/assets/{useQueries-DClgUTc7.js → useQueries-BpIlT8Mt.js} +1 -1
- package/build/assets/{useQuery-CRBP8vIS.js → useQuery-D5pEZbY0.js} +1 -1
- package/build/assets/{useTranslation-CDRCKC9-.js → useTranslation-Cbf5AGg_.js} +1 -1
- package/build/assets/{utils-D3U3rlqr.js → utils-DB9LsAzA.js} +1 -1
- package/build/assets/{vendor~browser-tab-Di0kh5Zw.js → vendor~browser-tab-CsMb-pta.js} +1 -1
- package/build/assets/{vendor~browser-Cvg7jXCP.js → vendor~browser-wXQ-WZEC.js} +1 -1
- package/build/assets/{vendor~entry.client-9tWQ_Ugw.js → vendor~entry.client-DDuH4--y.js} +1 -1
- package/build/assets/{vendor~entry.client-D6BtSOtn.js → vendor~entry.client-DQGrNspu.js} +1 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dhilvkxv-eGLBu60s.js +2 -0
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~iztiaf2o-rqo6vRFz.js +185 -0
- package/build/assets/{vendor~files-tab-B02k3xvx.js → vendor~files-tab-B-5fBohe.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation-CYMF9JYB.js → vendor~index-home~home~conversation-panel~conversation-ChmYLVgz.js} +1 -1
- package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BD7v71DM.js +2 -0
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BD0GaRGa.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BT05Osu4.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-D7EUmQ8Y.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DgzWSMRc.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-d8aETPbZ.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DqZatR3B.js} +1 -1
- package/build/assets/{vendor~launch-CHXA9cJu.js → vendor~launch-_Km3J77E.js} +1 -1
- package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~ivvrgjsa-BlIZPCXX.js → vendor~module-D5a_AClf.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-CpiTHpHl.js → vendor~root-layout~conversation-panel~conversation-8tIsyrPj.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-_TdZcNMD.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-BrguKXCn.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation-Cn2jwSga.js → vendor~root-layout~index-home~home~conversation-panel~conversation-BTvhGHHG.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-CZM4hwUT.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation~aler~gfu7qdtz-BOKQkbc6.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~settings~settings-index~agen~enjl5xdm-B0EIDu4M.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~ftka0fnu-cFNmfAE6.js} +2 -2
- package/build/assets/{verification-settings-D576N2xa.js → verification-settings-CfkrXoSa.js} +1 -1
- package/build/assets/x-ZE4iplpF.js +1 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +9 -0
- package/build/locales/ca/openhands.json +9 -0
- package/build/locales/de/openhands.json +9 -0
- package/build/locales/en/openhands.json +9 -0
- package/build/locales/es/openhands.json +9 -0
- package/build/locales/fr/openhands.json +9 -0
- package/build/locales/it/openhands.json +9 -0
- package/build/locales/ja/openhands.json +9 -0
- package/build/locales/ko-KR/openhands.json +9 -0
- package/build/locales/no/openhands.json +9 -0
- package/build/locales/pt/openhands.json +9 -0
- package/build/locales/tr/openhands.json +9 -0
- package/build/locales/uk/openhands.json +9 -0
- package/build/locales/zh-CN/openhands.json +9 -0
- package/build/locales/zh-TW/openhands.json +9 -0
- package/config/defaults.json +5 -4
- package/dist/api/agent-server-adapter.cjs +3 -3
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.d.ts +9 -1
- package/dist/api/agent-server-adapter.js +105 -102
- package/dist/api/agent-server-adapter.js.map +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 +3 -0
- package/dist/api/agent-server-config.js +45 -23
- package/dist/api/agent-server-config.js.map +1 -1
- package/dist/api/backend-registry/auth.cjs +1 -1
- package/dist/api/backend-registry/auth.cjs.map +1 -1
- package/dist/api/backend-registry/auth.js +1 -1
- package/dist/api/backend-registry/auth.js.map +1 -1
- package/dist/api/backend-registry/default-backend.cjs +1 -1
- package/dist/api/backend-registry/default-backend.cjs.map +1 -1
- package/dist/api/backend-registry/default-backend.d.ts +3 -0
- package/dist/api/backend-registry/default-backend.js +22 -10
- package/dist/api/backend-registry/default-backend.js.map +1 -1
- package/dist/api/backend-registry/storage.cjs +1 -1
- package/dist/api/backend-registry/storage.cjs.map +1 -1
- package/dist/api/backend-registry/storage.js +38 -33
- package/dist/api/backend-registry/storage.js.map +1 -1
- package/dist/api/backend-registry/types.d.ts +2 -0
- package/dist/api/canvas-ui-client-tool.cjs +38 -0
- package/dist/api/canvas-ui-client-tool.cjs.map +1 -0
- package/dist/api/canvas-ui-client-tool.d.ts +14 -0
- package/dist/api/canvas-ui-client-tool.js +47 -0
- package/dist/api/canvas-ui-client-tool.js.map +1 -0
- package/dist/api/client-source.cjs +2 -0
- package/dist/api/client-source.cjs.map +1 -0
- package/dist/api/client-source.d.ts +9 -0
- package/dist/api/client-source.js +10 -0
- package/dist/api/client-source.js.map +1 -0
- package/dist/api/cloud/client.cjs +2 -0
- package/dist/api/cloud/client.cjs.map +1 -0
- package/dist/api/cloud/client.d.ts +4 -0
- package/dist/api/cloud/client.js +38 -0
- package/dist/api/cloud/client.js.map +1 -0
- package/dist/api/cloud/conversation-service.api.cjs +1 -1
- package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
- package/dist/api/cloud/conversation-service.api.js +35 -33
- package/dist/api/cloud/conversation-service.api.js.map +1 -1
- package/dist/api/cloud/organization-service.api.cjs +1 -1
- package/dist/api/cloud/organization-service.api.cjs.map +1 -1
- package/dist/api/cloud/organization-service.api.js +11 -10
- package/dist/api/cloud/organization-service.api.js.map +1 -1
- package/dist/api/cloud/proxy.cjs +1 -1
- package/dist/api/cloud/proxy.cjs.map +1 -1
- package/dist/api/cloud/proxy.d.ts +2 -40
- package/dist/api/cloud/proxy.js +14 -39
- package/dist/api/cloud/proxy.js.map +1 -1
- package/dist/api/conversation-metadata-store.cjs +1 -1
- package/dist/api/conversation-metadata-store.cjs.map +1 -1
- package/dist/api/conversation-metadata-store.d.ts +2 -9
- package/dist/api/conversation-metadata-store.js +13 -9
- package/dist/api/conversation-metadata-store.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 +2 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +98 -88
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.types.d.ts +5 -0
- package/dist/api/device-flow-client.cjs +1 -1
- package/dist/api/device-flow-client.cjs.map +1 -1
- package/dist/api/device-flow-client.d.ts +4 -58
- package/dist/api/device-flow-client.js +8 -98
- package/dist/api/device-flow-client.js.map +1 -1
- package/dist/api/git-service/agent-server-git-service.api.cjs +1 -1
- package/dist/api/git-service/agent-server-git-service.api.cjs.map +1 -1
- package/dist/api/git-service/agent-server-git-service.api.d.ts +10 -2
- package/dist/api/git-service/agent-server-git-service.api.js +107 -40
- package/dist/api/git-service/agent-server-git-service.api.js.map +1 -1
- package/dist/api/open-hands.types.d.ts +11 -0
- package/dist/api/option-service/option-service.api.cjs +1 -1
- package/dist/api/option-service/option-service.api.cjs.map +1 -1
- package/dist/api/option-service/option-service.api.js +0 -1
- package/dist/api/option-service/option-service.api.js.map +1 -1
- package/dist/api/option-service/option.types.d.ts +0 -1
- package/dist/api/secrets-service.cjs +1 -1
- package/dist/api/secrets-service.cjs.map +1 -1
- package/dist/api/secrets-service.js +15 -14
- package/dist/api/secrets-service.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +73 -64
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.cjs +2 -2
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.js +2 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.js.map +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
- package/dist/components/features/backends/backend-form-modal.d.ts +4 -2
- package/dist/components/features/backends/backend-form-modal.js +108 -101
- package/dist/components/features/backends/backend-form-modal.js.map +1 -1
- package/dist/components/features/backends/backend-row.cjs +1 -1
- package/dist/components/features/backends/backend-row.cjs.map +1 -1
- package/dist/components/features/backends/backend-row.js +2 -1
- package/dist/components/features/backends/backend-row.js.map +1 -1
- package/dist/components/features/backends/backend-selector.cjs +1 -1
- package/dist/components/features/backends/backend-selector.cjs.map +1 -1
- package/dist/components/features/backends/backend-selector.js +51 -51
- package/dist/components/features/backends/backend-selector.js.map +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs.map +1 -1
- package/dist/components/features/backends/device-flow-auth.d.ts +4 -1
- package/dist/components/features/backends/device-flow-auth.js +38 -38
- package/dist/components/features/backends/device-flow-auth.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 +173 -165
- 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.d.ts +2 -1
- package/dist/components/features/chat/components/chat-input-actions.js +44 -43
- package/dist/components/features/chat/components/chat-input-actions.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-container.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-container.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-container.d.ts +2 -1
- package/dist/components/features/chat/components/chat-input-container.js +20 -19
- package/dist/components/features/chat/components/chat-input-container.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-profile-picker.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-profile-picker.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-profile-picker.js +44 -32
- package/dist/components/features/chat/components/chat-input-profile-picker.js.map +1 -1
- package/dist/components/features/chat/components/resolve-picker-kind.cjs +1 -1
- package/dist/components/features/chat/components/resolve-picker-kind.cjs.map +1 -1
- package/dist/components/features/chat/components/resolve-picker-kind.d.ts +10 -22
- package/dist/components/features/chat/components/resolve-picker-kind.js +6 -3
- package/dist/components/features/chat/components/resolve-picker-kind.js.map +1 -1
- package/dist/components/features/chat/custom-chat-input.cjs +1 -1
- package/dist/components/features/chat/custom-chat-input.cjs.map +1 -1
- package/dist/components/features/chat/custom-chat-input.d.ts +2 -1
- package/dist/components/features/chat/custom-chat-input.js +52 -51
- package/dist/components/features/chat/custom-chat-input.js.map +1 -1
- package/dist/components/features/chat/interactive-chat-box.cjs +1 -1
- package/dist/components/features/chat/interactive-chat-box.cjs.map +1 -1
- package/dist/components/features/chat/interactive-chat-box.d.ts +2 -1
- package/dist/components/features/chat/interactive-chat-box.js +9 -8
- package/dist/components/features/chat/interactive-chat-box.js.map +1 -1
- package/dist/components/features/diff-viewer/commit-list.cjs +2 -0
- package/dist/components/features/diff-viewer/commit-list.cjs.map +1 -0
- package/dist/components/features/diff-viewer/commit-list.d.ts +13 -0
- package/dist/components/features/diff-viewer/commit-list.js +27 -0
- package/dist/components/features/diff-viewer/commit-list.js.map +1 -0
- package/dist/components/features/diff-viewer/commit-row.cjs +2 -0
- package/dist/components/features/diff-viewer/commit-row.cjs.map +1 -0
- package/dist/components/features/diff-viewer/commit-row.d.ts +14 -0
- package/dist/components/features/diff-viewer/commit-row.js +59 -0
- package/dist/components/features/diff-viewer/commit-row.js.map +1 -0
- package/dist/components/features/diff-viewer/file-diff-viewer.cjs +1 -1
- package/dist/components/features/diff-viewer/file-diff-viewer.cjs.map +1 -1
- package/dist/components/features/diff-viewer/file-diff-viewer.d.ts +7 -1
- package/dist/components/features/diff-viewer/file-diff-viewer.js +40 -39
- package/dist/components/features/diff-viewer/file-diff-viewer.js.map +1 -1
- package/dist/components/features/plugins/plugin-detail-modal.d.ts +2 -1
- package/dist/components/providers/agent-server-ui-providers.cjs +1 -1
- package/dist/components/providers/agent-server-ui-providers.cjs.map +1 -1
- package/dist/components/providers/agent-server-ui-providers.d.ts +4 -2
- package/dist/components/providers/agent-server-ui-providers.js +9 -2
- package/dist/components/providers/agent-server-ui-providers.js.map +1 -1
- package/dist/components/providers/index.cjs +1 -1
- package/dist/components/providers/index.d.ts +1 -2
- package/dist/components/providers/index.js +0 -1
- package/dist/components/providers/telemetry-provider.cjs +2 -0
- package/dist/components/providers/telemetry-provider.cjs.map +1 -0
- package/dist/components/providers/telemetry-provider.d.ts +6 -0
- package/dist/components/providers/telemetry-provider.js +64 -0
- package/dist/components/providers/telemetry-provider.js.map +1 -0
- package/dist/components/shared/modals/settings/settings-modal.cjs +1 -1
- package/dist/components/shared/modals/settings/settings-modal.cjs.map +1 -1
- package/dist/components/shared/modals/settings/settings-modal.js +23 -22
- package/dist/components/shared/modals/settings/settings-modal.js.map +1 -1
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +5 -4
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants/acp-providers.cjs.map +1 -1
- package/dist/constants/acp-providers.d.ts +1 -1
- package/dist/constants/acp-providers.js.map +1 -1
- package/dist/constants/canvas-ui.cjs +2 -0
- package/dist/constants/canvas-ui.cjs.map +1 -0
- package/dist/constants/canvas-ui.d.ts +8 -0
- package/dist/constants/canvas-ui.js +6 -0
- package/dist/constants/canvas-ui.js.map +1 -0
- package/dist/contexts/conversation-websocket-context.cjs +3 -3
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js +197 -204
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
- package/dist/hooks/mutation/use-create-conversation.cjs.map +1 -1
- package/dist/hooks/mutation/use-create-conversation.d.ts +2 -1
- package/dist/hooks/mutation/use-create-conversation.js +52 -52
- package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
- package/dist/hooks/mutation/use-save-settings.cjs +1 -1
- package/dist/hooks/mutation/use-save-settings.cjs.map +1 -1
- package/dist/hooks/mutation/use-save-settings.d.ts +3 -1
- package/dist/hooks/mutation/use-save-settings.js +6 -5
- package/dist/hooks/mutation/use-save-settings.js.map +1 -1
- package/dist/hooks/query/query-keys.cjs +1 -1
- package/dist/hooks/query/query-keys.cjs.map +1 -1
- package/dist/hooks/query/query-keys.d.ts +2 -0
- package/dist/hooks/query/query-keys.js +4 -1
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-backends-health.cjs +1 -1
- package/dist/hooks/query/use-backends-health.cjs.map +1 -1
- package/dist/hooks/query/use-backends-health.js +50 -48
- package/dist/hooks/query/use-backends-health.js.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.d.ts +1 -0
- package/dist/hooks/query/use-cloud-organizations.js +5 -2
- package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
- package/dist/hooks/query/use-commit-changes.cjs +2 -0
- package/dist/hooks/query/use-commit-changes.cjs.map +1 -0
- package/dist/hooks/query/use-commit-changes.d.ts +5 -0
- package/dist/hooks/query/use-commit-changes.js +34 -0
- package/dist/hooks/query/use-commit-changes.js.map +1 -0
- package/dist/hooks/query/use-task-polling.cjs +1 -1
- package/dist/hooks/query/use-task-polling.cjs.map +1 -1
- package/dist/hooks/query/use-task-polling.d.ts +3 -2
- package/dist/hooks/query/use-task-polling.js +53 -40
- package/dist/hooks/query/use-task-polling.js.map +1 -1
- package/dist/hooks/query/use-unified-git-commits.cjs +2 -0
- package/dist/hooks/query/use-unified-git-commits.cjs.map +1 -0
- package/dist/hooks/query/use-unified-git-commits.d.ts +10 -0
- package/dist/hooks/query/use-unified-git-commits.js +41 -0
- package/dist/hooks/query/use-unified-git-commits.js.map +1 -0
- package/dist/hooks/query/use-unified-git-diff.cjs +1 -1
- package/dist/hooks/query/use-unified-git-diff.cjs.map +1 -1
- package/dist/hooks/query/use-unified-git-diff.d.ts +5 -0
- package/dist/hooks/query/use-unified-git-diff.js +11 -4
- package/dist/hooks/query/use-unified-git-diff.js.map +1 -1
- package/dist/hooks/use-acp-model-context.cjs +1 -1
- package/dist/hooks/use-acp-model-context.cjs.map +1 -1
- package/dist/hooks/use-acp-model-context.d.ts +4 -1
- package/dist/hooks/use-acp-model-context.js +9 -8
- package/dist/hooks/use-acp-model-context.js.map +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.cjs +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.cjs.map +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.js +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.js.map +1 -1
- package/dist/hooks/use-chat-input-model-state.cjs.map +1 -1
- package/dist/hooks/use-chat-input-model-state.d.ts +2 -1
- package/dist/hooks/use-chat-input-model-state.js.map +1 -1
- package/dist/hooks/use-chat-input-profile-state.cjs +1 -1
- package/dist/hooks/use-chat-input-profile-state.cjs.map +1 -1
- package/dist/hooks/use-chat-input-profile-state.d.ts +1 -10
- package/dist/hooks/use-chat-input-profile-state.js +42 -15
- package/dist/hooks/use-chat-input-profile-state.js.map +1 -1
- package/dist/hooks/use-device-flow.cjs +1 -1
- package/dist/hooks/use-device-flow.cjs.map +1 -1
- package/dist/hooks/use-device-flow.d.ts +4 -1
- package/dist/hooks/use-device-flow.js +42 -40
- package/dist/hooks/use-device-flow.js.map +1 -1
- package/dist/hooks/use-telemetry.cjs +1 -1
- package/dist/hooks/use-telemetry.cjs.map +1 -1
- package/dist/hooks/use-telemetry.d.ts +3 -3
- package/dist/hooks/use-telemetry.js +16 -22
- package/dist/hooks/use-telemetry.js.map +1 -1
- package/dist/hooks/use-tracking.cjs +1 -1
- package/dist/hooks/use-tracking.cjs.map +1 -1
- package/dist/hooks/use-tracking.d.ts +5 -5
- package/dist/hooks/use-tracking.js +37 -37
- package/dist/hooks/use-tracking.js.map +1 -1
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +9 -0
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/index.cjs +1 -1
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.js +19 -18
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/translation.cjs +2 -2
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +153 -0
- package/dist/i18n/translation.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +32 -32
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +1 -1
- package/dist/locales/ar/openhands.json +9 -0
- package/dist/locales/ca/openhands.json +9 -0
- package/dist/locales/de/openhands.json +9 -0
- package/dist/locales/en/openhands.json +9 -0
- package/dist/locales/es/openhands.json +9 -0
- package/dist/locales/fr/openhands.json +9 -0
- package/dist/locales/it/openhands.json +9 -0
- package/dist/locales/ja/openhands.json +9 -0
- package/dist/locales/ko-KR/openhands.json +9 -0
- package/dist/locales/no/openhands.json +9 -0
- package/dist/locales/pt/openhands.json +9 -0
- package/dist/locales/tr/openhands.json +9 -0
- package/dist/locales/uk/openhands.json +9 -0
- package/dist/locales/zh-CN/openhands.json +9 -0
- package/dist/locales/zh-TW/openhands.json +9 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.js +351 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.js +106 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js +69 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/clients.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/clients.js +3 -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 +18 -2
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.js.map +1 -1
- package/dist/node_modules/axios/index.cjs +1 -1
- package/dist/node_modules/axios/index.js +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.cjs.map +1 -1
- package/dist/routes/app-settings.js +59 -60
- package/dist/routes/app-settings.js.map +1 -1
- package/dist/routes/commits-tab.cjs +2 -0
- package/dist/routes/commits-tab.cjs.map +1 -0
- package/dist/routes/commits-tab.d.ts +8 -0
- package/dist/routes/commits-tab.js +45 -0
- package/dist/routes/commits-tab.js.map +1 -0
- package/dist/routes/files-tab.cjs +1 -1
- package/dist/routes/files-tab.cjs.map +1 -1
- package/dist/routes/files-tab.js +148 -127
- package/dist/routes/files-tab.js.map +1 -1
- package/dist/routes/llm-settings.cjs +1 -1
- package/dist/routes/llm-settings.cjs.map +1 -1
- package/dist/routes/llm-settings.js +4 -1
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/services/cloud-funnel-analytics.cjs +2 -0
- package/dist/services/cloud-funnel-analytics.cjs.map +1 -0
- package/dist/services/cloud-funnel-analytics.d.ts +4 -0
- package/dist/services/cloud-funnel-analytics.js +39 -0
- package/dist/services/cloud-funnel-analytics.js.map +1 -0
- package/dist/services/telemetry.cjs +1 -1
- package/dist/services/telemetry.cjs.map +1 -1
- package/dist/services/telemetry.d.ts +46 -9
- package/dist/services/telemetry.js +182 -71
- package/dist/services/telemetry.js.map +1 -1
- package/dist/themes/color-themes.cjs.map +1 -1
- package/dist/themes/color-themes.d.ts +3 -6
- package/dist/themes/color-themes.js.map +1 -1
- package/dist/types/agent-server/core/base/action.d.ts +5 -4
- package/dist/types/agent-server/core/base/base.d.ts +3 -2
- package/dist/types/agent-server/core/base/observation.d.ts +1 -1
- package/dist/types/agent-server/type-guards.cjs +1 -1
- package/dist/types/agent-server/type-guards.cjs.map +1 -1
- package/dist/types/agent-server/type-guards.d.ts +3 -5
- package/dist/types/agent-server/type-guards.js +2 -1
- package/dist/types/agent-server/type-guards.js.map +1 -1
- package/dist/types/automation.d.ts +5 -0
- package/dist/utils/api-error-message.d.ts +11 -0
- package/dist/utils/automation-timeout.d.ts +19 -0
- package/dist/utils/base-path.cjs +2 -0
- package/dist/utils/base-path.cjs.map +1 -0
- package/dist/utils/base-path.d.ts +2 -0
- package/dist/utils/base-path.js +23 -0
- package/dist/utils/base-path.js.map +1 -0
- package/dist/utils/error-handler.cjs +1 -1
- package/dist/utils/error-handler.cjs.map +1 -1
- package/dist/utils/error-handler.d.ts +1 -4
- package/dist/utils/error-handler.js +6 -7
- package/dist/utils/error-handler.js.map +1 -1
- package/dist/utils/map-provider.cjs +1 -1
- package/dist/utils/map-provider.cjs.map +1 -1
- package/dist/utils/map-provider.d.ts +1 -0
- package/dist/utils/map-provider.js +2 -1
- package/dist/utils/map-provider.js.map +1 -1
- package/package.json +3 -3
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/dev-safe.mjs +7 -8
- package/scripts/dev-static.mjs +3 -0
- package/scripts/dev-with-automation.mjs +3 -0
- package/scripts/docker-build.mjs +4 -0
- package/scripts/static-server.mjs +93 -7
- package/tools/canvas_ui_tool.py +14 -8
- package/build/assets/active-backend-context-hxq31W25.js +0 -1
- package/build/assets/agent-server-client-options-DVLRd9sw.js +0 -1
- package/build/assets/agent-server-conversation-service.api-CuSdr4Qb.js +0 -5
- package/build/assets/agent-settings-D_yOy8XB.js +0 -1
- package/build/assets/api-key-entry-screen-Dl0qVYi4.js +0 -1
- package/build/assets/app-settings-yVizGXox.js +0 -1
- package/build/assets/automation-detail-dvJfLs5u.js +0 -2
- package/build/assets/automation-export-BPcgLqPD.js +0 -2
- package/build/assets/automations-list-CUXogTe0.js +0 -1
- package/build/assets/backend-form-modal-CQJGmItq.js +0 -1
- package/build/assets/check-Bvi71siz.js +0 -1
- package/build/assets/condenser-settings-Ca8fYZ_Z.js +0 -1
- package/build/assets/conversation-9NBSRoR9.js +0 -1
- package/build/assets/conversation-BXg6Oti2.js +0 -89
- package/build/assets/conversation-panel-CZri9Rup.js +0 -1
- package/build/assets/conversation-service.api-DPBQvTKD.js +0 -1
- package/build/assets/declaration-gq8V5eTU.js +0 -1
- package/build/assets/files-tab-UVoray88.js +0 -1
- package/build/assets/git-provider-icon-o6hdnJUB.js +0 -1
- package/build/assets/handle-capture-consent-CPMXU29K.js +0 -1
- package/build/assets/home-D1IHvGTN.js +0 -1
- package/build/assets/index-redirect-CUUJiNki.js +0 -1
- package/build/assets/install-server-modal-BbuQaA2w.js +0 -1
- package/build/assets/lesson-plan-jC0HBoe6.js +0 -4
- package/build/assets/llm-not-configured-banner-DoARbcdL.js +0 -27
- package/build/assets/llm-settings-4JMLV8mq.js +0 -1
- package/build/assets/llm-settings-D91gMw3U.js +0 -1
- package/build/assets/llm-subscription-service-CKyaV24y.js +0 -1
- package/build/assets/loader-circle-BEykUKYG.js +0 -1
- package/build/assets/manage-backends-modal-DkWAMSle.js +0 -1
- package/build/assets/manifest-aa5c29f6.js +0 -1
- package/build/assets/model-selector-BfqpMkSJ.js +0 -1
- package/build/assets/mouse-pointer-click-PdEQPL6v.js +0 -1
- package/build/assets/onboarding-Bu-HN1ze.js +0 -1
- package/build/assets/onboarding-modal-CZgjs5Bx.js +0 -1
- package/build/assets/option-service.api-BrZ5q87N.js +0 -1
- package/build/assets/organization-service.api-Bk4pCGU1.js +0 -1
- package/build/assets/path-utils-CSmuZoix.js +0 -1
- package/build/assets/plugins-management-service-BRBLxvUl.js +0 -1
- package/build/assets/profiles-service.api-BMXQ9pZC.js +0 -1
- package/build/assets/providers-BpO967xS.js +0 -1
- package/build/assets/proxy-BgJLtxu7.js +0 -1
- package/build/assets/root-BM5WgQ4_.js +0 -2
- package/build/assets/root-V8fkplMy.css +0 -1
- package/build/assets/root-layout-BdoyoobY.js +0 -2
- package/build/assets/schema-field-BSHrUMme.js +0 -1
- package/build/assets/sdk-section-page-t82gsOqa.js +0 -1
- package/build/assets/search-4DHskuhE.js +0 -1
- package/build/assets/secrets-service-B2GqPV0N.js +0 -1
- package/build/assets/settings-DmPLkgq0.js +0 -1
- package/build/assets/settings-modal-CwrZKrTq.js +0 -1
- package/build/assets/settings-service.api-Ce-ub11I.js +0 -1
- package/build/assets/shared-conversation-BDREQPnE.js +0 -1
- package/build/assets/skills-plugins-2Y44YHbO.js +0 -1
- package/build/assets/use-acp-credential-form-MzZM6D7D.js +0 -1
- package/build/assets/use-agent-profiles-DwZxnwO5.js +0 -1
- package/build/assets/use-backends-health-CRHzuvxO.js +0 -1
- package/build/assets/use-cloud-current-user-id-utFreJ0i.js +0 -1
- package/build/assets/use-config-mJrtZHP1.js +0 -1
- package/build/assets/use-create-conversation-DdqsP78F.js +0 -1
- package/build/assets/use-is-authed-B6M0mcGL.js +0 -1
- package/build/assets/use-llm-profiles-RC-PkpBl.js +0 -1
- package/build/assets/use-plugins-marketplace-FHlbeQ4c.js +0 -1
- package/build/assets/use-runtime-is-ready-RKj2WmEh.js +0 -1
- package/build/assets/use-save-agent-profile-tvDP15mh.js +0 -1
- package/build/assets/use-save-settings-BGlSfuYn.js +0 -1
- package/build/assets/use-settings-CH5LzXD8.js +0 -1
- package/build/assets/use-settings-nav-items-Dwktv8wo.js +0 -16
- package/build/assets/use-skills-CSzSL6HG.js +0 -1
- package/build/assets/use-tracking-BIXzagSI.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~lf310vj7-CSVPGId3.js +0 -10
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~nfpll1wp-BCpa95De.js +0 -177
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~jewnulst-C57fm7C-.js +0 -1
- package/build/assets/vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CqXiHwjU.js +0 -2
- package/build/assets/x-Cb0WAtak.js +0 -1
- package/dist/components/providers/posthog-wrapper.cjs +0 -2
- package/dist/components/providers/posthog-wrapper.cjs.map +0 -1
- package/dist/components/providers/posthog-wrapper.d.ts +0 -4
- package/dist/components/providers/posthog-wrapper.js +0 -49
- package/dist/components/providers/posthog-wrapper.js.map +0 -1
- package/dist/node_modules/posthog-js/react/dist/esm/index.cjs +0 -2
- package/dist/node_modules/posthog-js/react/dist/esm/index.cjs.map +0 -1
- package/dist/node_modules/posthog-js/react/dist/esm/index.js +0 -113
- package/dist/node_modules/posthog-js/react/dist/esm/index.js.map +0 -1
- package/dist/utils/handle-capture-consent.cjs +0 -2
- package/dist/utils/handle-capture-consent.cjs.map +0 -1
- package/dist/utils/handle-capture-consent.d.ts +0 -7
- package/dist/utils/handle-capture-consent.js +0 -8
- package/dist/utils/handle-capture-consent.js.map +0 -1
- /package/build/assets/{__vite-browser-external-4xJsU2-u.js → __vite-browser-external-BQUj0sYu.js} +0 -0
- /package/build/assets/{agent-server-ui-style-scope-COnDHTm5.js → agent-server-ui-style-scope-qhnhZHBV.js} +0 -0
- /package/build/assets/{automation-BU8zu-FP.js → automation-LZB0MjdV.js} +0 -0
- /package/build/assets/{close-p3Op5lxI.js → close-DLFb5kfv.js} +0 -0
- /package/build/assets/{common-Dh7OqABE.js → common-CxbUL3nR.js} +0 -0
- /package/build/assets/{createLucideIcon-CVAsW2Yo.js → createLucideIcon-D4Tak8A1.js} +0 -0
- /package/build/assets/{folder-mMWFvaw0.js → folder-Bk311brm.js} +0 -0
- /package/build/assets/{get-language-from-path-CPNnuVhI.js → get-language-from-path-DBqBsCWH.js} +0 -0
- /package/build/assets/{git-status-mapper-BI8FyUVp.js → git-status-mapper-DnL9OC8_.js} +0 -0
- /package/build/assets/{iconBase-DaTRRUjy.js → iconBase-Dz51Zn5x.js} +0 -0
- /package/build/assets/{link-external-DfKQroKX.js → link-external-CaBmUEs_.js} +0 -0
- /package/build/assets/{search-BsjCEFNf.js → search-BgOCR7_c.js} +0 -0
- /package/build/assets/{settings-like-page-layout-classes-DENKlZpD.js → settings-like-page-layout-classes-Cdl6jOe5.js} +0 -0
- /package/build/assets/{skills-9cDZONKh.js → skills-EqzxYBvT.js} +0 -0
- /package/build/assets/{terminal-BuLtIrb9.js → terminal-Cgf___rK.js} +0 -0
- /package/build/assets/{u-check-circle-half-LiwZkuFe.js → u-check-circle-half-MsShT8Ec.js} +0 -0
- /package/build/assets/{u-edit-DJ90xc8Z.js → u-edit-DL5LgKon.js} +0 -0
- /package/build/assets/{use-breakpoint-B-O0lQ84.js → use-breakpoint-BP3lqLMx.js} +0 -0
- /package/build/assets/{use-click-outside-element-Bf4Omzot.js → use-click-outside-element-D9BYdANT.js} +0 -0
- /package/build/assets/{use-launch-skill-in-chat-BnoDgvAy.js → use-launch-skill-in-chat-DJWEfVc5.js} +0 -0
- /package/build/assets/{vendor~browser-Dqd33JyP.js → vendor~browser-By2MVv_N.js} +0 -0
- /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-DHDkknt5.js → vendor~conversation-panel~conversation~alert-banner-CxfzCmkN.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~epa72zsm-B4rXs7Zd.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~e0djk9ee-Cw6LUe8p.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~byh8a1g4-XNPdpuO8.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~jkpzbynd-CkpBIhVe.js} +0 -0
- /package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-9UMeuPV6.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-COhHANvV.js} +0 -0
- /package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DTzw2x50.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-FghQ3Z1a.js} +0 -0
- /package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~skills-settings~automations-~ki5qnp0d-rV6d1Iv_.js → vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~j2jlu22h-mC0v44WR.js} +0 -0
- /package/build/assets/{vendor~root-layout~home~mcp~automations-list~onboarding-modal-CXyYYvYh.js → vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-C4-GDgiF.js} +0 -0
- /package/build/assets/{vendor~terminal-aeP3PnKf.js → vendor~terminal-CnKZILnC.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-tab.cjs","names":[],"sources":["../../src/routes/files-tab.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { NoFileSelectedMessage } from \"#/components/features/files-tab/no-file-selected-message\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport { useWorkspaceFiles } from \"#/hooks/query/use-workspace-files\";\nimport { useWorkspaceFileContent } from \"#/hooks/query/use-workspace-file-content\";\nimport { useHasAttachedSource } from \"#/hooks/use-has-attached-source\";\nimport { useHasGitCommits } from \"#/hooks/query/use-has-git-commits\";\nimport { useAutoRefreshFilesOnEdit } from \"#/hooks/use-auto-refresh-files-on-edit\";\nimport { useUnifiedGetGitChanges } from \"#/hooks/query/use-unified-get-git-changes\";\nimport { useOptionalConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useWorkspaceMutationCounter,\n withWorkspaceCacheBuster,\n} from \"#/stores/use-workspace-mutation-counter\";\nimport { sortFilesByPriority } from \"#/utils/file-priority\";\nimport { FileQuickRow } from \"#/components/features/files-tab/file-quick-row\";\nimport { FileTreeView } from \"#/components/features/files-tab/file-tree-view\";\nimport { FileContentViewer } from \"#/components/features/files-tab/file-content-viewer\";\nimport { SegmentedToggle } from \"#/components/features/files-tab/segmented-toggle\";\nimport type { ViewMode } from \"#/components/features/files-tab/view-mode\";\nimport RefreshIcon from \"#/icons/u-refresh.svg?react\";\nimport LinkExternalIcon from \"#/icons/link-external.svg?react\";\nimport GitChanges from \"./changes-tab\";\n\nfunction FilesTab() {\n const { t } = useTranslation(\"openhands\");\n\n // Keep the list / content / diff caches fresh as the agent writes files.\n useAutoRefreshFilesOnEdit();\n\n const { hasAttachedSource, isLoading: isAttachedSourceLoading } =\n useHasAttachedSource();\n // A workspace with zero commits has no diff base to compare against, so\n // the diff view would just be empty / misleading. Only probe when we\n // already believe the user attached a source — saves a workspace round\n // trip on every plain (no-attachment) conversation.\n const { hasCommits } = useHasGitCommits({ enabled: hasAttachedSource });\n\n // Diff view defaults to ON when the user attached a source (repo or\n // local workspace) *and* there's at least one commit, OFF otherwise\n // (no attachment, or attachment with no commits yet).\n //\n // While the attachment / commit probes are still resolving we stay\n // optimistic — most attached conversations live in a real repo, so\n // defaulting to diff during the brief loading window avoids a\n // \"files → diff\" flash on initial load. We only flip to files-view\n // once `hasAttachedSource` *or* `hasCommits` definitively resolves\n // false. The user's persisted choice always wins.\n const { conversationId } = useOptionalConversationId();\n const {\n state: persistedState,\n setFilesTabDiffView,\n setFilesTabContentViewMode,\n } = useConversationLocalStorageState(conversationId ?? \"\");\n\n const diffViewDefault =\n (hasAttachedSource || isAttachedSourceLoading) && hasCommits !== false;\n const diffViewEnabled = persistedState.filesTabDiffView ?? diffViewDefault;\n const contentViewMode = persistedState.filesTabContentViewMode;\n\n // Collapsed by default — the quick-access pill row at the top is usually\n // enough; the user can expand the tree on demand.\n const [isTreeVisible, setIsTreeVisible] = useState(false);\n\n const filesQuery = useWorkspaceFiles();\n const paths = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);\n\n const storedSelectedPath = useFilesTabStore((s) => s.selectedPath);\n const selectedConversationId = useFilesTabStore(\n (s) => s.selectedConversationId,\n );\n const setSelectedPath = useFilesTabStore((s) => s.setSelectedPath);\n\n // A selection is scoped to the conversation it was made in. Ignore a path\n // that belongs to a different conversation so we never try to open a file\n // that only exists in the previous conversation's workspace (issue #1350).\n // The auto-select effect below then picks this conversation's top file.\n const selectedPath =\n selectedConversationId === conversationId ? storedSelectedPath : null;\n\n // Tag every selection with the active conversation so it can't leak into\n // the next one. FileQuickRow / FileTreeView call this with just the path.\n const handleSelectFile = useCallback(\n (path: string) => setSelectedPath(path, conversationId),\n [conversationId, setSelectedPath],\n );\n\n // Pre-fetch the selected file's content here too so the toolbar's\n // \"open in new window\" link can reach for its `staticUrl`. react-query\n // dedupes against `FileContentViewer`'s identical call, so this costs\n // nothing extra.\n const selectedFileContent = useWorkspaceFileContent(selectedPath);\n const mutationCounter = useWorkspaceMutationCounter((state) => state.count);\n const selectedFileStaticUrl = withWorkspaceCacheBuster(\n selectedFileContent.data?.staticUrl ?? null,\n mutationCounter,\n );\n\n useEffect(() => {\n if (selectedConversationId === conversationId) return;\n setSelectedPath(null, conversationId);\n }, [selectedConversationId, conversationId, setSelectedPath]);\n\n // Auto-select the highest-priority file the first time we load the list,\n // so users see something useful immediately.\n useEffect(() => {\n if (selectedPath || paths.length === 0) return;\n const [first] = sortFilesByPriority(paths);\n if (first) setSelectedPath(first, conversationId);\n }, [paths, selectedPath, conversationId, setSelectedPath]);\n\n // Refresh button: covers the diff view (git changes) and the file viewer\n // (workspace listing + cached file contents). Lives in this toolbar — not\n // in the outer ConversationTabs bar — so it sits with the other\n // files-tab-local controls.\n const queryClient = useQueryClient();\n const { refetch: refetchGitChanges, isFetching: isFetchingGitChanges } =\n useUnifiedGetGitChanges();\n const refreshFiles = () => {\n refetchGitChanges();\n queryClient.invalidateQueries({ queryKey: [\"workspace-files\"] });\n queryClient.invalidateQueries({ queryKey: [\"workspace-file-content\"] });\n };\n\n return (\n <main\n className=\"h-full w-full flex flex-col items-stretch\"\n data-testid=\"files-tab\"\n >\n {/* Top toolbar: diff/files + rich/plain toggles (left-aligned) plus\n the refresh button on the right. */}\n <div className=\"flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]\">\n <SegmentedToggle<\"on\" | \"off\">\n ariaLabel={t(I18nKey.FILES$DIFF_VIEW)}\n testId=\"files-tab-diff-toggle\"\n value={diffViewEnabled ? \"on\" : \"off\"}\n options={[\n { value: \"on\", label: t(I18nKey.FILES$DIFF_VIEW) },\n { value: \"off\", label: t(I18nKey.COMMON$FILES) },\n ]}\n onChange={(value) => setFilesTabDiffView(value === \"on\")}\n />\n\n {!diffViewEnabled && (\n <SegmentedToggle<ViewMode>\n ariaLabel={t(I18nKey.FILES$RICH)}\n testId=\"files-tab-content-mode-toggle\"\n value={contentViewMode}\n options={[\n { value: \"rich\", label: t(I18nKey.FILES$RICH) },\n { value: \"plain\", label: t(I18nKey.FILES$PLAIN) },\n ]}\n onChange={setFilesTabContentViewMode}\n />\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n {/* Open the currently-selected file in a new browser tab. Only\n meaningful while we're showing a file (not the diff view) and\n we've resolved its staticUrl from the workspace fileserver. */}\n {!diffViewEnabled && selectedFileStaticUrl && (\n <a\n href={selectedFileStaticUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n title={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n data-testid=\"files-tab-open-in-new-window\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white\"\n >\n <LinkExternalIcon width={14} height={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={refreshFiles}\n disabled={isFetchingGitChanges}\n aria-label={t(I18nKey.FILES$REFRESH)}\n title={t(I18nKey.FILES$REFRESH)}\n data-testid=\"files-tab-refresh\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <RefreshIcon\n width={12.75}\n height={15}\n color=\"#ffffff\"\n className={isFetchingGitChanges ? \"animate-spin\" : \"\"}\n />\n </button>\n </div>\n </div>\n\n {diffViewEnabled ? (\n <div className=\"flex-1 min-h-0\">\n <GitChanges />\n </div>\n ) : (\n <div className=\"flex flex-1 flex-col min-h-0\">\n {filesQuery.isLoading ? (\n <div className=\"flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]\">\n {t(I18nKey.FILES$LOADING_FILES)}\n </div>\n ) : (\n <>\n <FileQuickRow\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n isTreeVisible={isTreeVisible}\n onToggleTree={() => setIsTreeVisible((prev) => !prev)}\n />\n <div className=\"flex h-full min-h-0 flex-1\">\n {isTreeVisible && (\n <aside\n className=\"w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always\"\n data-testid=\"files-tab-tree\"\n >\n <FileTreeView\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n />\n </aside>\n )}\n <section\n className=\"flex h-full min-h-0 min-w-0 flex-1 flex-col\"\n data-testid=\"files-tab-content\"\n >\n {selectedPath ? (\n <FileContentViewer\n path={selectedPath}\n viewMode={contentViewMode}\n />\n ) : (\n <NoFileSelectedMessage />\n )}\n </section>\n </div>\n </>\n )}\n </div>\n )}\n </main>\n );\n}\n\nexport default FilesTab;\n"],"mappings":"uyCA6BA,SAAS,GAAW,CAClB,GAAM,CAAE,KAAM,EAAA,eAAe,YAAY,CAGzC,EAAA,2BAA2B,CAE3B,GAAM,CAAE,oBAAmB,UAAW,GACpC,EAAA,sBAAsB,CAKlB,CAAE,cAAe,EAAA,iBAAiB,CAAE,QAAS,EAAmB,CAAC,CAYjE,CAAE,kBAAmB,EAAA,2BAA2B,CAChD,CACJ,MAAO,EACP,sBACA,8BACE,EAAA,iCAAiC,GAAkB,GAAG,CAEpD,GACH,GAAqB,IAA4B,IAAe,GAC7D,EAAkB,EAAe,kBAAoB,EACrD,EAAkB,EAAe,wBAIjC,CAAC,EAAe,IAAA,EAAA,EAAA,UAA6B,GAAM,CAEnD,EAAa,EAAA,mBAAmB,CAChC,GAAA,EAAA,EAAA,aAAsB,EAAW,MAAQ,EAAE,CAAE,CAAC,EAAW,KAAK,CAAC,CAE/D,EAAqB,EAAA,iBAAkB,GAAM,EAAE,aAAa,CAC5D,EAAyB,EAAA,iBAC5B,GAAM,EAAE,uBACV,CACK,EAAkB,EAAA,iBAAkB,GAAM,EAAE,gBAAgB,CAM5D,EACJ,IAA2B,EAAiB,EAAqB,KAI7D,GAAA,EAAA,EAAA,aACH,GAAiB,EAAgB,EAAM,EAAe,CACvD,CAAC,EAAgB,EAAgB,CAClC,CAMK,EAAsB,EAAA,wBAAwB,EAAa,CAC3D,EAAkB,EAAA,4BAA6B,GAAU,EAAM,MAAM,CACrE,EAAwB,EAAA,yBAC5B,EAAoB,MAAM,WAAa,KACvC,EACD,EAED,EAAA,EAAA,eAAgB,CACV,IAA2B,GAC/B,EAAgB,KAAM,EAAe,EACpC,CAAC,EAAwB,EAAgB,EAAgB,CAAC,EAI7D,EAAA,EAAA,eAAgB,CACd,GAAI,GAAgB,EAAM,SAAW,EAAG,OACxC,GAAM,CAAC,GAAS,EAAA,oBAAoB,EAAM,CACtC,GAAO,EAAgB,EAAO,EAAe,EAChD,CAAC,EAAO,EAAc,EAAgB,EAAgB,CAAC,CAM1D,IAAM,EAAc,EAAA,gBAAgB,CAC9B,CAAE,QAAS,EAAmB,WAAY,GAC9C,EAAA,yBAAyB,CAO3B,OACE,EAAA,EAAA,MAAC,OAAD,CACE,UAAU,4CACV,cAAY,qBAFd,EAME,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,kFAAf,EACE,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,UAAW,EAAE,EAAA,QAAQ,gBAAgB,CACrC,OAAO,wBACP,MAAO,EAAkB,KAAO,MAChC,QAAS,CACP,CAAE,MAAO,KAAM,MAAO,EAAE,EAAA,QAAQ,gBAAgB,CAAE,CAClD,CAAE,MAAO,MAAO,MAAO,EAAE,EAAA,QAAQ,aAAa,CAAE,CACjD,CACD,SAAW,GAAU,EAAoB,IAAU,KAAK,CACxD,CAAA,CAED,CAAC,IACA,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,UAAW,EAAE,EAAA,QAAQ,WAAW,CAChC,OAAO,gCACP,MAAO,EACP,QAAS,CACP,CAAE,MAAO,OAAQ,MAAO,EAAE,EAAA,QAAQ,WAAW,CAAE,CAC/C,CAAE,MAAO,QAAS,MAAO,EAAE,EAAA,QAAQ,YAAY,CAAE,CAClD,CACD,SAAU,EACV,CAAA,EAGJ,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,2CAAf,CAIG,CAAC,GAAmB,IACnB,EAAA,EAAA,KAAC,IAAD,CACE,KAAM,EACN,OAAO,SACP,IAAI,sBACJ,aAAY,EAAE,EAAA,QAAQ,yBAAyB,CAC/C,MAAO,EAAE,EAAA,QAAQ,yBAAyB,CAC1C,cAAY,+BACZ,UAAU,0IAEV,EAAA,EAAA,KAAC,EAAA,QAAD,CAAkB,MAAO,GAAI,OAAQ,GAAM,CAAA,CACzC,CAAA,EAEN,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,YAzDiB,CACzB,GAAmB,CACnB,EAAY,kBAAkB,CAAE,SAAU,CAAC,kBAAkB,CAAE,CAAC,CAChE,EAAY,kBAAkB,CAAE,SAAU,CAAC,yBAAyB,CAAE,CAAC,EAuD/D,SAAU,EACV,aAAY,EAAE,EAAA,QAAQ,cAAc,CACpC,MAAO,EAAE,EAAA,QAAQ,cAAc,CAC/B,cAAY,oBACZ,UAAU,uLAEV,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,MAAO,MACP,OAAQ,GACR,MAAM,UACN,UAAW,EAAuB,eAAiB,GACnD,CAAA,CACK,CAAA,CACL,GACF,GAEL,GACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,2BACb,EAAA,EAAA,KAAC,EAAA,QAAD,EAAc,CAAA,CACV,CAAA,EAEN,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wCACZ,EAAW,WACV,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,kFACZ,EAAE,EAAA,QAAQ,oBAAoB,CAC3B,CAAA,EAEN,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAA,aAAD,CACS,QACO,eACd,aAAc,EACC,gBACf,iBAAoB,EAAkB,GAAS,CAAC,EAAK,CACrD,CAAA,EACF,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,sCAAf,CACG,IACC,EAAA,EAAA,KAAC,QAAD,CACE,UAAU,2FACV,cAAY,2BAEZ,EAAA,EAAA,KAAC,EAAA,aAAD,CACS,QACO,eACd,aAAc,EACd,CAAA,CACI,CAAA,EAEV,EAAA,EAAA,KAAC,UAAD,CACE,UAAU,8CACV,cAAY,6BAEX,GACC,EAAA,EAAA,KAAC,EAAA,kBAAD,CACE,KAAM,EACN,SAAU,EACV,CAAA,EAEF,EAAA,EAAA,KAAC,EAAA,sBAAD,EAAyB,CAAA,CAEnB,CAAA,CACN,GACL,CAAA,CAAA,CAED,CAAA,CAEH"}
|
|
1
|
+
{"version":3,"file":"files-tab.cjs","names":[],"sources":["../../src/routes/files-tab.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { NoFileSelectedMessage } from \"#/components/features/files-tab/no-file-selected-message\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport { useWorkspaceFiles } from \"#/hooks/query/use-workspace-files\";\nimport { useWorkspaceFileContent } from \"#/hooks/query/use-workspace-file-content\";\nimport { useHasAttachedSource } from \"#/hooks/use-has-attached-source\";\nimport { useHasGitCommits } from \"#/hooks/query/use-has-git-commits\";\nimport { useAutoRefreshFilesOnEdit } from \"#/hooks/use-auto-refresh-files-on-edit\";\nimport { useUnifiedGetGitChanges } from \"#/hooks/query/use-unified-get-git-changes\";\nimport { useOptionalConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useWorkspaceMutationCounter,\n withWorkspaceCacheBuster,\n} from \"#/stores/use-workspace-mutation-counter\";\nimport { sortFilesByPriority } from \"#/utils/file-priority\";\nimport { FileQuickRow } from \"#/components/features/files-tab/file-quick-row\";\nimport { FileTreeView } from \"#/components/features/files-tab/file-tree-view\";\nimport { FileContentViewer } from \"#/components/features/files-tab/file-content-viewer\";\nimport { SegmentedToggle } from \"#/components/features/files-tab/segmented-toggle\";\nimport type { ViewMode } from \"#/components/features/files-tab/view-mode\";\nimport RefreshIcon from \"#/icons/u-refresh.svg?react\";\nimport LinkExternalIcon from \"#/icons/link-external.svg?react\";\nimport { useUnifiedGitCommits } from \"#/hooks/query/use-unified-git-commits\";\nimport GitChanges from \"./changes-tab\";\nimport GitCommits from \"./commits-tab\";\n\nfunction FilesTab() {\n const { t } = useTranslation(\"openhands\");\n\n // Keep the list / content / diff caches fresh as the agent writes files.\n useAutoRefreshFilesOnEdit();\n\n const { hasAttachedSource, isLoading: isAttachedSourceLoading } =\n useHasAttachedSource();\n // A workspace with zero commits has no diff base to compare against, so\n // the diff view would just be empty / misleading. Only probe when we\n // already believe the user attached a source — saves a workspace round\n // trip on every plain (no-attachment) conversation.\n const { hasCommits } = useHasGitCommits({ enabled: hasAttachedSource });\n\n // Diff view defaults to ON when the user attached a source (repo or\n // local workspace) *and* there's at least one commit, OFF otherwise\n // (no attachment, or attachment with no commits yet).\n //\n // While the attachment / commit probes are still resolving we stay\n // optimistic — most attached conversations live in a real repo, so\n // defaulting to diff during the brief loading window avoids a\n // \"files → diff\" flash on initial load. We only flip to files-view\n // once `hasAttachedSource` *or* `hasCommits` definitively resolves\n // false. The user's persisted choice always wins.\n const { conversationId } = useOptionalConversationId();\n const {\n state: persistedState,\n setFilesTabDiffView,\n setFilesTabContentViewMode,\n } = useConversationLocalStorageState(conversationId ?? \"\");\n\n const diffViewDefault =\n (hasAttachedSource || isAttachedSourceLoading) && hasCommits !== false;\n const diffViewEnabled = persistedState.filesTabDiffView ?? diffViewDefault;\n const contentViewMode = persistedState.filesTabContentViewMode;\n\n // Commit history gets a third toggle segment, offered only when the\n // agent server supports the commits API (older servers 404 → the toggle\n // stays two-way and the tab looks exactly as it did before). The\n // selection is session-local; the persisted diff/files preference is\n // untouched so falling out of the commits view restores it.\n const { isSuccess: commitsIsSuccess, isUnsupported: commitsUnsupported } =\n useUnifiedGitCommits();\n const showCommitsOption = commitsIsSuccess && !commitsUnsupported;\n const [commitsViewSelected, setCommitsViewSelected] = useState(false);\n let activeView: \"on\" | \"off\" | \"commits\" = diffViewEnabled ? \"on\" : \"off\";\n if (commitsViewSelected && showCommitsOption) activeView = \"commits\";\n\n // Collapsed by default — the quick-access pill row at the top is usually\n // enough; the user can expand the tree on demand.\n const [isTreeVisible, setIsTreeVisible] = useState(false);\n\n const filesQuery = useWorkspaceFiles();\n const paths = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);\n\n const storedSelectedPath = useFilesTabStore((s) => s.selectedPath);\n const selectedConversationId = useFilesTabStore(\n (s) => s.selectedConversationId,\n );\n const setSelectedPath = useFilesTabStore((s) => s.setSelectedPath);\n\n // A selection is scoped to the conversation it was made in. Ignore a path\n // that belongs to a different conversation so we never try to open a file\n // that only exists in the previous conversation's workspace (issue #1350).\n // The auto-select effect below then picks this conversation's top file.\n const selectedPath =\n selectedConversationId === conversationId ? storedSelectedPath : null;\n\n // Tag every selection with the active conversation so it can't leak into\n // the next one. FileQuickRow / FileTreeView call this with just the path.\n const handleSelectFile = useCallback(\n (path: string) => setSelectedPath(path, conversationId),\n [conversationId, setSelectedPath],\n );\n\n // Pre-fetch the selected file's content here too so the toolbar's\n // \"open in new window\" link can reach for its `staticUrl`. react-query\n // dedupes against `FileContentViewer`'s identical call, so this costs\n // nothing extra.\n const selectedFileContent = useWorkspaceFileContent(selectedPath);\n const mutationCounter = useWorkspaceMutationCounter((state) => state.count);\n const selectedFileStaticUrl = withWorkspaceCacheBuster(\n selectedFileContent.data?.staticUrl ?? null,\n mutationCounter,\n );\n\n useEffect(() => {\n if (selectedConversationId === conversationId) return;\n setSelectedPath(null, conversationId);\n }, [selectedConversationId, conversationId, setSelectedPath]);\n\n // Auto-select the highest-priority file the first time we load the list,\n // so users see something useful immediately.\n useEffect(() => {\n if (selectedPath || paths.length === 0) return;\n const [first] = sortFilesByPriority(paths);\n if (first) setSelectedPath(first, conversationId);\n }, [paths, selectedPath, conversationId, setSelectedPath]);\n\n // Refresh button: covers the diff view (git changes) and the file viewer\n // (workspace listing + cached file contents). Lives in this toolbar — not\n // in the outer ConversationTabs bar — so it sits with the other\n // files-tab-local controls.\n const queryClient = useQueryClient();\n const { refetch: refetchGitChanges, isFetching: isFetchingGitChanges } =\n useUnifiedGetGitChanges();\n const refreshFiles = () => {\n refetchGitChanges();\n queryClient.invalidateQueries({ queryKey: [\"workspace-files\"] });\n queryClient.invalidateQueries({ queryKey: [\"workspace-file-content\"] });\n queryClient.invalidateQueries({ queryKey: [\"git_commits\"] });\n };\n\n return (\n <main\n className=\"h-full w-full flex flex-col items-stretch\"\n data-testid=\"files-tab\"\n >\n {/* Top toolbar: diff/files + rich/plain toggles (left-aligned) plus\n the refresh button on the right. */}\n <div className=\"flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]\">\n <SegmentedToggle<\"on\" | \"off\" | \"commits\">\n ariaLabel={t(I18nKey.FILES$DIFF_VIEW)}\n testId=\"files-tab-diff-toggle\"\n value={activeView}\n options={[\n { value: \"on\", label: t(I18nKey.FILES$DIFF_VIEW) },\n ...(showCommitsOption\n ? [\n {\n value: \"commits\" as const,\n label: t(I18nKey.DIFF_VIEWER$COMMITS),\n },\n ]\n : []),\n { value: \"off\", label: t(I18nKey.COMMON$FILES) },\n ]}\n onChange={(value) => {\n if (value === \"commits\") {\n setCommitsViewSelected(true);\n } else {\n setCommitsViewSelected(false);\n setFilesTabDiffView(value === \"on\");\n }\n }}\n />\n\n {activeView === \"off\" && (\n <SegmentedToggle<ViewMode>\n ariaLabel={t(I18nKey.FILES$RICH)}\n testId=\"files-tab-content-mode-toggle\"\n value={contentViewMode}\n options={[\n { value: \"rich\", label: t(I18nKey.FILES$RICH) },\n { value: \"plain\", label: t(I18nKey.FILES$PLAIN) },\n ]}\n onChange={setFilesTabContentViewMode}\n />\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n {/* Open the currently-selected file in a new browser tab. Only\n meaningful while we're showing a file (not the diff view) and\n we've resolved its staticUrl from the workspace fileserver. */}\n {activeView === \"off\" && selectedFileStaticUrl && (\n <a\n href={selectedFileStaticUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n title={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n data-testid=\"files-tab-open-in-new-window\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white\"\n >\n <LinkExternalIcon width={14} height={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={refreshFiles}\n disabled={isFetchingGitChanges}\n aria-label={t(I18nKey.FILES$REFRESH)}\n title={t(I18nKey.FILES$REFRESH)}\n data-testid=\"files-tab-refresh\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <RefreshIcon\n width={12.75}\n height={15}\n color=\"#ffffff\"\n className={isFetchingGitChanges ? \"animate-spin\" : \"\"}\n />\n </button>\n </div>\n </div>\n\n {activeView === \"on\" && (\n <div className=\"flex-1 min-h-0\">\n <GitChanges />\n </div>\n )}\n {activeView === \"commits\" && (\n <div className=\"flex-1 min-h-0\">\n <GitCommits />\n </div>\n )}\n {activeView === \"off\" && (\n <div className=\"flex flex-1 flex-col min-h-0\">\n {filesQuery.isLoading ? (\n <div className=\"flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]\">\n {t(I18nKey.FILES$LOADING_FILES)}\n </div>\n ) : (\n <>\n <FileQuickRow\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n isTreeVisible={isTreeVisible}\n onToggleTree={() => setIsTreeVisible((prev) => !prev)}\n />\n <div className=\"flex h-full min-h-0 flex-1\">\n {isTreeVisible && (\n <aside\n className=\"w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always\"\n data-testid=\"files-tab-tree\"\n >\n <FileTreeView\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n />\n </aside>\n )}\n <section\n className=\"flex h-full min-h-0 min-w-0 flex-1 flex-col\"\n data-testid=\"files-tab-content\"\n >\n {selectedPath ? (\n <FileContentViewer\n path={selectedPath}\n viewMode={contentViewMode}\n />\n ) : (\n <NoFileSelectedMessage />\n )}\n </section>\n </div>\n </>\n )}\n </div>\n )}\n </main>\n );\n}\n\nexport default FilesTab;\n"],"mappings":"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"}
|
package/dist/routes/files-tab.js
CHANGED
|
@@ -9,143 +9,164 @@ import { SegmentedToggle as s } from "../components/features/files-tab/segmented
|
|
|
9
9
|
import { NoFileSelectedMessage as c } from "../components/features/files-tab/no-file-selected-message.js";
|
|
10
10
|
import { useUnifiedGetGitChanges as l } from "../hooks/query/use-unified-get-git-changes.js";
|
|
11
11
|
import { useWorkspaceFiles as u } from "../hooks/query/use-workspace-files.js";
|
|
12
|
-
import { useWorkspaceMutationCounter as
|
|
13
|
-
import { useWorkspaceFileContent as
|
|
14
|
-
import { useHasAttachedSource as
|
|
15
|
-
import { useHasGitCommits as
|
|
16
|
-
import { useAutoRefreshFilesOnEdit as
|
|
17
|
-
import { sortFilesByPriority as
|
|
18
|
-
import { FileQuickRow as
|
|
19
|
-
import { FileTreeView as
|
|
20
|
-
import { FileContentViewer as
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
12
|
+
import { useWorkspaceMutationCounter as ee, withWorkspaceCacheBuster as te } from "../stores/use-workspace-mutation-counter.js";
|
|
13
|
+
import { useWorkspaceFileContent as ne } from "../hooks/query/use-workspace-file-content.js";
|
|
14
|
+
import { useHasAttachedSource as re } from "../hooks/use-has-attached-source.js";
|
|
15
|
+
import { useHasGitCommits as d } from "../hooks/query/use-has-git-commits.js";
|
|
16
|
+
import { useAutoRefreshFilesOnEdit as f } from "../hooks/use-auto-refresh-files-on-edit.js";
|
|
17
|
+
import { sortFilesByPriority as ie } from "../utils/file-priority.js";
|
|
18
|
+
import { FileQuickRow as p } from "../components/features/files-tab/file-quick-row.js";
|
|
19
|
+
import { FileTreeView as m } from "../components/features/files-tab/file-tree-view.js";
|
|
20
|
+
import { FileContentViewer as h } from "../components/features/files-tab/file-content-viewer.js";
|
|
21
|
+
import g from "../icons/u-refresh.js";
|
|
22
|
+
import { useUnifiedGitCommits as _ } from "../hooks/query/use-unified-git-commits.js";
|
|
23
|
+
import v from "./changes-tab.js";
|
|
24
|
+
import y from "./commits-tab.js";
|
|
25
|
+
import { useCallback as b, useEffect as x, useMemo as ae, useState as S } from "react";
|
|
26
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
25
27
|
//#region src/routes/files-tab.tsx
|
|
26
|
-
function
|
|
27
|
-
let { t:
|
|
28
|
-
|
|
29
|
-
let { hasAttachedSource:
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
function E() {
|
|
29
|
+
let { t: E } = e("openhands");
|
|
30
|
+
f();
|
|
31
|
+
let { hasAttachedSource: D, isLoading: O } = re(), { hasCommits: k } = d({ enabled: D }), { conversationId: A } = n(), { state: j, setFilesTabDiffView: M, setFilesTabContentViewMode: N } = r(A ?? ""), P = (D || O) && k !== !1, F = j.filesTabDiffView ?? P, I = j.filesTabContentViewMode, { isSuccess: oe, isUnsupported: L } = _(), R = oe && !L, [z, B] = S(!1), V = F ? "on" : "off";
|
|
32
|
+
z && R && (V = "commits");
|
|
33
|
+
let [H, U] = S(!1), W = u(), G = ae(() => W.data ?? [], [W.data]), K = a((e) => e.selectedPath), q = a((e) => e.selectedConversationId), J = a((e) => e.setSelectedPath), Y = q === A ? K : null, X = b((e) => J(e, A), [A, J]), se = ne(Y), ce = ee((e) => e.count), Z = te(se.data?.staticUrl ?? null, ce);
|
|
34
|
+
x(() => {
|
|
35
|
+
q !== A && J(null, A);
|
|
32
36
|
}, [
|
|
33
|
-
G,
|
|
34
|
-
N,
|
|
35
|
-
K
|
|
36
|
-
]), C(() => {
|
|
37
|
-
if (q || U.length === 0) return;
|
|
38
|
-
let [e] = _(U);
|
|
39
|
-
e && K(e, N);
|
|
40
|
-
}, [
|
|
41
|
-
U,
|
|
42
37
|
q,
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
A,
|
|
39
|
+
J
|
|
40
|
+
]), x(() => {
|
|
41
|
+
if (Y || G.length === 0) return;
|
|
42
|
+
let [e] = ie(G);
|
|
43
|
+
e && J(e, A);
|
|
44
|
+
}, [
|
|
45
|
+
G,
|
|
46
|
+
Y,
|
|
47
|
+
A,
|
|
48
|
+
J
|
|
45
49
|
]);
|
|
46
|
-
let Q = i(), { refetch:
|
|
47
|
-
|
|
50
|
+
let Q = i(), { refetch: le, isFetching: $ } = l(), ue = () => {
|
|
51
|
+
le(), Q.invalidateQueries({ queryKey: ["workspace-files"] }), Q.invalidateQueries({ queryKey: ["workspace-file-content"] }), Q.invalidateQueries({ queryKey: ["git_commits"] });
|
|
52
|
+
};
|
|
53
|
+
return /* @__PURE__ */ T("main", {
|
|
48
54
|
className: "h-full w-full flex flex-col items-stretch",
|
|
49
55
|
"data-testid": "files-tab",
|
|
50
|
-
children: [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ T("div", {
|
|
58
|
+
className: "flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]",
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ w(s, {
|
|
61
|
+
ariaLabel: E(t.FILES$DIFF_VIEW),
|
|
62
|
+
testId: "files-tab-diff-toggle",
|
|
63
|
+
value: V,
|
|
64
|
+
options: [
|
|
65
|
+
{
|
|
66
|
+
value: "on",
|
|
67
|
+
label: E(t.FILES$DIFF_VIEW)
|
|
68
|
+
},
|
|
69
|
+
...R ? [{
|
|
70
|
+
value: "commits",
|
|
71
|
+
label: E(t.DIFF_VIEWER$COMMITS)
|
|
72
|
+
}] : [],
|
|
73
|
+
{
|
|
74
|
+
value: "off",
|
|
75
|
+
label: E(t.COMMON$FILES)
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
onChange: (e) => {
|
|
79
|
+
e === "commits" ? B(!0) : (B(!1), M(e === "on"));
|
|
80
|
+
}
|
|
81
|
+
}),
|
|
82
|
+
V === "off" && /* @__PURE__ */ w(s, {
|
|
83
|
+
ariaLabel: E(t.FILES$RICH),
|
|
84
|
+
testId: "files-tab-content-mode-toggle",
|
|
85
|
+
value: I,
|
|
86
|
+
options: [{
|
|
87
|
+
value: "rich",
|
|
88
|
+
label: E(t.FILES$RICH)
|
|
89
|
+
}, {
|
|
90
|
+
value: "plain",
|
|
91
|
+
label: E(t.FILES$PLAIN)
|
|
92
|
+
}],
|
|
93
|
+
onChange: N
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ T("div", {
|
|
96
|
+
className: "ml-auto flex items-center gap-1",
|
|
97
|
+
children: [V === "off" && Z && /* @__PURE__ */ w("a", {
|
|
98
|
+
href: Z,
|
|
99
|
+
target: "_blank",
|
|
100
|
+
rel: "noopener noreferrer",
|
|
101
|
+
"aria-label": E(t.FILES$OPEN_IN_NEW_WINDOW),
|
|
102
|
+
title: E(t.FILES$OPEN_IN_NEW_WINDOW),
|
|
103
|
+
"data-testid": "files-tab-open-in-new-window",
|
|
104
|
+
className: "flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white",
|
|
105
|
+
children: /* @__PURE__ */ w(o, {
|
|
106
|
+
width: 14,
|
|
107
|
+
height: 14
|
|
108
|
+
})
|
|
109
|
+
}), /* @__PURE__ */ w("button", {
|
|
110
|
+
type: "button",
|
|
111
|
+
onClick: ue,
|
|
112
|
+
disabled: $,
|
|
113
|
+
"aria-label": E(t.FILES$REFRESH),
|
|
114
|
+
title: E(t.FILES$REFRESH),
|
|
115
|
+
"data-testid": "files-tab-refresh",
|
|
116
|
+
className: "flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
|
|
117
|
+
children: /* @__PURE__ */ w(g, {
|
|
118
|
+
width: 12.75,
|
|
119
|
+
height: 15,
|
|
120
|
+
color: "#ffffff",
|
|
121
|
+
className: $ ? "animate-spin" : ""
|
|
122
|
+
})
|
|
123
|
+
})]
|
|
124
|
+
})
|
|
125
|
+
]
|
|
126
|
+
}),
|
|
127
|
+
V === "on" && /* @__PURE__ */ w("div", {
|
|
128
|
+
className: "flex-1 min-h-0",
|
|
129
|
+
children: /* @__PURE__ */ w(v, {})
|
|
130
|
+
}),
|
|
131
|
+
V === "commits" && /* @__PURE__ */ w("div", {
|
|
132
|
+
className: "flex-1 min-h-0",
|
|
133
|
+
children: /* @__PURE__ */ w(y, {})
|
|
134
|
+
}),
|
|
135
|
+
V === "off" && /* @__PURE__ */ w("div", {
|
|
136
|
+
className: "flex flex-1 flex-col min-h-0",
|
|
137
|
+
children: W.isLoading ? /* @__PURE__ */ w("div", {
|
|
138
|
+
className: "flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]",
|
|
139
|
+
children: E(t.FILES$LOADING_FILES)
|
|
140
|
+
}) : /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(p, {
|
|
141
|
+
paths: G,
|
|
142
|
+
selectedPath: Y,
|
|
143
|
+
onSelectFile: X,
|
|
144
|
+
isTreeVisible: H,
|
|
145
|
+
onToggleTree: () => U((e) => !e)
|
|
146
|
+
}), /* @__PURE__ */ T("div", {
|
|
147
|
+
className: "flex h-full min-h-0 flex-1",
|
|
148
|
+
children: [H && /* @__PURE__ */ w("aside", {
|
|
149
|
+
className: "w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always",
|
|
150
|
+
"data-testid": "files-tab-tree",
|
|
151
|
+
children: /* @__PURE__ */ w(m, {
|
|
152
|
+
paths: G,
|
|
153
|
+
selectedPath: Y,
|
|
154
|
+
onSelectFile: X
|
|
108
155
|
})
|
|
156
|
+
}), /* @__PURE__ */ w("section", {
|
|
157
|
+
className: "flex h-full min-h-0 min-w-0 flex-1 flex-col",
|
|
158
|
+
"data-testid": "files-tab-content",
|
|
159
|
+
children: Y ? /* @__PURE__ */ w(h, {
|
|
160
|
+
path: Y,
|
|
161
|
+
viewMode: I
|
|
162
|
+
}) : /* @__PURE__ */ w(c, {})
|
|
109
163
|
})]
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
className: "flex-1 min-h-0",
|
|
114
|
-
children: /* @__PURE__ */ D(S, {})
|
|
115
|
-
}) : /* @__PURE__ */ D("div", {
|
|
116
|
-
className: "flex flex-1 flex-col min-h-0",
|
|
117
|
-
children: H.isLoading ? /* @__PURE__ */ D("div", {
|
|
118
|
-
className: "flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]",
|
|
119
|
-
children: k(t.FILES$LOADING_FILES)
|
|
120
|
-
}) : /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D(v, {
|
|
121
|
-
paths: U,
|
|
122
|
-
selectedPath: q,
|
|
123
|
-
onSelectFile: J,
|
|
124
|
-
isTreeVisible: B,
|
|
125
|
-
onToggleTree: () => V((e) => !e)
|
|
126
|
-
}), /* @__PURE__ */ O("div", {
|
|
127
|
-
className: "flex h-full min-h-0 flex-1",
|
|
128
|
-
children: [B && /* @__PURE__ */ D("aside", {
|
|
129
|
-
className: "w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always",
|
|
130
|
-
"data-testid": "files-tab-tree",
|
|
131
|
-
children: /* @__PURE__ */ D(y, {
|
|
132
|
-
paths: U,
|
|
133
|
-
selectedPath: q,
|
|
134
|
-
onSelectFile: J
|
|
135
|
-
})
|
|
136
|
-
}), /* @__PURE__ */ D("section", {
|
|
137
|
-
className: "flex h-full min-h-0 min-w-0 flex-1 flex-col",
|
|
138
|
-
"data-testid": "files-tab-content",
|
|
139
|
-
children: q ? /* @__PURE__ */ D(b, {
|
|
140
|
-
path: q,
|
|
141
|
-
viewMode: z
|
|
142
|
-
}) : /* @__PURE__ */ D(c, {})
|
|
143
|
-
})]
|
|
144
|
-
})] })
|
|
145
|
-
})]
|
|
164
|
+
})] })
|
|
165
|
+
})
|
|
166
|
+
]
|
|
146
167
|
});
|
|
147
168
|
}
|
|
148
169
|
//#endregion
|
|
149
|
-
export {
|
|
170
|
+
export { E as default };
|
|
150
171
|
|
|
151
172
|
//# sourceMappingURL=files-tab.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-tab.js","names":[],"sources":["../../src/routes/files-tab.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { NoFileSelectedMessage } from \"#/components/features/files-tab/no-file-selected-message\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport { useWorkspaceFiles } from \"#/hooks/query/use-workspace-files\";\nimport { useWorkspaceFileContent } from \"#/hooks/query/use-workspace-file-content\";\nimport { useHasAttachedSource } from \"#/hooks/use-has-attached-source\";\nimport { useHasGitCommits } from \"#/hooks/query/use-has-git-commits\";\nimport { useAutoRefreshFilesOnEdit } from \"#/hooks/use-auto-refresh-files-on-edit\";\nimport { useUnifiedGetGitChanges } from \"#/hooks/query/use-unified-get-git-changes\";\nimport { useOptionalConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useWorkspaceMutationCounter,\n withWorkspaceCacheBuster,\n} from \"#/stores/use-workspace-mutation-counter\";\nimport { sortFilesByPriority } from \"#/utils/file-priority\";\nimport { FileQuickRow } from \"#/components/features/files-tab/file-quick-row\";\nimport { FileTreeView } from \"#/components/features/files-tab/file-tree-view\";\nimport { FileContentViewer } from \"#/components/features/files-tab/file-content-viewer\";\nimport { SegmentedToggle } from \"#/components/features/files-tab/segmented-toggle\";\nimport type { ViewMode } from \"#/components/features/files-tab/view-mode\";\nimport RefreshIcon from \"#/icons/u-refresh.svg?react\";\nimport LinkExternalIcon from \"#/icons/link-external.svg?react\";\nimport GitChanges from \"./changes-tab\";\n\nfunction FilesTab() {\n const { t } = useTranslation(\"openhands\");\n\n // Keep the list / content / diff caches fresh as the agent writes files.\n useAutoRefreshFilesOnEdit();\n\n const { hasAttachedSource, isLoading: isAttachedSourceLoading } =\n useHasAttachedSource();\n // A workspace with zero commits has no diff base to compare against, so\n // the diff view would just be empty / misleading. Only probe when we\n // already believe the user attached a source — saves a workspace round\n // trip on every plain (no-attachment) conversation.\n const { hasCommits } = useHasGitCommits({ enabled: hasAttachedSource });\n\n // Diff view defaults to ON when the user attached a source (repo or\n // local workspace) *and* there's at least one commit, OFF otherwise\n // (no attachment, or attachment with no commits yet).\n //\n // While the attachment / commit probes are still resolving we stay\n // optimistic — most attached conversations live in a real repo, so\n // defaulting to diff during the brief loading window avoids a\n // \"files → diff\" flash on initial load. We only flip to files-view\n // once `hasAttachedSource` *or* `hasCommits` definitively resolves\n // false. The user's persisted choice always wins.\n const { conversationId } = useOptionalConversationId();\n const {\n state: persistedState,\n setFilesTabDiffView,\n setFilesTabContentViewMode,\n } = useConversationLocalStorageState(conversationId ?? \"\");\n\n const diffViewDefault =\n (hasAttachedSource || isAttachedSourceLoading) && hasCommits !== false;\n const diffViewEnabled = persistedState.filesTabDiffView ?? diffViewDefault;\n const contentViewMode = persistedState.filesTabContentViewMode;\n\n // Collapsed by default — the quick-access pill row at the top is usually\n // enough; the user can expand the tree on demand.\n const [isTreeVisible, setIsTreeVisible] = useState(false);\n\n const filesQuery = useWorkspaceFiles();\n const paths = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);\n\n const storedSelectedPath = useFilesTabStore((s) => s.selectedPath);\n const selectedConversationId = useFilesTabStore(\n (s) => s.selectedConversationId,\n );\n const setSelectedPath = useFilesTabStore((s) => s.setSelectedPath);\n\n // A selection is scoped to the conversation it was made in. Ignore a path\n // that belongs to a different conversation so we never try to open a file\n // that only exists in the previous conversation's workspace (issue #1350).\n // The auto-select effect below then picks this conversation's top file.\n const selectedPath =\n selectedConversationId === conversationId ? storedSelectedPath : null;\n\n // Tag every selection with the active conversation so it can't leak into\n // the next one. FileQuickRow / FileTreeView call this with just the path.\n const handleSelectFile = useCallback(\n (path: string) => setSelectedPath(path, conversationId),\n [conversationId, setSelectedPath],\n );\n\n // Pre-fetch the selected file's content here too so the toolbar's\n // \"open in new window\" link can reach for its `staticUrl`. react-query\n // dedupes against `FileContentViewer`'s identical call, so this costs\n // nothing extra.\n const selectedFileContent = useWorkspaceFileContent(selectedPath);\n const mutationCounter = useWorkspaceMutationCounter((state) => state.count);\n const selectedFileStaticUrl = withWorkspaceCacheBuster(\n selectedFileContent.data?.staticUrl ?? null,\n mutationCounter,\n );\n\n useEffect(() => {\n if (selectedConversationId === conversationId) return;\n setSelectedPath(null, conversationId);\n }, [selectedConversationId, conversationId, setSelectedPath]);\n\n // Auto-select the highest-priority file the first time we load the list,\n // so users see something useful immediately.\n useEffect(() => {\n if (selectedPath || paths.length === 0) return;\n const [first] = sortFilesByPriority(paths);\n if (first) setSelectedPath(first, conversationId);\n }, [paths, selectedPath, conversationId, setSelectedPath]);\n\n // Refresh button: covers the diff view (git changes) and the file viewer\n // (workspace listing + cached file contents). Lives in this toolbar — not\n // in the outer ConversationTabs bar — so it sits with the other\n // files-tab-local controls.\n const queryClient = useQueryClient();\n const { refetch: refetchGitChanges, isFetching: isFetchingGitChanges } =\n useUnifiedGetGitChanges();\n const refreshFiles = () => {\n refetchGitChanges();\n queryClient.invalidateQueries({ queryKey: [\"workspace-files\"] });\n queryClient.invalidateQueries({ queryKey: [\"workspace-file-content\"] });\n };\n\n return (\n <main\n className=\"h-full w-full flex flex-col items-stretch\"\n data-testid=\"files-tab\"\n >\n {/* Top toolbar: diff/files + rich/plain toggles (left-aligned) plus\n the refresh button on the right. */}\n <div className=\"flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]\">\n <SegmentedToggle<\"on\" | \"off\">\n ariaLabel={t(I18nKey.FILES$DIFF_VIEW)}\n testId=\"files-tab-diff-toggle\"\n value={diffViewEnabled ? \"on\" : \"off\"}\n options={[\n { value: \"on\", label: t(I18nKey.FILES$DIFF_VIEW) },\n { value: \"off\", label: t(I18nKey.COMMON$FILES) },\n ]}\n onChange={(value) => setFilesTabDiffView(value === \"on\")}\n />\n\n {!diffViewEnabled && (\n <SegmentedToggle<ViewMode>\n ariaLabel={t(I18nKey.FILES$RICH)}\n testId=\"files-tab-content-mode-toggle\"\n value={contentViewMode}\n options={[\n { value: \"rich\", label: t(I18nKey.FILES$RICH) },\n { value: \"plain\", label: t(I18nKey.FILES$PLAIN) },\n ]}\n onChange={setFilesTabContentViewMode}\n />\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n {/* Open the currently-selected file in a new browser tab. Only\n meaningful while we're showing a file (not the diff view) and\n we've resolved its staticUrl from the workspace fileserver. */}\n {!diffViewEnabled && selectedFileStaticUrl && (\n <a\n href={selectedFileStaticUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n title={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n data-testid=\"files-tab-open-in-new-window\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white\"\n >\n <LinkExternalIcon width={14} height={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={refreshFiles}\n disabled={isFetchingGitChanges}\n aria-label={t(I18nKey.FILES$REFRESH)}\n title={t(I18nKey.FILES$REFRESH)}\n data-testid=\"files-tab-refresh\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <RefreshIcon\n width={12.75}\n height={15}\n color=\"#ffffff\"\n className={isFetchingGitChanges ? \"animate-spin\" : \"\"}\n />\n </button>\n </div>\n </div>\n\n {diffViewEnabled ? (\n <div className=\"flex-1 min-h-0\">\n <GitChanges />\n </div>\n ) : (\n <div className=\"flex flex-1 flex-col min-h-0\">\n {filesQuery.isLoading ? (\n <div className=\"flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]\">\n {t(I18nKey.FILES$LOADING_FILES)}\n </div>\n ) : (\n <>\n <FileQuickRow\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n isTreeVisible={isTreeVisible}\n onToggleTree={() => setIsTreeVisible((prev) => !prev)}\n />\n <div className=\"flex h-full min-h-0 flex-1\">\n {isTreeVisible && (\n <aside\n className=\"w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always\"\n data-testid=\"files-tab-tree\"\n >\n <FileTreeView\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n />\n </aside>\n )}\n <section\n className=\"flex h-full min-h-0 min-w-0 flex-1 flex-col\"\n data-testid=\"files-tab-content\"\n >\n {selectedPath ? (\n <FileContentViewer\n path={selectedPath}\n viewMode={contentViewMode}\n />\n ) : (\n <NoFileSelectedMessage />\n )}\n </section>\n </div>\n </>\n )}\n </div>\n )}\n </main>\n );\n}\n\nexport default FilesTab;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"files-tab.js","names":[],"sources":["../../src/routes/files-tab.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { NoFileSelectedMessage } from \"#/components/features/files-tab/no-file-selected-message\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport { useWorkspaceFiles } from \"#/hooks/query/use-workspace-files\";\nimport { useWorkspaceFileContent } from \"#/hooks/query/use-workspace-file-content\";\nimport { useHasAttachedSource } from \"#/hooks/use-has-attached-source\";\nimport { useHasGitCommits } from \"#/hooks/query/use-has-git-commits\";\nimport { useAutoRefreshFilesOnEdit } from \"#/hooks/use-auto-refresh-files-on-edit\";\nimport { useUnifiedGetGitChanges } from \"#/hooks/query/use-unified-get-git-changes\";\nimport { useOptionalConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useWorkspaceMutationCounter,\n withWorkspaceCacheBuster,\n} from \"#/stores/use-workspace-mutation-counter\";\nimport { sortFilesByPriority } from \"#/utils/file-priority\";\nimport { FileQuickRow } from \"#/components/features/files-tab/file-quick-row\";\nimport { FileTreeView } from \"#/components/features/files-tab/file-tree-view\";\nimport { FileContentViewer } from \"#/components/features/files-tab/file-content-viewer\";\nimport { SegmentedToggle } from \"#/components/features/files-tab/segmented-toggle\";\nimport type { ViewMode } from \"#/components/features/files-tab/view-mode\";\nimport RefreshIcon from \"#/icons/u-refresh.svg?react\";\nimport LinkExternalIcon from \"#/icons/link-external.svg?react\";\nimport { useUnifiedGitCommits } from \"#/hooks/query/use-unified-git-commits\";\nimport GitChanges from \"./changes-tab\";\nimport GitCommits from \"./commits-tab\";\n\nfunction FilesTab() {\n const { t } = useTranslation(\"openhands\");\n\n // Keep the list / content / diff caches fresh as the agent writes files.\n useAutoRefreshFilesOnEdit();\n\n const { hasAttachedSource, isLoading: isAttachedSourceLoading } =\n useHasAttachedSource();\n // A workspace with zero commits has no diff base to compare against, so\n // the diff view would just be empty / misleading. Only probe when we\n // already believe the user attached a source — saves a workspace round\n // trip on every plain (no-attachment) conversation.\n const { hasCommits } = useHasGitCommits({ enabled: hasAttachedSource });\n\n // Diff view defaults to ON when the user attached a source (repo or\n // local workspace) *and* there's at least one commit, OFF otherwise\n // (no attachment, or attachment with no commits yet).\n //\n // While the attachment / commit probes are still resolving we stay\n // optimistic — most attached conversations live in a real repo, so\n // defaulting to diff during the brief loading window avoids a\n // \"files → diff\" flash on initial load. We only flip to files-view\n // once `hasAttachedSource` *or* `hasCommits` definitively resolves\n // false. The user's persisted choice always wins.\n const { conversationId } = useOptionalConversationId();\n const {\n state: persistedState,\n setFilesTabDiffView,\n setFilesTabContentViewMode,\n } = useConversationLocalStorageState(conversationId ?? \"\");\n\n const diffViewDefault =\n (hasAttachedSource || isAttachedSourceLoading) && hasCommits !== false;\n const diffViewEnabled = persistedState.filesTabDiffView ?? diffViewDefault;\n const contentViewMode = persistedState.filesTabContentViewMode;\n\n // Commit history gets a third toggle segment, offered only when the\n // agent server supports the commits API (older servers 404 → the toggle\n // stays two-way and the tab looks exactly as it did before). The\n // selection is session-local; the persisted diff/files preference is\n // untouched so falling out of the commits view restores it.\n const { isSuccess: commitsIsSuccess, isUnsupported: commitsUnsupported } =\n useUnifiedGitCommits();\n const showCommitsOption = commitsIsSuccess && !commitsUnsupported;\n const [commitsViewSelected, setCommitsViewSelected] = useState(false);\n let activeView: \"on\" | \"off\" | \"commits\" = diffViewEnabled ? \"on\" : \"off\";\n if (commitsViewSelected && showCommitsOption) activeView = \"commits\";\n\n // Collapsed by default — the quick-access pill row at the top is usually\n // enough; the user can expand the tree on demand.\n const [isTreeVisible, setIsTreeVisible] = useState(false);\n\n const filesQuery = useWorkspaceFiles();\n const paths = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);\n\n const storedSelectedPath = useFilesTabStore((s) => s.selectedPath);\n const selectedConversationId = useFilesTabStore(\n (s) => s.selectedConversationId,\n );\n const setSelectedPath = useFilesTabStore((s) => s.setSelectedPath);\n\n // A selection is scoped to the conversation it was made in. Ignore a path\n // that belongs to a different conversation so we never try to open a file\n // that only exists in the previous conversation's workspace (issue #1350).\n // The auto-select effect below then picks this conversation's top file.\n const selectedPath =\n selectedConversationId === conversationId ? storedSelectedPath : null;\n\n // Tag every selection with the active conversation so it can't leak into\n // the next one. FileQuickRow / FileTreeView call this with just the path.\n const handleSelectFile = useCallback(\n (path: string) => setSelectedPath(path, conversationId),\n [conversationId, setSelectedPath],\n );\n\n // Pre-fetch the selected file's content here too so the toolbar's\n // \"open in new window\" link can reach for its `staticUrl`. react-query\n // dedupes against `FileContentViewer`'s identical call, so this costs\n // nothing extra.\n const selectedFileContent = useWorkspaceFileContent(selectedPath);\n const mutationCounter = useWorkspaceMutationCounter((state) => state.count);\n const selectedFileStaticUrl = withWorkspaceCacheBuster(\n selectedFileContent.data?.staticUrl ?? null,\n mutationCounter,\n );\n\n useEffect(() => {\n if (selectedConversationId === conversationId) return;\n setSelectedPath(null, conversationId);\n }, [selectedConversationId, conversationId, setSelectedPath]);\n\n // Auto-select the highest-priority file the first time we load the list,\n // so users see something useful immediately.\n useEffect(() => {\n if (selectedPath || paths.length === 0) return;\n const [first] = sortFilesByPriority(paths);\n if (first) setSelectedPath(first, conversationId);\n }, [paths, selectedPath, conversationId, setSelectedPath]);\n\n // Refresh button: covers the diff view (git changes) and the file viewer\n // (workspace listing + cached file contents). Lives in this toolbar — not\n // in the outer ConversationTabs bar — so it sits with the other\n // files-tab-local controls.\n const queryClient = useQueryClient();\n const { refetch: refetchGitChanges, isFetching: isFetchingGitChanges } =\n useUnifiedGetGitChanges();\n const refreshFiles = () => {\n refetchGitChanges();\n queryClient.invalidateQueries({ queryKey: [\"workspace-files\"] });\n queryClient.invalidateQueries({ queryKey: [\"workspace-file-content\"] });\n queryClient.invalidateQueries({ queryKey: [\"git_commits\"] });\n };\n\n return (\n <main\n className=\"h-full w-full flex flex-col items-stretch\"\n data-testid=\"files-tab\"\n >\n {/* Top toolbar: diff/files + rich/plain toggles (left-aligned) plus\n the refresh button on the right. */}\n <div className=\"flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]\">\n <SegmentedToggle<\"on\" | \"off\" | \"commits\">\n ariaLabel={t(I18nKey.FILES$DIFF_VIEW)}\n testId=\"files-tab-diff-toggle\"\n value={activeView}\n options={[\n { value: \"on\", label: t(I18nKey.FILES$DIFF_VIEW) },\n ...(showCommitsOption\n ? [\n {\n value: \"commits\" as const,\n label: t(I18nKey.DIFF_VIEWER$COMMITS),\n },\n ]\n : []),\n { value: \"off\", label: t(I18nKey.COMMON$FILES) },\n ]}\n onChange={(value) => {\n if (value === \"commits\") {\n setCommitsViewSelected(true);\n } else {\n setCommitsViewSelected(false);\n setFilesTabDiffView(value === \"on\");\n }\n }}\n />\n\n {activeView === \"off\" && (\n <SegmentedToggle<ViewMode>\n ariaLabel={t(I18nKey.FILES$RICH)}\n testId=\"files-tab-content-mode-toggle\"\n value={contentViewMode}\n options={[\n { value: \"rich\", label: t(I18nKey.FILES$RICH) },\n { value: \"plain\", label: t(I18nKey.FILES$PLAIN) },\n ]}\n onChange={setFilesTabContentViewMode}\n />\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n {/* Open the currently-selected file in a new browser tab. Only\n meaningful while we're showing a file (not the diff view) and\n we've resolved its staticUrl from the workspace fileserver. */}\n {activeView === \"off\" && selectedFileStaticUrl && (\n <a\n href={selectedFileStaticUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n title={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n data-testid=\"files-tab-open-in-new-window\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white\"\n >\n <LinkExternalIcon width={14} height={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={refreshFiles}\n disabled={isFetchingGitChanges}\n aria-label={t(I18nKey.FILES$REFRESH)}\n title={t(I18nKey.FILES$REFRESH)}\n data-testid=\"files-tab-refresh\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <RefreshIcon\n width={12.75}\n height={15}\n color=\"#ffffff\"\n className={isFetchingGitChanges ? \"animate-spin\" : \"\"}\n />\n </button>\n </div>\n </div>\n\n {activeView === \"on\" && (\n <div className=\"flex-1 min-h-0\">\n <GitChanges />\n </div>\n )}\n {activeView === \"commits\" && (\n <div className=\"flex-1 min-h-0\">\n <GitCommits />\n </div>\n )}\n {activeView === \"off\" && (\n <div className=\"flex flex-1 flex-col min-h-0\">\n {filesQuery.isLoading ? (\n <div className=\"flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]\">\n {t(I18nKey.FILES$LOADING_FILES)}\n </div>\n ) : (\n <>\n <FileQuickRow\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n isTreeVisible={isTreeVisible}\n onToggleTree={() => setIsTreeVisible((prev) => !prev)}\n />\n <div className=\"flex h-full min-h-0 flex-1\">\n {isTreeVisible && (\n <aside\n className=\"w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always\"\n data-testid=\"files-tab-tree\"\n >\n <FileTreeView\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n />\n </aside>\n )}\n <section\n className=\"flex h-full min-h-0 min-w-0 flex-1 flex-col\"\n data-testid=\"files-tab-content\"\n >\n {selectedPath ? (\n <FileContentViewer\n path={selectedPath}\n viewMode={contentViewMode}\n />\n ) : (\n <NoFileSelectedMessage />\n )}\n </section>\n </div>\n </>\n )}\n </div>\n )}\n </main>\n );\n}\n\nexport default FilesTab;\n"],"mappings":"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"}
|
|
@@ -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(`../services/settings.cjs`),i=require(`../constants/llm-subscription.cjs`),a=require(`../hooks/query/use-settings.cjs`),o=require(`../components/features/settings/settings-input.cjs`),s=require(`../components/features/settings/settings-dropdown-input.cjs`),c=require(`../utils/extract-model-and-provider.cjs`),l=require(`../ui/help-link.cjs`),u=require(`../components/shared/modals/settings/model-selector.cjs`),d=require(`../hooks/query/use-agent-settings-schema.cjs`),f=require(`../components/features/settings/llm-settings/openai-subscription-auth-card.cjs`),p=require(`../components/features/settings/key-status-icon.cjs`),m=require(`../utils/sdk-settings-schema.cjs`),h=require(`../components/features/settings/sdk-settings/sdk-section-page.cjs`);require(`../components/features/settings/llm-profiles/index.cjs`);const g=require(`../hooks/query/use-llm-subscription-models.cjs`);let _=require(`react`);_=e.__toESM(_,1);let v=require(`react/jsx-runtime`);var y=new Set([`llm.model`,`llm.api_key`,`llm.base_url`,i.LLM_AUTH_TYPE_KEY,i.LLM_SUBSCRIPTION_VENDOR_KEY]),b=(e,t)=>!e||!t?null:`${e}/${t}`,x=(e,t)=>e?.sections.flatMap(e=>e.fields).find(e=>e.key===t)?.default??null,S={openai:new Set([`https://api.openai.com`,`https://api.openai.com/v1`])},C=e=>{try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``)||``;return`${t.origin}${n}`}catch{return e.trim().replace(/\/+$/,``)}},w=(e,t)=>{let n=C(t),{provider:r}=c.extractModelAndProvider(e);if(r){let e=S[r];if(e)return e.has(n)}return Object.values(S).some(e=>e?.has(n))};function T({testId:e}){let{t:r}=t.useTranslation(`openhands`);return(0,v.jsx)(l.HelpLink,{testId:e,text:r(n.I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT),linkText:r(n.I18nKey.SETTINGS$NAV_API_KEYS),href:`https://app.all-hands.dev/settings/api-keys`,suffix:` ${r(n.I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`})}function E({scope:e=`personal`,onSaveSuccess:c,initialValueOverrides:S,embedded:C,hideSaveButton:E,suppressSuccessToast:D,onSaveControlChange:O}){let{t:k}=t.useTranslation(`openhands`),{data:A}=a.useSettings(e),{data:j}=d.useAgentSettingsSchema(A?.agent_settings_schema),M=A?.agent_settings?.llm,N=i.resolveLlmAuthType(S?.[`llm.auth_type`]??M?.auth_type),[P,F]=_.default.useState(N===i.LLM_AUTH_TYPE_SUBSCRIPTION),{data:I,isLoading:L,isFetching:R}=g.useOpenAISubscriptionModels({enabled:P}),z=P&&!I&&(L||R),B=_.default.useRef(null),V=_.default.useRef(null);_.default.useEffect(()=>{N===`subscription`&&F(!0)},[N]);let H=String(r.DEFAULT_SETTINGS.agent_settings?.llm?.model??``),U=_.default.useCallback((e,t)=>{let n=m.inferInitialView(e,t);if(n!==`basic`)return n;let r=e.llm_model??``,i=e.llm_base_url?.trim()??``;return i.length>0&&!w(r,i)?`all`:`basic`},[]),W=_.default.useCallback(({values:e,isDisabled:t,view:r,onChange:a})=>{let c=typeof e[`llm.model`]==`string`?e[`llm.model`]:``,d=typeof e[`llm.base_url`]==`string`?e[`llm.base_url`]:``,m=c.startsWith(`openhands/`),h=i.resolveLlmAuthType(e[i.LLM_AUTH_TYPE_KEY]),g=h===i.LLM_AUTH_TYPE_SUBSCRIPTION,_=t||g&&z,y=I?.includes(c)?c:I?.[0]??``,x=typeof e[`llm.api_key`]==`string`?e[`llm.api_key`]:``,S=C?x.length>0:!!A?.llm_api_key_set,w=(e,r)=>(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(o.SettingsInput,{testId:e,label:k(n.I18nKey.SETTINGS_FORM$API_KEY),type:`password`,className:`w-full`,value:x,placeholder:S?`<hidden>`:``,onChange:e=>a(`llm.api_key`,e),isDisabled:t,startContent:S?(0,v.jsx)(p.KeyStatusIcon,{isSet:S}):void 0}),(0,v.jsx)(l.HelpLink,{testId:r,text:k(n.I18nKey.SETTINGS$DONT_KNOW_API_KEY),linkText:k(n.I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS),href:`https://docs.openhands.dev/usage/local-setup#getting-an-api-key`})]}),E=e=>{let t=e===`subscription`?i.LLM_AUTH_TYPE_SUBSCRIPTION:i.LLM_AUTH_TYPE_API_KEY;if(a(i.LLM_AUTH_TYPE_KEY,t),t===`subscription`){F(!0),c&&!I?.includes(c)&&(B.current=c);let e=V.current&&I?.includes(V.current)?V.current:I?.[0];a(i.LLM_SUBSCRIPTION_VENDOR_KEY,i.OPENAI_SUBSCRIPTION_VENDOR),!I?.includes(c)&&e&&a(`llm.model`,e);return}c&&I?.includes(c)&&(V.current=c,a(`llm.model`,B.current??H))},D=()=>(0,v.jsx)(s.SettingsDropdownInput,{testId:`llm-auth-type-input`,name:i.LLM_AUTH_TYPE_KEY,label:k(n.I18nKey.SETTINGS$LLM_AUTH_TYPE),items:[{key:i.LLM_AUTH_TYPE_API_KEY,label:k(n.I18nKey.SETTINGS$LLM_AUTH_TYPE_API_KEY)},{key:i.LLM_AUTH_TYPE_SUBSCRIPTION,label:k(n.I18nKey.SETTINGS$LLM_AUTH_TYPE_SUBSCRIPTION)}],selectedKey:h,isClearable:!1,required:!0,isDisabled:_,onSelectionChange:E}),O=()=>(0,v.jsxs)(`div`,{className:`flex flex-col gap-6`,"data-testid":`llm-subscription-settings`,children:[(0,v.jsx)(s.SettingsDropdownInput,{testId:`llm-subscription-model-input`,name:`llm.subscription_model`,label:k(n.I18nKey.SETTINGS$SUBSCRIPTION_MODEL),items:(I??[]).map(e=>({key:e,label:e})),selectedKey:y,isClearable:!1,required:!0,isDisabled:_||!I?.length,onSelectionChange:e=>{let t=typeof e==`string`?e:I?.[0];t&&a(`llm.model`,t)}}),(0,v.jsx)(f.OpenAISubscriptionAuthCard,{isDisabled:t})]});return(0,v.jsx)(`div`,{className:`flex flex-col gap-6`,children:r===`basic`?(0,v.jsxs)(`div`,{className:`flex flex-col gap-6`,"data-testid":`llm-settings-form-basic`,children:[D(),g?O():(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(u.ModelSelector,{currentModel:c||void 0,onChange:(e,t)=>{let n=b(e,t);n&&a(`llm.model`,n)},wrapperClassName:`!flex-col !gap-6`,isDisabled:t}),m?(0,v.jsx)(T,{testId:`openhands-api-key-help`}):null,w(`llm-api-key-input`,`llm-api-key-help-anchor`)]})]}):(0,v.jsxs)(`div`,{className:`flex flex-col gap-6`,"data-testid":`llm-settings-form-advanced`,children:[D(),g?O():(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(o.SettingsInput,{testId:`llm-custom-model-input`,label:k(n.I18nKey.SETTINGS$CUSTOM_MODEL),type:`text`,className:`w-full`,value:c,placeholder:H,onChange:e=>a(`llm.model`,e),isDisabled:t}),m?(0,v.jsx)(T,{testId:`openhands-api-key-help-2`}):null,(0,v.jsx)(o.SettingsInput,{testId:`base-url-input`,label:k(n.I18nKey.SETTINGS$BASE_URL),type:`text`,className:`w-full`,value:d,placeholder:`https://api.openai.com`,onChange:e=>a(`llm.base_url`,e),isDisabled:t}),w(`llm-api-key-input`,`llm-api-key-help-anchor-advanced`)]})]})})},[H,C,z,A?.llm_api_key_set,I,k]),G=_.default.useCallback((e,t)=>{let n=structuredClone(e.agent_settings_diff??{}),r=n.llm??{};if(i.resolveLlmAuthType(t.values[`llm.auth_type`])===`subscription`){r.auth_type=i.LLM_AUTH_TYPE_SUBSCRIPTION,r.subscription_vendor=i.OPENAI_SUBSCRIPTION_VENDOR;let e=typeof r.model==`string`?r.model:String(t.values[`llm.model`]??``),n=I?.[0];if(!I?.includes(e)&&!n)throw Error(`Subscription models are not loaded yet.`);r.model=I?.includes(e)?e:n,delete r.api_key,delete r.base_url}else t.dirty[`llm.auth_type`]&&(r.auth_type=i.LLM_AUTH_TYPE_API_KEY,r.subscription_vendor=null),t.view===`basic`&&r.model!==void 0&&(r.base_url=x(j,`llm.base_url`));return n.llm=r,{agent_settings_diff:n}},[j,I]);return(0,v.jsx)(h.SdkSectionPage,{scope:e,settingsSources:[{settingsSource:`agent_settings`,sectionKeys:[`llm`],excludeKeys:y}],header:W,buildPayload:G,getInitialView:U,forceShowAdvancedView:!0,allowAllView:!0,onSaveSuccess:c,initialValueOverrides:S,embedded:C,hideSaveButton:E,suppressSuccessToast:D,onSaveControlChange:O,testId:`llm-settings-screen`})}exports.LlmSettingsScreen=E;
|
|
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(`../services/settings.cjs`),i=require(`../constants/llm-subscription.cjs`),a=require(`../hooks/query/use-settings.cjs`),o=require(`../components/features/settings/settings-input.cjs`),s=require(`../components/features/settings/settings-dropdown-input.cjs`),c=require(`../utils/extract-model-and-provider.cjs`),l=require(`../ui/help-link.cjs`),u=require(`../components/shared/modals/settings/model-selector.cjs`),d=require(`../hooks/query/use-agent-settings-schema.cjs`),f=require(`../components/features/settings/llm-settings/openai-subscription-auth-card.cjs`),p=require(`../components/features/settings/key-status-icon.cjs`),m=require(`../utils/sdk-settings-schema.cjs`),h=require(`../components/features/settings/sdk-settings/sdk-section-page.cjs`);require(`../components/features/settings/llm-profiles/index.cjs`);const g=require(`../hooks/query/use-llm-subscription-models.cjs`);let _=require(`react`);_=e.__toESM(_,1);let v=require(`react/jsx-runtime`);var y=new Set([`llm.model`,`llm.api_key`,`llm.base_url`,i.LLM_AUTH_TYPE_KEY,i.LLM_SUBSCRIPTION_VENDOR_KEY]),b=(e,t)=>!e||!t?null:`${e}/${t}`,x=(e,t)=>e?.sections.flatMap(e=>e.fields).find(e=>e.key===t)?.default??null,S={openai:new Set([`https://api.openai.com`,`https://api.openai.com/v1`]),moonshot:new Set([`https://api.kimi.com/coding/v1`])},C=e=>{try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``)||``;return`${t.origin}${n}`}catch{return e.trim().replace(/\/+$/,``)}},w=(e,t)=>{let n=C(t),{provider:r}=c.extractModelAndProvider(e);if(r){let e=S[r];if(e)return e.has(n)}return Object.values(S).some(e=>e?.has(n))};function T({testId:e}){let{t:r}=t.useTranslation(`openhands`);return(0,v.jsx)(l.HelpLink,{testId:e,text:r(n.I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT),linkText:r(n.I18nKey.SETTINGS$NAV_API_KEYS),href:`https://app.all-hands.dev/settings/api-keys`,suffix:` ${r(n.I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`})}function E({scope:e=`personal`,onSaveSuccess:c,initialValueOverrides:S,embedded:C,hideSaveButton:E,suppressSuccessToast:D,onSaveControlChange:O}){let{t:k}=t.useTranslation(`openhands`),{data:A}=a.useSettings(e),{data:j}=d.useAgentSettingsSchema(A?.agent_settings_schema),M=A?.agent_settings?.llm,N=i.resolveLlmAuthType(S?.[`llm.auth_type`]??M?.auth_type),[P,F]=_.default.useState(N===i.LLM_AUTH_TYPE_SUBSCRIPTION),{data:I,isLoading:L,isFetching:R}=g.useOpenAISubscriptionModels({enabled:P}),z=P&&!I&&(L||R),B=_.default.useRef(null),V=_.default.useRef(null);_.default.useEffect(()=>{N===`subscription`&&F(!0)},[N]);let H=String(r.DEFAULT_SETTINGS.agent_settings?.llm?.model??``),U=_.default.useCallback((e,t)=>{let n=m.inferInitialView(e,t);if(n!==`basic`)return n;let r=e.llm_model??``,i=e.llm_base_url?.trim()??``;return i.length>0&&!w(r,i)?`all`:`basic`},[]),W=_.default.useCallback(({values:e,isDisabled:t,view:r,onChange:a})=>{let c=typeof e[`llm.model`]==`string`?e[`llm.model`]:``,d=typeof e[`llm.base_url`]==`string`?e[`llm.base_url`]:``,m=c.startsWith(`openhands/`),h=i.resolveLlmAuthType(e[i.LLM_AUTH_TYPE_KEY]),g=h===i.LLM_AUTH_TYPE_SUBSCRIPTION,_=t||g&&z,y=I?.includes(c)?c:I?.[0]??``,x=typeof e[`llm.api_key`]==`string`?e[`llm.api_key`]:``,S=C?x.length>0:!!A?.llm_api_key_set,w=(e,r)=>(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(o.SettingsInput,{testId:e,label:k(n.I18nKey.SETTINGS_FORM$API_KEY),type:`password`,className:`w-full`,value:x,placeholder:S?`<hidden>`:``,onChange:e=>a(`llm.api_key`,e),isDisabled:t,startContent:S?(0,v.jsx)(p.KeyStatusIcon,{isSet:S}):void 0}),(0,v.jsx)(l.HelpLink,{testId:r,text:k(n.I18nKey.SETTINGS$DONT_KNOW_API_KEY),linkText:k(n.I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS),href:`https://docs.openhands.dev/usage/local-setup#getting-an-api-key`})]}),E=e=>{let t=e===`subscription`?i.LLM_AUTH_TYPE_SUBSCRIPTION:i.LLM_AUTH_TYPE_API_KEY;if(a(i.LLM_AUTH_TYPE_KEY,t),t===`subscription`){F(!0),c&&!I?.includes(c)&&(B.current=c);let e=V.current&&I?.includes(V.current)?V.current:I?.[0];a(i.LLM_SUBSCRIPTION_VENDOR_KEY,i.OPENAI_SUBSCRIPTION_VENDOR),!I?.includes(c)&&e&&a(`llm.model`,e);return}c&&I?.includes(c)&&(V.current=c,a(`llm.model`,B.current??H))},D=()=>(0,v.jsx)(s.SettingsDropdownInput,{testId:`llm-auth-type-input`,name:i.LLM_AUTH_TYPE_KEY,label:k(n.I18nKey.SETTINGS$LLM_AUTH_TYPE),items:[{key:i.LLM_AUTH_TYPE_API_KEY,label:k(n.I18nKey.SETTINGS$LLM_AUTH_TYPE_API_KEY)},{key:i.LLM_AUTH_TYPE_SUBSCRIPTION,label:k(n.I18nKey.SETTINGS$LLM_AUTH_TYPE_SUBSCRIPTION)}],selectedKey:h,isClearable:!1,required:!0,isDisabled:_,onSelectionChange:E}),O=()=>(0,v.jsxs)(`div`,{className:`flex flex-col gap-6`,"data-testid":`llm-subscription-settings`,children:[(0,v.jsx)(s.SettingsDropdownInput,{testId:`llm-subscription-model-input`,name:`llm.subscription_model`,label:k(n.I18nKey.SETTINGS$SUBSCRIPTION_MODEL),items:(I??[]).map(e=>({key:e,label:e})),selectedKey:y,isClearable:!1,required:!0,isDisabled:_||!I?.length,onSelectionChange:e=>{let t=typeof e==`string`?e:I?.[0];t&&a(`llm.model`,t)}}),(0,v.jsx)(f.OpenAISubscriptionAuthCard,{isDisabled:t})]});return(0,v.jsx)(`div`,{className:`flex flex-col gap-6`,children:r===`basic`?(0,v.jsxs)(`div`,{className:`flex flex-col gap-6`,"data-testid":`llm-settings-form-basic`,children:[D(),g?O():(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(u.ModelSelector,{currentModel:c||void 0,onChange:(e,t)=>{let n=b(e,t);n&&a(`llm.model`,n)},wrapperClassName:`!flex-col !gap-6`,isDisabled:t}),m?(0,v.jsx)(T,{testId:`openhands-api-key-help`}):null,w(`llm-api-key-input`,`llm-api-key-help-anchor`)]})]}):(0,v.jsxs)(`div`,{className:`flex flex-col gap-6`,"data-testid":`llm-settings-form-advanced`,children:[D(),g?O():(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(o.SettingsInput,{testId:`llm-custom-model-input`,label:k(n.I18nKey.SETTINGS$CUSTOM_MODEL),type:`text`,className:`w-full`,value:c,placeholder:H,onChange:e=>a(`llm.model`,e),isDisabled:t}),m?(0,v.jsx)(T,{testId:`openhands-api-key-help-2`}):null,(0,v.jsx)(o.SettingsInput,{testId:`base-url-input`,label:k(n.I18nKey.SETTINGS$BASE_URL),type:`text`,className:`w-full`,value:d,placeholder:`https://api.openai.com`,onChange:e=>a(`llm.base_url`,e),isDisabled:t}),w(`llm-api-key-input`,`llm-api-key-help-anchor-advanced`)]})]})})},[H,C,z,A?.llm_api_key_set,I,k]),G=_.default.useCallback((e,t)=>{let n=structuredClone(e.agent_settings_diff??{}),r=n.llm??{};if(i.resolveLlmAuthType(t.values[`llm.auth_type`])===`subscription`){r.auth_type=i.LLM_AUTH_TYPE_SUBSCRIPTION,r.subscription_vendor=i.OPENAI_SUBSCRIPTION_VENDOR;let e=typeof r.model==`string`?r.model:String(t.values[`llm.model`]??``),n=I?.[0];if(!I?.includes(e)&&!n)throw Error(`Subscription models are not loaded yet.`);r.model=I?.includes(e)?e:n,delete r.api_key,delete r.base_url}else t.dirty[`llm.auth_type`]&&(r.auth_type=i.LLM_AUTH_TYPE_API_KEY,r.subscription_vendor=null),t.view===`basic`&&r.model!==void 0&&(r.base_url=x(j,`llm.base_url`));return n.llm=r,{agent_settings_diff:n}},[j,I]);return(0,v.jsx)(h.SdkSectionPage,{scope:e,settingsSources:[{settingsSource:`agent_settings`,sectionKeys:[`llm`],excludeKeys:y}],header:W,buildPayload:G,getInitialView:U,forceShowAdvancedView:!0,allowAllView:!0,onSaveSuccess:c,initialValueOverrides:S,embedded:C,hideSaveButton:E,suppressSuccessToast:D,onSaveControlChange:O,testId:`llm-settings-screen`})}exports.LlmSettingsScreen=E;
|
|
2
2
|
//# sourceMappingURL=llm-settings.cjs.map
|