@openhands/agent-canvas 1.0.0-rc.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -31
- package/README.windows.md +2 -2
- package/bin/agent-canvas.mjs +3 -1
- package/build/assets/Trans-CBypf0vt.js +1 -0
- package/build/assets/{acp-providers-BqUvf67Q.js → acp-providers-BMyF5WII.js} +1 -1
- package/build/assets/active-backend-context-Cy_Ui5d7.js +1 -0
- package/build/assets/add-backend-modal-CUw7x0zm.js +1 -0
- package/build/assets/agent-server-client-options-FoO1qgAQ.js +1 -0
- package/build/assets/agent-server-conversation-service.api-D6Cmbnhd.js +5 -0
- package/build/assets/{agent-settings-DoHXHcoA.js → agent-settings-DW4vwOaz.js} +2 -2
- package/build/assets/{alert-banner-Bsvys-hT.js → alert-banner-BHmoArV2.js} +1 -1
- package/build/assets/{analytics-consent-form-modal-CVhsAREx.js → analytics-consent-form-modal-BNK0yu4L.js} +1 -1
- package/build/assets/api-key-entry-screen-BjVajIjf.js +1 -0
- package/build/assets/app-settings-C-5X6RzZ.js +1 -0
- package/build/assets/automation-detail-uDMoYmAc.js +1 -0
- package/build/assets/automations-list-DBCKCbId.js +1 -0
- package/build/assets/{back-nav-button-D20Avel_.js → back-nav-button-Bckz5Wh6.js} +1 -1
- package/build/assets/backend-form-modal-D2-XqJA4.js +1 -0
- package/build/assets/{backend-synced-settings-badge-Dcd4712m.js → backend-synced-settings-badge-Dx16CR_k.js} +1 -1
- package/build/assets/{base-modal-DvuGYyu1.js → base-modal-7QRNzf6r.js} +1 -1
- package/build/assets/{brand-button-9SOzmqPP.js → brand-button-CKLvirxz.js} +1 -1
- package/build/assets/browser-D1ZybR7v.js +5 -0
- package/build/assets/browser-store-hzasvz9c.js +1 -0
- package/build/assets/{browser-tab-bveyJhG9.js → browser-tab-iOQjXzmI.js} +1 -1
- package/build/assets/chat-send-button-_Uc9iFpG.js +1 -0
- package/build/assets/check-DfvhVBub.js +1 -0
- package/build/assets/{checkmark--JWAesua.js → checkmark-BHPhb50L.js} +1 -1
- package/build/assets/{chevron-down-B9j6lcFg.js → chevron-down-CMkqyPEY.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-AO9DWyDX.js → circle-plus-check-toggle-ChmnRlpR.js} +1 -1
- package/build/assets/{close--W-tHn1h.js → close-DBs90sI6.js} +1 -1
- package/build/assets/{code-tag-chmctf4w.js → code-tag-BtHOqHwB.js} +1 -1
- package/build/assets/{color-themes-0biOprdo.js → color-themes-CBikRn3w.js} +1 -1
- package/build/assets/{combobox-caret-C9BNHfSu.js → combobox-caret-evUAh6YW.js} +1 -1
- package/build/assets/{command-store-UzKGSUC2.js → command-store-DZfR8QtE.js} +1 -1
- package/build/assets/condenser-settings-0tw3yXX8.js +1 -0
- package/build/assets/{confirmation-modal-Cq3eqvqH.js → confirmation-modal-DWuxe1zG.js} +1 -1
- package/build/assets/{context-menu-list-item-BQU0jZPq.js → context-menu-list-item-BbHFxHaq.js} +1 -1
- package/build/assets/conversation-B1v96pQf.js +19 -0
- package/build/assets/conversation-DgfcjCPm.js +1 -0
- package/build/assets/{conversation-local-storage-an3MiIiJ.js → conversation-local-storage-Btum2xBJ.js} +1 -1
- package/build/assets/conversation-panel-TJ7swm6a.js +1 -0
- package/build/assets/conversation-service.api-DXawvmNN.js +1 -0
- package/build/assets/conversation-state-store-DmuPn875.js +1 -0
- package/build/assets/{conversation-store-FQmakEd-.js → conversation-store-Bu89Yxg1.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-C8tztloo.js → conversation-tab-empty-state-7js7FjYM.js} +1 -1
- package/build/assets/{copy-CdKN5rtJ.js → copy-B0SkXenR.js} +1 -1
- package/build/assets/copy-to-clipboard-button-CfH2EQz9.js +1 -0
- package/build/assets/{createLucideIcon-CkGTf9Qj.js → createLucideIcon-Bazr-V-B.js} +1 -1
- package/build/assets/declaration-Cn-NXHEy.js +1 -0
- package/build/assets/{device-verify-YuGXnpRk.js → device-verify-CWKyQ680.js} +1 -1
- package/build/assets/{dist-5dObF4p4.js → dist-Cbu6eGx8.js} +1 -1
- package/build/assets/dist-Dg2JWLGc.js +1 -0
- package/build/assets/{dropdown-classes-CVp0kVdt.js → dropdown-classes-BI1bI1ho.js} +1 -1
- package/build/assets/edit-automation-modal-DdAG6kFZ.js +1 -0
- package/build/assets/{ellipsis-button-k7HLwYth.js → ellipsis-button-DdCsOBHV.js} +1 -1
- package/build/assets/entry.client-DXyvKj5G.js +2 -0
- package/build/assets/{enum-filter-dropdown-COqUq3mB.js → enum-filter-dropdown-WROAIeys.js} +1 -1
- package/build/assets/{environment-switch-overlay-wB5LxfYZ.js → environment-switch-overlay-Dv0imPE6.js} +1 -1
- package/build/assets/{extensions-hub-CoWO3SzQ.js → extensions-hub-CkyDPXvn.js} +1 -1
- package/build/assets/{extensions-navigation-D5w2sFQe.js → extensions-navigation-gMR-la1J.js} +1 -1
- package/build/assets/{external-link-BATfjnkz.js → external-link-FsutnU75.js} +1 -1
- package/build/assets/files-tab-DNUoveJZ.js +1 -0
- package/build/assets/files-tab-store-SyvkH3ic.js +1 -0
- package/build/assets/{folder-DPTBlxWb.js → folder-DusyBXDE.js} +1 -1
- package/build/assets/{globe-Dpgjreyy.js → globe-BUcin4kT.js} +1 -1
- package/build/assets/home-D809jWVS.js +1 -0
- package/build/assets/{iconBase-BVhFI-0E.js → iconBase-B6CXDDaE.js} +1 -1
- package/build/assets/index-redirect-nMYgOTBX.js +1 -0
- package/build/assets/install-server-modal-D92Qy57I.js +1 -0
- package/build/assets/{launch-fU77utLO.js → launch-BnCG2g2a.js} +1 -1
- package/build/assets/lesson-plan-j-ZaE8vK.js +3 -0
- package/build/assets/{lightbulb-S616sGEL.js → lightbulb-BJ5tWmAh.js} +1 -1
- package/build/assets/{link-external-ooNztGLp.js → link-external-DUtmHAHi.js} +1 -1
- package/build/assets/{list-todo-nCa9zxVE.js → list-todo-C-gekh-4.js} +1 -1
- package/build/assets/{llm-client-P9f2gKeW.js → llm-client-BZUkZYlc.js} +1 -1
- package/build/assets/llm-not-configured-banner-PlvJ99rE.js +27 -0
- package/build/assets/llm-settings-Dgk32xRW.js +1 -0
- package/build/assets/llm-settings-Dxo7owKm.js +1 -0
- package/build/assets/llm-subscription-Bvu8BLXc.js +1 -0
- package/build/assets/llm-subscription-service-Bq6z3Wkv.js +1 -0
- package/build/assets/loader-circle-Cw7_q9hg.js +1 -0
- package/build/assets/{loading-spinner-D7bOU6I7.js → loading-spinner-RF3IlMF5.js} +1 -1
- package/build/assets/manage-backends-modal-BT66a6e0.js +1 -0
- package/build/assets/manifest-b8402d59.js +1 -0
- package/build/assets/markdown-renderer-Tw6FR2ad.js +2 -0
- package/build/assets/mcp-B_pA7vZg.js +9 -0
- package/build/assets/mcp-client-ppbYplKX.js +1 -0
- package/build/assets/messages-Cg9aNVi6.js +41 -0
- package/build/assets/{modal-backdrop-_VbcKk5K.js → modal-backdrop-DRpBVVW5.js} +1 -1
- package/build/assets/{modal-body-Cd-PtMHr.js → modal-body-CEV2O67p.js} +1 -1
- package/build/assets/{modal-classes-CNm4ovfm.js → modal-classes-B2DuQ9qD.js} +1 -1
- package/build/assets/{modal-close-button-Dbo0NAMt.js → modal-close-button-gtb7RHFB.js} +1 -1
- package/build/assets/model-selector-CAv3RrJ3.js +1 -0
- package/build/assets/{mouse-pointer-click-D0QNGSIo.js → mouse-pointer-click-B3i6HcaF.js} +1 -1
- package/build/assets/{navigation-context-BpAOh_t5.js → navigation-context-CM9JmTvm.js} +1 -1
- package/build/assets/{navigation-link-Dci7Nuyf.js → navigation-link-FmXzqR1J.js} +1 -1
- package/build/assets/onboarding-Q9CzuVWy.js +1 -0
- package/build/assets/{openhands-logo-Dzm-d_V_.js → openhands-logo-B4aEO2sf.js} +1 -1
- package/build/assets/option-service.api-C-s2BYZp.js +1 -0
- package/build/assets/organization-service.api-CXTKpFnV.js +1 -0
- package/build/assets/{path-utils-YlkpoImJ.js → path-utils-CE98fIFP.js} +1 -1
- package/build/assets/{pencil-DPEtl5QD.js → pencil-bWrxRWlr.js} +1 -1
- package/build/assets/{plan-components-CutRBi0G.js → plan-components-BF-X7vnQ.js} +1 -1
- package/build/assets/{planner-tab-DjIFIQDk.js → planner-tab-jkyaGiRc.js} +1 -1
- package/build/assets/plus-BTCK8WtR.js +1 -0
- package/build/assets/{profiles-client-BNvHck-I.js → profiles-client-CQ9L1yHR.js} +1 -1
- package/build/assets/providers-B3hkV58J.js +1 -0
- package/build/assets/proxy-BOcEWkCD.js +1 -0
- package/build/assets/{react-dom-hVBnwgwZ.js → react-dom-BBXlXOZX.js} +1 -1
- package/build/assets/{react-CM_dJw1Z.js → react-uQK8du1l.js} +1 -1
- package/build/assets/{react-Dy05vyj5.js → react-x84lbX6s.js} +1 -1
- package/build/assets/{recommended-automations-launcher-DCi0RXIj.js → recommended-automations-launcher-DMk35aFI.js} +11 -11
- package/build/assets/root-CV0kyxfP.js +2 -0
- package/build/assets/root-PB2Jnj61.css +1 -0
- package/build/assets/root-layout-Bl4Qzg5J.js +2 -0
- package/build/assets/{runtime-waiting-state-8i0Z3A_i.js → runtime-waiting-state-C1hJpXxl.js} +1 -1
- package/build/assets/sdk-section-page-DHbC2_j3.js +1 -0
- package/build/assets/sdk-settings-schema-z51bBmMl.js +1 -0
- package/build/assets/{search-C_l_XW4e.js → search-Dxm1MUMi.js} +1 -1
- package/build/assets/{secrets-service-D6Gcymcs.js → secrets-service-DlScPUwy.js} +1 -1
- package/build/assets/secrets-settings-B97-JKBe.js +1 -0
- package/build/assets/settings-BpmooyBV.js +1 -0
- package/build/assets/{settings-dropdown-input-BP-arqjU.js → settings-dropdown-input-hIIAlmHb.js} +1 -1
- package/build/assets/{settings-gear-f-zWpxfI.js → settings-gear-DQLTCnFx.js} +1 -1
- package/build/assets/{settings-index-B035V2pu.js → settings-index-kKASonWk.js} +1 -1
- package/build/assets/{settings-input-BM8ANxDb.js → settings-input-BlOzCtP3.js} +1 -1
- package/build/assets/{settings-list-classes-B9uo5WES.js → settings-list-classes-BFRbCy4U.js} +1 -1
- package/build/assets/settings-modal-C4pZwj-l.js +1 -0
- package/build/assets/{settings-section-header-context-Cid25HM2.js → settings-section-header-context-iz4Go0dL.js} +1 -1
- package/build/assets/settings-service.api-DVLwi82B.js +1 -0
- package/build/assets/{settings-switch-xa6q4M6j.js → settings-switch-6cXIH-UE.js} +1 -1
- package/build/assets/{settings-utils--H_EvFjx.js → settings-utils-CfScEaPn.js} +1 -1
- package/build/assets/shared-conversation-CLkayApe.js +1 -0
- package/build/assets/sidebar-mobile-menu-toggle-C8uT4Mhd.js +1 -0
- package/build/assets/{sidebar-nav-link-CPWuQ_c6.js → sidebar-nav-link-BKZiAQxQ.js} +1 -1
- package/build/assets/{skill-card-pill-row-DeodrwPG.js → skill-card-pill-row-D13WRKIE.js} +1 -1
- package/build/assets/{skills-BE5HJuGM.js → skills-NpRk6v79.js} +1 -1
- package/build/assets/{skills-client-Ui_9FvXp.js → skills-client-DsqwQEwj.js} +1 -1
- package/build/assets/{skills-plugins-Dc4ec3CW.js → skills-plugins-bkwxItAw.js} +1 -1
- package/build/assets/{skills-settings-B6HwvA0S.js → skills-settings-DMbrlB2b.js} +2 -2
- package/build/assets/{square-chevron-right-BWAB7NPp.js → square-chevron-right-DxZKcVq4.js} +1 -1
- package/build/assets/{styled-tooltip-X61SEwqk.js → styled-tooltip-DG1ofAcS.js} +1 -1
- package/build/assets/suspense-sOGeme-f.js +1 -0
- package/build/assets/{switch-skeleton-BbIWemkK.js → switch-skeleton-CZ6XCVZk.js} +1 -1
- package/build/assets/{task-list-tab-BFnyHGsn.js → task-list-tab-CddMPNCD.js} +1 -1
- package/build/assets/telemetry-CX4mTZUw.js +2 -0
- package/build/assets/{terminal-CltMeLv4.js → terminal-BOAVxAej.js} +1 -1
- package/build/assets/{terminal-B92mACR5.js → terminal-DbtwHqt4.js} +1 -1
- package/build/assets/{toggle-switch-CL_wRiGs.js → toggle-switch-C0t6ge2m.js} +1 -1
- package/build/assets/{trash-2-C-RvV8WA.js → trash-2-Dmprz0A0.js} +1 -1
- package/build/assets/{typography-BLSEGjph.js → typography-CNHbO1eE.js} +1 -1
- package/build/assets/{u-check-circle-dG_VJqx5.js → u-check-circle-CX66WzfT.js} +1 -1
- package/build/assets/{u-check-circle-half-D-5ZPRnd.js → u-check-circle-half-Bj853Ub0.js} +1 -1
- package/build/assets/{u-circuit-BXoisXOA.js → u-circuit-B9bLCP7N.js} +1 -1
- package/build/assets/{u-edit-DIgADxLH.js → u-edit-D7JyvoWm.js} +1 -1
- package/build/assets/use-acp-credential-form-Cj_oUYd5.js +1 -0
- package/build/assets/{use-active-conversation-B0_rXnqa.js → use-active-conversation-B64-yy2X.js} +1 -1
- package/build/assets/use-agent-settings-schema-BzbQYEzb.js +1 -0
- package/build/assets/{use-agent-state-BuOzLeFN.js → use-agent-state-DxFk391r.js} +1 -1
- package/build/assets/{use-breakpoint-DpxHDmuH.js → use-breakpoint-Cent5lpI.js} +1 -1
- package/build/assets/{use-click-outside-element-DhxCUyWl.js → use-click-outside-element-DOYR26nw.js} +1 -1
- package/build/assets/{use-cloud-current-user-id-DVZXa_WH.js → use-cloud-current-user-id-BVf7pb8n.js} +1 -1
- package/build/assets/use-config-CvdJUq4E.js +1 -0
- package/build/assets/use-create-conversation-Cnouynop.js +1 -0
- package/build/assets/{use-create-secret-ClPpLBgD.js → use-create-secret-Cgu4uxyr.js} +1 -1
- package/build/assets/{use-event-store-DNSmyzUh.js → use-event-store-Nv92IYMU.js} +1 -1
- package/build/assets/use-handle-plan-click-C7824bbe.js +1 -0
- package/build/assets/use-is-authed-mnJtd2bw.js +1 -0
- package/build/assets/{use-launch-skill-in-chat-BTgXIu3N.js → use-launch-skill-in-chat-NDUo_UCA.js} +1 -1
- package/build/assets/use-llm-profiles-9eH3Y3Ef.js +1 -0
- package/build/assets/use-runtime-is-ready-DEnxJH7W.js +1 -0
- package/build/assets/use-save-settings-DrClHnX7.js +1 -0
- package/build/assets/use-settings-BNAoCX93.js +1 -0
- package/build/assets/{use-settings-nav-items-DVrMNk0I.js → use-settings-nav-items-CLIW2p2n.js} +2 -2
- package/build/assets/{use-skills-Bv8LXrys.js → use-skills-B9gOHrOj.js} +1 -1
- package/build/assets/{use-task-list-E5t-jtgs.js → use-task-list-DLKPnq3I.js} +1 -1
- package/build/assets/{use-tracking-BhyV5A9i.js → use-tracking-Dph_dRlL.js} +1 -1
- package/build/assets/{use-user-conversation-6yFVEXiG.js → use-user-conversation-leIsQH1B.js} +1 -1
- package/build/assets/useMutation-cXADjWAv.js +1 -0
- package/build/assets/useQuery-BQr6A6ry.js +1 -0
- package/build/assets/useTranslation-Bp1btAjp.js +1 -0
- package/build/assets/{utils-eXk6yerZ.js → utils-o-OXNtEy.js} +1 -1
- package/build/assets/v4-DOSjXdIn.js +1 -0
- package/build/assets/{vendor~browser-tab-BGJDGHyS.js → vendor~browser-tab-642bOcE1.js} +1 -1
- package/build/assets/{vendor~conversation-panel~conversation-D98u43rl.js → vendor~conversation-panel~conversation-DqmbnXRn.js} +1 -1
- package/build/assets/{vendor~conversation-panel~conversation~alert-banner-CtjHOMO_.js → vendor~conversation-panel~conversation~alert-banner-CSDVP1nw.js} +1 -1
- package/build/assets/{vendor~conversation-panel~conversation~index-BXt2-3Cc.js → vendor~conversation-panel~conversation~index-DITarr3F.js} +1 -1
- package/build/assets/{vendor~entry.client-DrAdOKqA.js → vendor~entry.client-CQ77DucR.js} +1 -1
- package/build/assets/{vendor~entry.client-EcEhmoJW.js → vendor~entry.client-ePAFmSwg.js} +1 -1
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~f0pn7nss-DUk-MwlC.js +177 -0
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~lb3qbbk3-BvmOva8I.js +1 -0
- package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~lpdshwee-Cl4h-NSi.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~lpdshwee-BkQQxq_q.js} +1 -1
- package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~oli4dvxu-BmOMM-6e.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~oli4dvxu-8xF3WeB9.js} +1 -1
- package/build/assets/{vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-BjMt2JeR.js → vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~nyk4vv4g-UzR6fe3Y.js} +1 -1
- package/build/assets/{vendor~files-tab--640YzQO.js → vendor~files-tab-Cko7Kr5k.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation-dhKA2JVJ.js → vendor~home~conversation-panel~conversation-D3otw5Jn.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DMOoHVBy.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CMdKUYP2.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BoE6JRJj.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DSR6Mugx.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Dqpi2xyZ.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DdOzMvB1.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DX2CmDJ0.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Dj2eezvL.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BNExlCqT.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DyN8jeZz.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DCn1M97v.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-lpEWrbMA.js} +1 -1
- package/build/assets/{vendor~launch-C0VvUe2W.js → vendor~launch-DoYO54df.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-COLUW-6M.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-BGwU2SbU.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation-eG1kjEbj.js → vendor~root-layout~home~conversation-panel~conversation-Iqs0j4Wo.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~bok0tgtf-7eqKdLSQ.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~bok0tgtf-BdS6bbw9.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~bok0tgtf-BP3MGAAY.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~bok0tgtf-Fd3F3jth.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~ceijy54y-Dkd2wxJA.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~ceijy54y-Cg0AqwMN.js} +2 -2
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~bxn4ldi1-_LydBB1e.js → vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~bxn4ldi1-BlsbqRyZ.js} +1 -1
- package/build/assets/vendor~root-layout~home~conversation-panel~conversation~launch~settings~settings-index~agen~ec6pk3ix-CBICqfKC.js +48 -0
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~skills-settings~mcp~automati~dou5smdo-DavKsAvB.js → vendor~root-layout~home~conversation-panel~conversation~launch~skills-settings~automations-~nv6afr11-BYNoKMU0.js} +97 -69
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-CsO1gYxF.js → vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-BspUuSsP.js} +1 -1
- package/build/assets/{vendor~root-layout~home~mcp~automations-list-D40jgugf.js → vendor~root-layout~home~mcp~automations-list-C9U_eOqU.js} +1 -1
- package/build/assets/{vendor~root-layout~home~mcp~automations-list-cNHi83v_.js → vendor~root-layout~home~mcp~automations-list-DhQ3LPVw.js} +1 -1
- package/build/assets/{vendor~root-layout~home~mcp~llm-settings~agent-settings~condenser-settings~verification-set~o7tv66sg-xCM3k6Rd.js → vendor~root-layout~home~mcp~llm-settings~agent-settings~condenser-settings~verification-set~o7tv66sg-BEbhHQYg.js} +1 -1
- package/build/assets/{vendor~root-layout~home~mcp~llm-settings~agent-settings~condenser-settings~verification-set~o7tv66sg-BIm99UaF.js → vendor~root-layout~home~mcp~llm-settings~agent-settings~condenser-settings~verification-set~o7tv66sg-DdgDNzMc.js} +2 -2
- package/build/assets/{verification-settings-Be6NxjuT.js → verification-settings-D7R-Ne6L.js} +1 -1
- package/build/assets/x-DCZg87p7.js +1 -0
- package/build/assets/{x-mark-C42svtnu.js → x-mark-jrBTJbnP.js} +1 -1
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +22 -0
- package/build/locales/ca/openhands.json +22 -0
- package/build/locales/de/openhands.json +22 -0
- package/build/locales/en/openhands.json +22 -0
- package/build/locales/es/openhands.json +22 -0
- package/build/locales/fr/openhands.json +22 -0
- package/build/locales/it/openhands.json +22 -0
- package/build/locales/ja/openhands.json +22 -0
- package/build/locales/ko-KR/openhands.json +22 -0
- package/build/locales/no/openhands.json +22 -0
- package/build/locales/pt/openhands.json +22 -0
- package/build/locales/tr/openhands.json +22 -0
- package/build/locales/uk/openhands.json +22 -0
- package/build/locales/zh-CN/openhands.json +22 -0
- package/build/locales/zh-TW/openhands.json +22 -0
- package/config/defaults.json +4 -7
- 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 +8 -0
- package/dist/api/agent-server-adapter.js +82 -80
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/agent-server-compatibility.cjs +1 -1
- package/dist/api/agent-server-compatibility.cjs.map +1 -1
- package/dist/api/agent-server-compatibility.d.ts +10 -0
- package/dist/api/agent-server-compatibility.js +69 -25
- package/dist/api/agent-server-compatibility.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 +6 -5
- package/dist/api/backend-registry/default-backend.js +1 -1
- 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 -68
- package/dist/api/backend-registry/storage.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 +3 -16
- package/dist/api/cloud/proxy.js +1 -1
- package/dist/api/cloud/proxy.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.js +75 -75
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/llm-subscription-service.cjs +2 -0
- package/dist/api/llm-subscription-service.cjs.map +1 -0
- package/dist/api/llm-subscription-service.d.ts +23 -0
- package/dist/api/llm-subscription-service.js +109 -0
- package/dist/api/llm-subscription-service.js.map +1 -0
- package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
- package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
- package/dist/api/mcp-service/mcp-service.api.d.ts +2 -3
- package/dist/api/mcp-service/mcp-service.api.js +38 -13
- package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
- package/dist/api/settings-service/settings-service.api.cjs +1 -1
- package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
- package/dist/api/settings-service/settings-service.api.js +41 -42
- package/dist/api/settings-service/settings-service.api.js.map +1 -1
- package/dist/components/conversation-events/chat/messages.cjs +1 -1
- package/dist/components/conversation-events/chat/messages.cjs.map +1 -1
- package/dist/components/conversation-events/chat/messages.js +4 -4
- package/dist/components/conversation-events/chat/messages.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.js +136 -135
- package/dist/components/features/backends/backend-form-modal.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 +103 -91
- package/dist/components/features/backends/backend-selector.js.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.js +14 -8
- package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
- package/dist/components/features/chat/path-component.cjs +1 -1
- package/dist/components/features/chat/path-component.cjs.map +1 -1
- package/dist/components/features/chat/path-component.js +1 -1
- package/dist/components/features/chat/path-component.js.map +1 -1
- package/dist/components/features/home/workspace-dropdown/folder-browser-modal.cjs +1 -1
- package/dist/components/features/home/workspace-dropdown/folder-browser-modal.cjs.map +1 -1
- package/dist/components/features/home/workspace-dropdown/folder-browser-modal.js +77 -66
- package/dist/components/features/home/workspace-dropdown/folder-browser-modal.js.map +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.js +1 -0
- package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
- package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
- package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
- package/dist/components/features/mcp-page/install-server-modal.js +73 -46
- package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
- package/dist/components/features/mcp-page/marketplace-card.cjs +1 -1
- package/dist/components/features/mcp-page/marketplace-card.cjs.map +1 -1
- package/dist/components/features/mcp-page/marketplace-card.js +6 -2
- package/dist/components/features/mcp-page/marketplace-card.js.map +1 -1
- package/dist/components/features/settings/brand-button.cjs +1 -1
- package/dist/components/features/settings/brand-button.cjs.map +1 -1
- package/dist/components/features/settings/brand-button.js +1 -1
- package/dist/components/features/settings/brand-button.js.map +1 -1
- package/dist/components/features/settings/llm-settings/openai-subscription-auth-card.cjs +2 -0
- package/dist/components/features/settings/llm-settings/openai-subscription-auth-card.cjs.map +1 -0
- package/dist/components/features/settings/llm-settings/openai-subscription-auth-card.d.ts +5 -0
- package/dist/components/features/settings/llm-settings/openai-subscription-auth-card.js +167 -0
- package/dist/components/features/settings/llm-settings/openai-subscription-auth-card.js.map +1 -0
- package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
- package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
- package/dist/components/shared/modals/settings/model-selector.d.ts +1 -2
- package/dist/components/shared/modals/settings/model-selector.js +59 -65
- package/dist/components/shared/modals/settings/model-selector.js.map +1 -1
- package/dist/components/shared/modals/settings/settings-form.cjs +1 -1
- package/dist/components/shared/modals/settings/settings-form.cjs.map +1 -1
- package/dist/components/shared/modals/settings/settings-form.js +1 -2
- package/dist/components/shared/modals/settings/settings-form.js.map +1 -1
- package/dist/config/defaults.cjs +2 -0
- package/dist/config/defaults.cjs.map +1 -0
- package/dist/config/defaults.js +35 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/constants/llm-subscription.cjs +2 -0
- package/dist/constants/llm-subscription.cjs.map +1 -0
- package/dist/constants/llm-subscription.d.ts +16 -0
- package/dist/constants/llm-subscription.js +47 -0
- package/dist/constants/llm-subscription.js.map +1 -0
- package/dist/contexts/conversation-websocket-context.cjs +1 -1
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js +1 -1
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/hooks/mutation/use-llm-subscription-auth.cjs +2 -0
- package/dist/hooks/mutation/use-llm-subscription-auth.cjs.map +1 -0
- package/dist/hooks/mutation/use-llm-subscription-auth.d.ts +3 -0
- package/dist/hooks/mutation/use-llm-subscription-auth.js +30 -0
- package/dist/hooks/mutation/use-llm-subscription-auth.js.map +1 -0
- package/dist/hooks/mutation/use-save-fields-as-secrets.cjs +1 -1
- package/dist/hooks/mutation/use-save-fields-as-secrets.cjs.map +1 -1
- package/dist/hooks/mutation/use-save-fields-as-secrets.d.ts +8 -6
- package/dist/hooks/mutation/use-save-fields-as-secrets.js +1 -1
- package/dist/hooks/mutation/use-save-fields-as-secrets.js.map +1 -1
- package/dist/hooks/mutation/use-test-mcp-server.d.ts +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 +5 -0
- package/dist/hooks/query/query-keys.js +14 -2
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-agent-settings-schema.cjs +1 -1
- package/dist/hooks/query/use-agent-settings-schema.cjs.map +1 -1
- package/dist/hooks/query/use-agent-settings-schema.d.ts +2 -2
- package/dist/hooks/query/use-agent-settings-schema.js +21 -19
- package/dist/hooks/query/use-agent-settings-schema.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 +38 -36
- package/dist/hooks/query/use-backends-health.js.map +1 -1
- package/dist/hooks/query/use-llm-subscription-models.cjs +2 -0
- package/dist/hooks/query/use-llm-subscription-models.cjs.map +1 -0
- package/dist/hooks/query/use-llm-subscription-models.d.ts +3 -0
- package/dist/hooks/query/use-llm-subscription-models.js +19 -0
- package/dist/hooks/query/use-llm-subscription-models.js.map +1 -0
- package/dist/hooks/query/use-llm-subscription-status.cjs +2 -0
- package/dist/hooks/query/use-llm-subscription-status.cjs.map +1 -0
- package/dist/hooks/query/use-llm-subscription-status.d.ts +3 -0
- package/dist/hooks/query/use-llm-subscription-status.js +19 -0
- package/dist/hooks/query/use-llm-subscription-status.js.map +1 -0
- package/dist/hooks/use-websocket.cjs +1 -1
- package/dist/hooks/use-websocket.cjs.map +1 -1
- package/dist/hooks/use-websocket.d.ts +0 -1
- package/dist/hooks/use-websocket.js +37 -38
- package/dist/hooks/use-websocket.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 +22 -0
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +2 -2
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +374 -0
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +22 -0
- package/dist/locales/ca/openhands.json +22 -0
- package/dist/locales/de/openhands.json +22 -0
- package/dist/locales/en/openhands.json +22 -0
- package/dist/locales/es/openhands.json +22 -0
- package/dist/locales/fr/openhands.json +22 -0
- package/dist/locales/it/openhands.json +22 -0
- package/dist/locales/ja/openhands.json +22 -0
- package/dist/locales/ko-KR/openhands.json +22 -0
- package/dist/locales/no/openhands.json +22 -0
- package/dist/locales/pt/openhands.json +22 -0
- package/dist/locales/tr/openhands.json +22 -0
- package/dist/locales/uk/openhands.json +22 -0
- package/dist/locales/zh-CN/openhands.json +22 -0
- package/dist/locales/zh-TW/openhands.json +22 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +10 -22
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.cjs +97 -69
- package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.js +3 -3
- package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +3 -5
- package/dist/package.js.map +1 -1
- package/dist/routes/files-tab.cjs +1 -1
- package/dist/routes/files-tab.cjs.map +1 -1
- package/dist/routes/files-tab.js +28 -17
- 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 +142 -85
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/services/canvas-ui.cjs +1 -1
- package/dist/services/canvas-ui.cjs.map +1 -1
- package/dist/services/canvas-ui.d.ts +1 -1
- package/dist/services/canvas-ui.js +2 -2
- package/dist/services/canvas-ui.js.map +1 -1
- package/dist/stores/files-tab-store.cjs +1 -1
- package/dist/stores/files-tab-store.cjs.map +1 -1
- package/dist/stores/files-tab-store.d.ts +2 -1
- package/dist/stores/files-tab-store.js +5 -1
- package/dist/stores/files-tab-store.js.map +1 -1
- package/dist/stores/use-event-store.cjs +1 -1
- package/dist/stores/use-event-store.cjs.map +1 -1
- package/dist/stores/use-event-store.js +39 -34
- package/dist/stores/use-event-store.js.map +1 -1
- package/dist/types/mcp-server.d.ts +21 -0
- package/dist/ui/dropdown/dropdown.cjs +1 -1
- package/dist/ui/dropdown/dropdown.cjs.map +1 -1
- package/dist/ui/dropdown/dropdown.js +6 -2
- package/dist/ui/dropdown/dropdown.js.map +1 -1
- package/dist/utils/handle-event-for-ui.cjs +1 -1
- package/dist/utils/handle-event-for-ui.cjs.map +1 -1
- package/dist/utils/handle-event-for-ui.d.ts +2 -0
- package/dist/utils/handle-event-for-ui.js +1 -1
- package/dist/utils/handle-event-for-ui.js.map +1 -1
- package/dist/utils/llm-subscription-schema.cjs +2 -0
- package/dist/utils/llm-subscription-schema.cjs.map +1 -0
- package/dist/utils/llm-subscription-schema.d.ts +2 -0
- package/dist/utils/llm-subscription-schema.js +22 -0
- package/dist/utils/llm-subscription-schema.js.map +1 -0
- package/dist/utils/mcp-config.cjs +1 -1
- package/dist/utils/mcp-config.cjs.map +1 -1
- package/dist/utils/mcp-config.js +32 -17
- package/dist/utils/mcp-config.js.map +1 -1
- package/dist/utils/mcp-credential-validation.cjs +2 -0
- package/dist/utils/mcp-credential-validation.cjs.map +1 -0
- package/dist/utils/mcp-credential-validation.d.ts +22 -0
- package/dist/utils/mcp-credential-validation.js +31 -0
- package/dist/utils/mcp-credential-validation.js.map +1 -0
- package/dist/utils/mcp-marketplace-utils.cjs +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
- package/dist/utils/mcp-marketplace-utils.d.ts +7 -2
- package/dist/utils/mcp-marketplace-utils.js +33 -48
- package/dist/utils/mcp-marketplace-utils.js.map +1 -1
- package/dist/utils/sdk-settings-schema.cjs +1 -1
- package/dist/utils/sdk-settings-schema.cjs.map +1 -1
- package/dist/utils/sdk-settings-schema.js +64 -61
- package/dist/utils/sdk-settings-schema.js.map +1 -1
- package/dist/utils/websocket-url.cjs +1 -1
- package/dist/utils/websocket-url.cjs.map +1 -1
- package/dist/utils/websocket-url.js +2 -2
- package/dist/utils/websocket-url.js.map +1 -1
- package/package.json +3 -5
- package/scripts/check-sdk-version-sync.mjs +9 -27
- package/scripts/dev-with-automation.mjs +1 -3
- package/scripts/docker-build.mjs +0 -4
- package/scripts/run-staged-typecheck.mjs +44 -0
- package/build/assets/QueryClientProvider-XcSjsfpb.js +0 -1
- package/build/assets/Trans-sy4l4TyQ.js +0 -1
- package/build/assets/active-backend-context-CNF2lPkA.js +0 -1
- package/build/assets/add-backend-modal-BywVr6uq.js +0 -1
- package/build/assets/agent-server-adapter-k8veH-1O.js +0 -5
- package/build/assets/agent-server-client-options-B-C8JaTb.js +0 -1
- package/build/assets/agent-server-conversation-service.api-CGbkhsLj.js +0 -1
- package/build/assets/api-key-entry-screen-Dnr5TcV0.js +0 -1
- package/build/assets/app-settings-Bgm2-yOM.js +0 -1
- package/build/assets/automation-detail-86M_yMqz.js +0 -1
- package/build/assets/automations-list-BWUILrqY.js +0 -1
- package/build/assets/backend-form-modal-Dl29wkF5.js +0 -1
- package/build/assets/browser-store-JRrcGdlk.js +0 -1
- package/build/assets/browser-wz8UzRmF.js +0 -5
- package/build/assets/chat-send-button-BhoO7T0s.js +0 -1
- package/build/assets/check-BhnsMsWy.js +0 -1
- package/build/assets/condenser-settings-DgQ0rsAf.js +0 -1
- package/build/assets/context-CI9FqkUp.js +0 -1
- package/build/assets/conversation-CayU5Lrr.js +0 -19
- package/build/assets/conversation-erinyBqT.js +0 -1
- package/build/assets/conversation-panel-DiI4q-8-.js +0 -1
- package/build/assets/conversation-service.api-shHWtFwu.js +0 -1
- package/build/assets/conversation-state-store-NEktJKfL.js +0 -1
- package/build/assets/declaration-D9ucT0fq.js +0 -1
- package/build/assets/dist-BCpEDEJq.js +0 -1
- package/build/assets/edit-automation-modal-8y9Uctxo.js +0 -1
- package/build/assets/entry.client-D_wtryHT.js +0 -2
- package/build/assets/files-tab-CxdtgkIe.js +0 -1
- package/build/assets/files-tab-store-DSKUhziI.js +0 -1
- package/build/assets/home-3joHMYSR.js +0 -1
- package/build/assets/index-redirect-BQ_55qN6.js +0 -1
- package/build/assets/install-server-modal-_7l1gcjd.js +0 -1
- package/build/assets/lesson-plan-CHGc-B8Y.js +0 -3
- package/build/assets/llm-not-configured-banner-BMGzpBPV.js +0 -27
- package/build/assets/llm-settings-BRotm_g6.js +0 -1
- package/build/assets/llm-settings-yDgbXP6Q.js +0 -1
- package/build/assets/loader-circle-1XB9nbwF.js +0 -1
- package/build/assets/manage-backends-modal-tfdzTXWU.js +0 -1
- package/build/assets/manifest-bbc1374e.js +0 -1
- package/build/assets/markdown-renderer-z446oW0Z.js +0 -2
- package/build/assets/mcp-Dopstf0t.js +0 -9
- package/build/assets/mcp-settings-redirect-l3Zbmc0F.js +0 -1
- package/build/assets/messages-CsFUrAen.js +0 -41
- package/build/assets/model-selector-sioC8xP4.js +0 -1
- package/build/assets/onboarding-CQh50i2z.js +0 -1
- package/build/assets/option-service.api-DjPvPAtd.js +0 -1
- package/build/assets/organization-service.api-BNc9Kn6n.js +0 -1
- package/build/assets/plus-DKUID4kd.js +0 -1
- package/build/assets/providers-BiWSYwRT.js +0 -1
- package/build/assets/proxy--Uy1iGsW.js +0 -1
- package/build/assets/query-client-config-Ca3tW1AH.js +0 -1
- package/build/assets/root-CRkz_h2T.css +0 -1
- package/build/assets/root-DrHpnAqU.js +0 -2
- package/build/assets/root-layout-Cf7FC9DC.js +0 -2
- package/build/assets/sdk-section-page-COlGKv4E.js +0 -1
- package/build/assets/sdk-settings-schema-Big50zDH.js +0 -1
- package/build/assets/secrets-settings-DYfTc5c8.js +0 -1
- package/build/assets/settings-DRmVFdOc.js +0 -1
- package/build/assets/settings-modal-CeRvS5Bc.js +0 -1
- package/build/assets/settings-service.api-CFt5HmXD.js +0 -1
- package/build/assets/shared-conversation-CBbpyPaD.js +0 -1
- package/build/assets/sidebar-mobile-menu-toggle-SKcwsEtD.js +0 -1
- package/build/assets/suspense-Bqb0V0q1.js +0 -1
- package/build/assets/telemetry-DCFAqpIA.js +0 -2
- package/build/assets/use-acp-credential-form-LjCIhMSK.js +0 -1
- package/build/assets/use-agent-settings-schema-D8x5LJVS.js +0 -1
- package/build/assets/use-config-5zEjywCL.js +0 -1
- package/build/assets/use-create-conversation-pV2eA-e9.js +0 -1
- package/build/assets/use-handle-plan-click-CwN_nNib.js +0 -1
- package/build/assets/use-is-authed-B8eLO-Xq.js +0 -1
- package/build/assets/use-llm-profiles-CWLfWjav.js +0 -1
- package/build/assets/use-runtime-is-ready-Bbory9-s.js +0 -1
- package/build/assets/use-save-settings-Xp8DD-jf.js +0 -1
- package/build/assets/use-settings-0SeqaDeW.js +0 -1
- package/build/assets/useMutation-Dm84WAKR.js +0 -1
- package/build/assets/useQuery-DGRSm7IT.js +0 -1
- package/build/assets/useTranslation-CL6FTf1b.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~dqseey1n-D_BSEDk4.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~jfbjdnyv-C5ZIbuq8.js +0 -177
- package/build/assets/vendor~root-layout~home~conversation-panel~conversation~launch~mcp~settings~settings-index~~m3acswdn-CGm-Jxp5.js +0 -48
- package/build/assets/x-CCfDppg5.js +0 -1
- package/dist/api/settings-service/legacy-app-preferences-migration.cjs +0 -2
- package/dist/api/settings-service/legacy-app-preferences-migration.cjs.map +0 -1
- package/dist/api/settings-service/legacy-app-preferences-migration.d.ts +0 -34
- package/dist/api/settings-service/legacy-app-preferences-migration.js +0 -52
- package/dist/api/settings-service/legacy-app-preferences-migration.js.map +0 -1
- package/dist/hooks/query/use-openhands-verified-models.cjs +0 -2
- package/dist/hooks/query/use-openhands-verified-models.cjs.map +0 -1
- package/dist/hooks/query/use-openhands-verified-models.d.ts +0 -1
- package/dist/hooks/query/use-openhands-verified-models.js +0 -14
- package/dist/hooks/query/use-openhands-verified-models.js.map +0 -1
- package/dist/utils/normalize-display-model.cjs +0 -2
- package/dist/utils/normalize-display-model.cjs.map +0 -1
- package/dist/utils/normalize-display-model.d.ts +0 -9
- package/dist/utils/normalize-display-model.js +0 -13
- package/dist/utils/normalize-display-model.js.map +0 -1
- package/dist/utils/openhands-llm.cjs +0 -2
- package/dist/utils/openhands-llm.cjs.map +0 -1
- package/dist/utils/openhands-llm.d.ts +0 -15
- package/dist/utils/openhands-llm.js +0 -15
- package/dist/utils/openhands-llm.js.map +0 -1
- /package/build/assets/{agent-server-ui-style-scope-BwIZYdC1.js → agent-server-ui-style-scope-1MuaCC1k.js} +0 -0
- /package/build/assets/{common-Dh7OqABE.js → common-DqjLSBOt.js} +0 -0
- /package/build/assets/{environment-switch-store-CiurvTtK.js → environment-switch-store-CBXkf5bS.js} +0 -0
- /package/build/assets/{extension-module-card-classes-DP5J6ngE.js → extension-module-card-classes-CVGfXtoL.js} +0 -0
- /package/build/assets/{git-status-mapper-BI8FyUVp.js → git-status-mapper-DVFXF1_X.js} +0 -0
- /package/build/assets/{handle-capture-consent-CPMXU29K.js → handle-capture-consent-BTvatyfE.js} +0 -0
- /package/build/assets/{map-provider-BM2SJarp.js → map-provider-COgsZR9p.js} +0 -0
- /package/build/assets/{objectWithoutPropertiesLoose-DSQKyRhw.js → objectWithoutPropertiesLoose-B80nTzVc.js} +0 -0
- /package/build/assets/{preload-helper-CT1Z6Pdu.js → preload-helper-D_sPnjeL.js} +0 -0
- /package/build/assets/{rolldown-runtime-BFRubm34.js → rolldown-runtime-wFmyQBCi.js} +0 -0
- /package/build/assets/{sdk-settings-field-metadata-p2GVlft7.js → sdk-settings-field-metadata-Cc4D-ut7.js} +0 -0
- /package/build/assets/{settings-wh2sLLJM.js → settings-1287uR2J.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~nh19ovoo-DJTFnsA1.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~cg1m3bv7-aUIHudsf.js} +0 -0
- /package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~ntycl9e1-BmZcy_kH.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~ntycl9e1-DPPGSgT1.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-settings.cjs","names":[],"sources":["../../src/routes/llm-settings.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModelSelector } from \"#/components/shared/modals/settings/model-selector\";\nimport { useAgentSettingsSchema } from \"#/hooks/query/use-agent-settings-schema\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { KeyStatusIcon } from \"#/components/features/settings/key-status-icon\";\nimport {\n SdkSectionHeaderProps,\n SdkSectionPage,\n SdkSectionSaveControl,\n} from \"#/components/features/settings/sdk-settings/sdk-section-page\";\nimport { LlmSettingsLocalView } from \"#/components/features/settings/llm-profiles\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { Settings, SettingsSchema, SettingsScope } from \"#/types/settings\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport {\n inferInitialView,\n type SettingsFormValues,\n type SettingsView,\n} from \"#/utils/sdk-settings-schema\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport {\n OPENHANDS_LLM_PROXY_BASE_URL,\n isOpenHandsProxyModel,\n} from \"#/utils/openhands-llm\";\n\nconst LLM_EXCLUDED_KEYS = new Set([\"llm.model\", \"llm.api_key\", \"llm.base_url\"]);\n\nconst buildModelId = (provider: string | null, model: string | null) => {\n if (!provider || !model) return null;\n return `${provider}/${model}`;\n};\n\nconst getSchemaFieldDefaultValue = (\n schema: SettingsSchema | null | undefined,\n fieldKey: string,\n) =>\n schema?.sections\n .flatMap((section) => section.fields)\n .find((field) => field.key === fieldKey)?.default ?? null;\n\nconst KNOWN_PROVIDER_DEFAULT_BASE_URLS: Partial<Record<string, Set<string>>> = {\n openai: new Set([\"https://api.openai.com\", \"https://api.openai.com/v1\"]),\n openhands: new Set([\n OPENHANDS_LLM_PROXY_BASE_URL,\n \"https://llm-proxy.app.all-hands.dev/v1\",\n ]),\n litellm_proxy: new Set([\n OPENHANDS_LLM_PROXY_BASE_URL,\n \"https://llm-proxy.app.all-hands.dev/v1\",\n ]),\n};\n\nconst normalizeBaseUrl = (baseUrl: string) => {\n try {\n const parsedUrl = new URL(baseUrl);\n const normalizedPath = parsedUrl.pathname.replace(/\\/+$/, \"\") || \"\";\n return `${parsedUrl.origin}${normalizedPath}`;\n } catch {\n return baseUrl.trim().replace(/\\/+$/, \"\");\n }\n};\n\nconst isProviderDefaultBaseUrl = (model: string, baseUrl: string) => {\n const normalizedBaseUrl = normalizeBaseUrl(baseUrl);\n const { provider } = extractModelAndProvider(model);\n\n if (provider) {\n const knownDefaults = KNOWN_PROVIDER_DEFAULT_BASE_URLS[provider];\n if (knownDefaults) {\n return knownDefaults.has(normalizedBaseUrl);\n }\n }\n\n return Object.values(KNOWN_PROVIDER_DEFAULT_BASE_URLS).some((knownDefaults) =>\n knownDefaults?.has(normalizedBaseUrl),\n );\n};\n\ninterface OpenHandsApiKeyHelpProps {\n testId: string;\n}\n\nfunction OpenHandsApiKeyHelp({ testId }: OpenHandsApiKeyHelpProps) {\n const { t } = useTranslation(\"openhands\");\n\n return (\n <HelpLink\n testId={testId}\n text={t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT)}\n linkText={t(I18nKey.SETTINGS$NAV_API_KEYS)}\n href=\"https://app.all-hands.dev/settings/api-keys\"\n suffix={` ${t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`}\n />\n );\n}\n\nexport function LlmSettingsScreen({\n scope = \"personal\",\n onSaveSuccess,\n initialValueOverrides,\n embedded,\n hideSaveButton,\n suppressSuccessToast,\n onSaveControlChange,\n}: {\n scope?: SettingsScope;\n /** Optional hook fired after a successful save (e.g. advance an onboarding step). */\n onSaveSuccess?: () => void;\n /** Forwarded to {@link SdkSectionPage}. */\n initialValueOverrides?: SettingsFormValues;\n /** Forwarded to {@link SdkSectionPage}. */\n embedded?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n hideSaveButton?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n suppressSuccessToast?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n onSaveControlChange?: (control: SdkSectionSaveControl) => void;\n}) {\n const { t } = useTranslation(\"openhands\");\n\n const { data: settings } = useSettings(scope);\n const { data: schema } = useAgentSettingsSchema(\n settings?.agent_settings_schema,\n );\n\n const defaultModel = String(\n (DEFAULT_SETTINGS.agent_settings?.llm as Record<string, unknown>)?.model ??\n \"\",\n );\n\n const getInitialView = React.useCallback(\n (\n currentSettings: Settings,\n filteredSchema: SettingsSchema,\n ): SettingsView => {\n const schemaView = inferInitialView(currentSettings, filteredSchema);\n if (schemaView !== \"basic\") {\n return schemaView;\n }\n\n const currentModel = currentSettings.llm_model ?? \"\";\n const trimmedBaseUrl = currentSettings.llm_base_url?.trim() ?? \"\";\n const hasCustomBaseUrl =\n trimmedBaseUrl.length > 0 &&\n !isProviderDefaultBaseUrl(currentModel, trimmedBaseUrl);\n\n return hasCustomBaseUrl ? \"all\" : \"basic\";\n },\n [],\n );\n\n const buildHeader = React.useCallback(\n ({ values, isDisabled, view, onChange }: SdkSectionHeaderProps) => {\n const modelValue =\n typeof values[\"llm.model\"] === \"string\" ? values[\"llm.model\"] : \"\";\n const baseUrlValue =\n typeof values[\"llm.base_url\"] === \"string\"\n ? values[\"llm.base_url\"]\n : \"\";\n const showOpenHandsApiKeyHelp = modelValue.startsWith(\"openhands/\");\n\n const apiKeyValue =\n typeof values[\"llm.api_key\"] === \"string\" ? values[\"llm.api_key\"] : \"\";\n // For embedded profile forms (create/edit) the global\n // `llm_api_key_set` flag is misleading: a brand-new profile would show a\n // \"key set\" indicator just because some other profile has a key. Reflect\n // the form's own key state instead so create mode starts visibly unset.\n const apiKeyIsSet = embedded\n ? apiKeyValue.length > 0\n : Boolean(settings?.llm_api_key_set);\n\n const renderApiKeyInput = (testId: string, helpTestId: string) => (\n <>\n <SettingsInput\n testId={testId}\n label={t(I18nKey.SETTINGS_FORM$API_KEY)}\n type=\"password\"\n className=\"w-full\"\n value={apiKeyValue}\n placeholder={apiKeyIsSet ? \"<hidden>\" : \"\"}\n onChange={(value) => onChange(\"llm.api_key\", value)}\n isDisabled={isDisabled}\n startContent={\n apiKeyIsSet ? <KeyStatusIcon isSet={apiKeyIsSet} /> : undefined\n }\n />\n\n <HelpLink\n testId={helpTestId}\n text={t(I18nKey.SETTINGS$DONT_KNOW_API_KEY)}\n linkText={t(I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS)}\n href=\"https://docs.openhands.dev/usage/local-setup#getting-an-api-key\"\n />\n </>\n );\n\n return (\n <div className=\"flex flex-col gap-6\">\n {view === \"basic\" ? (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-basic\"\n >\n <ModelSelector\n currentModel={modelValue || undefined}\n currentBaseUrl={baseUrlValue || undefined}\n onChange={(provider, model) => {\n const nextModel = buildModelId(provider, model);\n if (nextModel) {\n onChange(\"llm.model\", nextModel);\n }\n }}\n wrapperClassName=\"!flex-col !gap-6\"\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help\" />\n ) : null}\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor\",\n )}\n </div>\n ) : (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-advanced\"\n >\n <SettingsInput\n testId=\"llm-custom-model-input\"\n label={t(I18nKey.SETTINGS$CUSTOM_MODEL)}\n type=\"text\"\n className=\"w-full\"\n value={modelValue}\n placeholder={defaultModel}\n onChange={(value) => onChange(\"llm.model\", value)}\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help-2\" />\n ) : null}\n\n <SettingsInput\n testId=\"base-url-input\"\n label={t(I18nKey.SETTINGS$BASE_URL)}\n type=\"text\"\n className=\"w-full\"\n value={baseUrlValue}\n placeholder=\"https://api.openai.com\"\n onChange={(value) => onChange(\"llm.base_url\", value)}\n isDisabled={isDisabled}\n />\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor-advanced\",\n )}\n </div>\n )}\n </div>\n );\n },\n [defaultModel, embedded, settings?.llm_api_key_set, t],\n );\n\n const buildPayload = React.useCallback(\n (\n defaultPayload: Record<string, unknown>,\n context: {\n values: Record<string, string | boolean>;\n view: SettingsView;\n },\n ) => {\n // defaultPayload is the wrapped diff (e.g.\n // `{ agent_settings_diff: { llm: { model: \"gpt-4\" } } }`); we only\n // mutate the inner `llm` object below.\n const agentSettings = structuredClone(\n (defaultPayload.agent_settings_diff as Record<string, unknown>) ?? {},\n );\n\n const llm = (agentSettings.llm ?? {}) as Record<string, unknown>;\n\n if (context.view === \"basic\") {\n const model = llm.model ?? context.values[\"llm.model\"];\n const baseUrl = llm.base_url ?? context.values[\"llm.base_url\"];\n llm.base_url = isOpenHandsProxyModel(model, baseUrl)\n ? OPENHANDS_LLM_PROXY_BASE_URL\n : getSchemaFieldDefaultValue(schema, \"llm.base_url\");\n agentSettings.llm = llm;\n }\n\n return { agent_settings_diff: agentSettings };\n },\n [schema],\n );\n\n return (\n <SdkSectionPage\n scope={scope}\n settingsSources={[\n {\n settingsSource: \"agent_settings\",\n sectionKeys: [\"llm\"],\n excludeKeys: LLM_EXCLUDED_KEYS,\n },\n ]}\n header={buildHeader}\n buildPayload={buildPayload}\n getInitialView={getInitialView}\n forceShowAdvancedView\n allowAllView\n onSaveSuccess={onSaveSuccess}\n initialValueOverrides={initialValueOverrides}\n embedded={embedded}\n hideSaveButton={hideSaveButton}\n suppressSuccessToast={suppressSuccessToast}\n onSaveControlChange={onSaveControlChange}\n testId=\"llm-settings-screen\"\n />\n );\n}\n\n/**\n * Default export for the route renders different views based on backend type:\n * - Local backends: LlmSettingsLocalView with profile management\n * - Cloud backends: Standard LlmSettingsScreen (profiles are not supported)\n *\n * The LlmSettingsScreen component is also exported for embedded use cases\n * (e.g., onboarding, profile editing forms).\n *\n * Note: This is a route file, only the router should import the default export.\n * Other consumers should use the named export `LlmSettingsScreen` for embedded\n * use cases.\n */\nexport default function LlmSettingsRoute() {\n const { backend } = useActiveBackend();\n const isCloud = backend.kind === \"cloud\";\n\n // Cloud backends use the standard LLM settings form (no profiles support)\n if (isCloud) {\n return <LlmSettingsScreen />;\n }\n\n // Local backends use the profile management view\n return <LlmSettingsLocalView />;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"llm-settings.cjs","names":[],"sources":["../../src/routes/llm-settings.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModelSelector } from \"#/components/shared/modals/settings/model-selector\";\nimport { useAgentSettingsSchema } from \"#/hooks/query/use-agent-settings-schema\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { SettingsDropdownInput } from \"#/components/features/settings/settings-dropdown-input\";\nimport { OpenAISubscriptionAuthCard } from \"#/components/features/settings/llm-settings/openai-subscription-auth-card\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { KeyStatusIcon } from \"#/components/features/settings/key-status-icon\";\nimport {\n SdkSectionHeaderProps,\n SdkSectionPage,\n SdkSectionSaveControl,\n} from \"#/components/features/settings/sdk-settings/sdk-section-page\";\nimport { LlmSettingsLocalView } from \"#/components/features/settings/llm-profiles\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { Settings, SettingsSchema, SettingsScope } from \"#/types/settings\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport {\n inferInitialView,\n type SettingsFormValues,\n type SettingsView,\n} from \"#/utils/sdk-settings-schema\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport {\n LLM_AUTH_TYPE_API_KEY,\n LLM_AUTH_TYPE_KEY,\n LLM_AUTH_TYPE_SUBSCRIPTION,\n LLM_SUBSCRIPTION_VENDOR_KEY,\n OPENAI_SUBSCRIPTION_VENDOR,\n resolveLlmAuthType,\n} from \"#/constants/llm-subscription\";\nimport { useOpenAISubscriptionModels } from \"#/hooks/query/use-llm-subscription-models\";\n\nconst LLM_EXCLUDED_KEYS = new Set([\n \"llm.model\",\n \"llm.api_key\",\n \"llm.base_url\",\n LLM_AUTH_TYPE_KEY,\n LLM_SUBSCRIPTION_VENDOR_KEY,\n]);\n\nconst buildModelId = (provider: string | null, model: string | null) => {\n if (!provider || !model) return null;\n return `${provider}/${model}`;\n};\n\nconst getSchemaFieldDefaultValue = (\n schema: SettingsSchema | null | undefined,\n fieldKey: string,\n) =>\n schema?.sections\n .flatMap((section) => section.fields)\n .find((field) => field.key === fieldKey)?.default ?? null;\n\nconst KNOWN_PROVIDER_DEFAULT_BASE_URLS: Partial<Record<string, Set<string>>> = {\n openai: new Set([\"https://api.openai.com\", \"https://api.openai.com/v1\"]),\n};\n\nconst normalizeBaseUrl = (baseUrl: string) => {\n try {\n const parsedUrl = new URL(baseUrl);\n const normalizedPath = parsedUrl.pathname.replace(/\\/+$/, \"\") || \"\";\n return `${parsedUrl.origin}${normalizedPath}`;\n } catch {\n return baseUrl.trim().replace(/\\/+$/, \"\");\n }\n};\n\nconst isProviderDefaultBaseUrl = (model: string, baseUrl: string) => {\n const normalizedBaseUrl = normalizeBaseUrl(baseUrl);\n const { provider } = extractModelAndProvider(model);\n\n if (provider) {\n const knownDefaults = KNOWN_PROVIDER_DEFAULT_BASE_URLS[provider];\n if (knownDefaults) {\n return knownDefaults.has(normalizedBaseUrl);\n }\n }\n\n return Object.values(KNOWN_PROVIDER_DEFAULT_BASE_URLS).some((knownDefaults) =>\n knownDefaults?.has(normalizedBaseUrl),\n );\n};\n\ninterface OpenHandsApiKeyHelpProps {\n testId: string;\n}\n\nfunction OpenHandsApiKeyHelp({ testId }: OpenHandsApiKeyHelpProps) {\n const { t } = useTranslation(\"openhands\");\n\n return (\n <HelpLink\n testId={testId}\n text={t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT)}\n linkText={t(I18nKey.SETTINGS$NAV_API_KEYS)}\n href=\"https://app.all-hands.dev/settings/api-keys\"\n suffix={` ${t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`}\n />\n );\n}\n\nexport function LlmSettingsScreen({\n scope = \"personal\",\n onSaveSuccess,\n initialValueOverrides,\n embedded,\n hideSaveButton,\n suppressSuccessToast,\n onSaveControlChange,\n}: {\n scope?: SettingsScope;\n /** Optional hook fired after a successful save (e.g. advance an onboarding step). */\n onSaveSuccess?: () => void;\n /** Forwarded to {@link SdkSectionPage}. */\n initialValueOverrides?: SettingsFormValues;\n /** Forwarded to {@link SdkSectionPage}. */\n embedded?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n hideSaveButton?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n suppressSuccessToast?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n onSaveControlChange?: (control: SdkSectionSaveControl) => void;\n}) {\n const { t } = useTranslation(\"openhands\");\n\n const { data: settings } = useSettings(scope);\n const { data: schema } = useAgentSettingsSchema(\n settings?.agent_settings_schema,\n );\n const persistedLlmSettings = settings?.agent_settings?.llm as\n | Record<string, unknown>\n | undefined;\n const initialAuthType = resolveLlmAuthType(\n initialValueOverrides?.[LLM_AUTH_TYPE_KEY] ??\n persistedLlmSettings?.auth_type,\n );\n const [enableSubscriptionModels, setEnableSubscriptionModels] =\n React.useState(initialAuthType === LLM_AUTH_TYPE_SUBSCRIPTION);\n const {\n data: subscriptionModels,\n isLoading: isSubscriptionModelsLoading,\n isFetching: isSubscriptionModelsFetching,\n } = useOpenAISubscriptionModels({ enabled: enableSubscriptionModels });\n const isWaitingForSubscriptionModels =\n enableSubscriptionModels &&\n !subscriptionModels &&\n (isSubscriptionModelsLoading || isSubscriptionModelsFetching);\n const lastApiKeyModelRef = React.useRef<string | null>(null);\n const lastSubscriptionModelRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n if (initialAuthType === LLM_AUTH_TYPE_SUBSCRIPTION) {\n setEnableSubscriptionModels(true);\n }\n }, [initialAuthType]);\n\n const defaultModel = String(\n (DEFAULT_SETTINGS.agent_settings?.llm as Record<string, unknown>)?.model ??\n \"\",\n );\n\n const getInitialView = React.useCallback(\n (\n currentSettings: Settings,\n filteredSchema: SettingsSchema,\n ): SettingsView => {\n const schemaView = inferInitialView(currentSettings, filteredSchema);\n if (schemaView !== \"basic\") {\n return schemaView;\n }\n\n const currentModel = currentSettings.llm_model ?? \"\";\n const trimmedBaseUrl = currentSettings.llm_base_url?.trim() ?? \"\";\n const hasCustomBaseUrl =\n trimmedBaseUrl.length > 0 &&\n !isProviderDefaultBaseUrl(currentModel, trimmedBaseUrl);\n\n return hasCustomBaseUrl ? \"all\" : \"basic\";\n },\n [],\n );\n\n const buildHeader = React.useCallback(\n ({ values, isDisabled, view, onChange }: SdkSectionHeaderProps) => {\n const modelValue =\n typeof values[\"llm.model\"] === \"string\" ? values[\"llm.model\"] : \"\";\n const baseUrlValue =\n typeof values[\"llm.base_url\"] === \"string\"\n ? values[\"llm.base_url\"]\n : \"\";\n const showOpenHandsApiKeyHelp = modelValue.startsWith(\"openhands/\");\n const authType = resolveLlmAuthType(values[LLM_AUTH_TYPE_KEY]);\n const isSubscriptionAuth = authType === LLM_AUTH_TYPE_SUBSCRIPTION;\n const shouldDisableSubscriptionControls =\n isDisabled || (isSubscriptionAuth && isWaitingForSubscriptionModels);\n const subscriptionModelValue = subscriptionModels?.includes(modelValue)\n ? modelValue\n : (subscriptionModels?.[0] ?? \"\");\n\n const apiKeyValue =\n typeof values[\"llm.api_key\"] === \"string\" ? values[\"llm.api_key\"] : \"\";\n // For embedded profile forms (create/edit) the global\n // `llm_api_key_set` flag is misleading: a brand-new profile would show a\n // \"key set\" indicator just because some other profile has a key. Reflect\n // the form's own key state instead so create mode starts visibly unset.\n const apiKeyIsSet = embedded\n ? apiKeyValue.length > 0\n : Boolean(settings?.llm_api_key_set);\n\n const renderApiKeyInput = (testId: string, helpTestId: string) => (\n <>\n <SettingsInput\n testId={testId}\n label={t(I18nKey.SETTINGS_FORM$API_KEY)}\n type=\"password\"\n className=\"w-full\"\n value={apiKeyValue}\n placeholder={apiKeyIsSet ? \"<hidden>\" : \"\"}\n onChange={(value) => onChange(\"llm.api_key\", value)}\n isDisabled={isDisabled}\n startContent={\n apiKeyIsSet ? <KeyStatusIcon isSet={apiKeyIsSet} /> : undefined\n }\n />\n\n <HelpLink\n testId={helpTestId}\n text={t(I18nKey.SETTINGS$DONT_KNOW_API_KEY)}\n linkText={t(I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS)}\n href=\"https://docs.openhands.dev/usage/local-setup#getting-an-api-key\"\n />\n </>\n );\n\n const handleAuthTypeChange = (selectedKey: React.Key | null) => {\n const nextAuthType =\n selectedKey === LLM_AUTH_TYPE_SUBSCRIPTION\n ? LLM_AUTH_TYPE_SUBSCRIPTION\n : LLM_AUTH_TYPE_API_KEY;\n onChange(LLM_AUTH_TYPE_KEY, nextAuthType);\n\n if (nextAuthType === LLM_AUTH_TYPE_SUBSCRIPTION) {\n setEnableSubscriptionModels(true);\n if (modelValue && !subscriptionModels?.includes(modelValue)) {\n lastApiKeyModelRef.current = modelValue;\n }\n const restoredSubscriptionModel =\n lastSubscriptionModelRef.current &&\n subscriptionModels?.includes(lastSubscriptionModelRef.current)\n ? lastSubscriptionModelRef.current\n : subscriptionModels?.[0];\n onChange(LLM_SUBSCRIPTION_VENDOR_KEY, OPENAI_SUBSCRIPTION_VENDOR);\n if (\n !subscriptionModels?.includes(modelValue) &&\n restoredSubscriptionModel\n ) {\n onChange(\"llm.model\", restoredSubscriptionModel);\n }\n return;\n }\n\n if (modelValue && subscriptionModels?.includes(modelValue)) {\n lastSubscriptionModelRef.current = modelValue;\n onChange(\"llm.model\", lastApiKeyModelRef.current ?? defaultModel);\n }\n };\n\n const renderAuthTypeInput = () => (\n <SettingsDropdownInput\n testId=\"llm-auth-type-input\"\n name={LLM_AUTH_TYPE_KEY}\n label={t(I18nKey.SETTINGS$LLM_AUTH_TYPE)}\n items={[\n {\n key: LLM_AUTH_TYPE_API_KEY,\n label: t(I18nKey.SETTINGS$LLM_AUTH_TYPE_API_KEY),\n },\n {\n key: LLM_AUTH_TYPE_SUBSCRIPTION,\n label: t(I18nKey.SETTINGS$LLM_AUTH_TYPE_SUBSCRIPTION),\n },\n ]}\n selectedKey={authType}\n isClearable={false}\n required\n isDisabled={shouldDisableSubscriptionControls}\n onSelectionChange={handleAuthTypeChange}\n />\n );\n\n const renderSubscriptionSettings = () => (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-subscription-settings\"\n >\n <SettingsDropdownInput\n testId=\"llm-subscription-model-input\"\n name=\"llm.subscription_model\"\n label={t(I18nKey.SETTINGS$SUBSCRIPTION_MODEL)}\n items={(subscriptionModels ?? []).map((model) => ({\n key: model,\n label: model,\n }))}\n selectedKey={subscriptionModelValue}\n isClearable={false}\n required\n isDisabled={\n shouldDisableSubscriptionControls || !subscriptionModels?.length\n }\n onSelectionChange={(selectedKey) => {\n const nextModel =\n typeof selectedKey === \"string\"\n ? selectedKey\n : subscriptionModels?.[0];\n if (nextModel) {\n onChange(\"llm.model\", nextModel);\n }\n }}\n />\n <OpenAISubscriptionAuthCard isDisabled={isDisabled} />\n </div>\n );\n\n return (\n <div className=\"flex flex-col gap-6\">\n {view === \"basic\" ? (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-basic\"\n >\n {renderAuthTypeInput()}\n\n {isSubscriptionAuth ? (\n renderSubscriptionSettings()\n ) : (\n <>\n <ModelSelector\n currentModel={modelValue || undefined}\n onChange={(provider, model) => {\n const nextModel = buildModelId(provider, model);\n if (nextModel) {\n onChange(\"llm.model\", nextModel);\n }\n }}\n wrapperClassName=\"!flex-col !gap-6\"\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help\" />\n ) : null}\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor\",\n )}\n </>\n )}\n </div>\n ) : (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-advanced\"\n >\n {renderAuthTypeInput()}\n\n {isSubscriptionAuth ? (\n renderSubscriptionSettings()\n ) : (\n <>\n <SettingsInput\n testId=\"llm-custom-model-input\"\n label={t(I18nKey.SETTINGS$CUSTOM_MODEL)}\n type=\"text\"\n className=\"w-full\"\n value={modelValue}\n placeholder={defaultModel}\n onChange={(value) => onChange(\"llm.model\", value)}\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help-2\" />\n ) : null}\n\n <SettingsInput\n testId=\"base-url-input\"\n label={t(I18nKey.SETTINGS$BASE_URL)}\n type=\"text\"\n className=\"w-full\"\n value={baseUrlValue}\n placeholder=\"https://api.openai.com\"\n onChange={(value) => onChange(\"llm.base_url\", value)}\n isDisabled={isDisabled}\n />\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor-advanced\",\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n },\n [\n defaultModel,\n embedded,\n isWaitingForSubscriptionModels,\n settings?.llm_api_key_set,\n subscriptionModels,\n t,\n ],\n );\n\n const buildPayload = React.useCallback(\n (\n defaultPayload: Record<string, unknown>,\n context: {\n values: Record<string, string | boolean>;\n dirty: Record<string, boolean>;\n view: SettingsView;\n },\n ) => {\n // defaultPayload is the wrapped diff (e.g.\n // `{ agent_settings_diff: { llm: { model: \"gpt-4\" } } }`); we only\n // mutate the inner `llm` object below.\n const agentSettings = structuredClone(\n (defaultPayload.agent_settings_diff as Record<string, unknown>) ?? {},\n );\n const llm = (agentSettings.llm ?? {}) as Record<string, unknown>;\n const authType = resolveLlmAuthType(context.values[LLM_AUTH_TYPE_KEY]);\n\n if (authType === LLM_AUTH_TYPE_SUBSCRIPTION) {\n llm.auth_type = LLM_AUTH_TYPE_SUBSCRIPTION;\n llm.subscription_vendor = OPENAI_SUBSCRIPTION_VENDOR;\n const model =\n typeof llm.model === \"string\"\n ? llm.model\n : String(context.values[\"llm.model\"] ?? \"\");\n const fallbackSubscriptionModel = subscriptionModels?.[0];\n if (\n !subscriptionModels?.includes(model) &&\n !fallbackSubscriptionModel\n ) {\n throw new Error(\"Subscription models are not loaded yet.\");\n }\n llm.model = subscriptionModels?.includes(model)\n ? model\n : fallbackSubscriptionModel;\n delete llm.api_key;\n delete llm.base_url;\n } else {\n if (context.dirty[LLM_AUTH_TYPE_KEY]) {\n llm.auth_type = LLM_AUTH_TYPE_API_KEY;\n llm.subscription_vendor = null;\n }\n if (context.view === \"basic\" && llm.model !== undefined) {\n llm.base_url = getSchemaFieldDefaultValue(schema, \"llm.base_url\");\n }\n }\n\n agentSettings.llm = llm;\n return { agent_settings_diff: agentSettings };\n },\n [schema, subscriptionModels],\n );\n\n return (\n <SdkSectionPage\n scope={scope}\n settingsSources={[\n {\n settingsSource: \"agent_settings\",\n sectionKeys: [\"llm\"],\n excludeKeys: LLM_EXCLUDED_KEYS,\n },\n ]}\n header={buildHeader}\n buildPayload={buildPayload}\n getInitialView={getInitialView}\n forceShowAdvancedView\n allowAllView\n onSaveSuccess={onSaveSuccess}\n initialValueOverrides={initialValueOverrides}\n embedded={embedded}\n hideSaveButton={hideSaveButton}\n suppressSuccessToast={suppressSuccessToast}\n onSaveControlChange={onSaveControlChange}\n testId=\"llm-settings-screen\"\n />\n );\n}\n\n/**\n * Default export for the route renders different views based on backend type:\n * - Local backends: LlmSettingsLocalView with profile management\n * - Cloud backends: Standard LlmSettingsScreen (profiles are not supported)\n *\n * The LlmSettingsScreen component is also exported for embedded use cases\n * (e.g., onboarding, profile editing forms).\n *\n * Note: This is a route file, only the router should import the default export.\n * Other consumers should use the named export `LlmSettingsScreen` for embedded\n * use cases.\n */\nexport default function LlmSettingsRoute() {\n const { backend } = useActiveBackend();\n const isCloud = backend.kind === \"cloud\";\n\n // Cloud backends use the standard LLM settings form (no profiles support)\n if (isCloud) {\n return <LlmSettingsScreen />;\n }\n\n // Local backends use the profile management view\n return <LlmSettingsLocalView />;\n}\n"],"mappings":"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"}
|
|
@@ -2,46 +2,47 @@ import { useTranslation as e } from "../node_modules/react-i18next/dist/es/useTr
|
|
|
2
2
|
import { I18nKey as t } from "../i18n/declaration.js";
|
|
3
3
|
import "../contexts/active-backend-context.js";
|
|
4
4
|
import { DEFAULT_SETTINGS as n } from "../services/settings.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
5
|
+
import { LLM_AUTH_TYPE_API_KEY as r, LLM_AUTH_TYPE_KEY as i, LLM_AUTH_TYPE_SUBSCRIPTION as a, LLM_SUBSCRIPTION_VENDOR_KEY as o, OPENAI_SUBSCRIPTION_VENDOR as s, resolveLlmAuthType as c } from "../constants/llm-subscription.js";
|
|
6
|
+
import { useSettings as l } from "../hooks/query/use-settings.js";
|
|
7
|
+
import { SettingsInput as u } from "../components/features/settings/settings-input.js";
|
|
8
|
+
import { SettingsDropdownInput as d } from "../components/features/settings/settings-dropdown-input.js";
|
|
9
|
+
import { extractModelAndProvider as f } from "../utils/extract-model-and-provider.js";
|
|
10
|
+
import { HelpLink as p } from "../ui/help-link.js";
|
|
11
|
+
import { ModelSelector as m } from "../components/shared/modals/settings/model-selector.js";
|
|
12
|
+
import { useAgentSettingsSchema as h } from "../hooks/query/use-agent-settings-schema.js";
|
|
13
|
+
import { OpenAISubscriptionAuthCard as g } from "../components/features/settings/llm-settings/openai-subscription-auth-card.js";
|
|
14
|
+
import { KeyStatusIcon as _ } from "../components/features/settings/key-status-icon.js";
|
|
15
|
+
import { inferInitialView as v } from "../utils/sdk-settings-schema.js";
|
|
16
|
+
import { SdkSectionPage as y } from "../components/features/settings/sdk-settings/sdk-section-page.js";
|
|
15
17
|
import "../components/features/settings/llm-profiles/index.js";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
+
import { useOpenAISubscriptionModels as b } from "../hooks/query/use-llm-subscription-models.js";
|
|
19
|
+
import x from "react";
|
|
20
|
+
import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
18
21
|
//#region src/routes/llm-settings.tsx
|
|
19
|
-
var
|
|
22
|
+
var T = new Set([
|
|
20
23
|
"llm.model",
|
|
21
24
|
"llm.api_key",
|
|
22
|
-
"llm.base_url"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
litellm_proxy: new Set([s, "https://llm-proxy.app.all-hands.dev/v1"])
|
|
27
|
-
}, S = (e) => {
|
|
25
|
+
"llm.base_url",
|
|
26
|
+
i,
|
|
27
|
+
o
|
|
28
|
+
]), E = (e, t) => !e || !t ? null : `${e}/${t}`, D = (e, t) => e?.sections.flatMap((e) => e.fields).find((e) => e.key === t)?.default ?? null, O = { openai: new Set(["https://api.openai.com", "https://api.openai.com/v1"]) }, k = (e) => {
|
|
28
29
|
try {
|
|
29
30
|
let t = new URL(e), n = t.pathname.replace(/\/+$/, "") || "";
|
|
30
31
|
return `${t.origin}${n}`;
|
|
31
32
|
} catch {
|
|
32
33
|
return e.trim().replace(/\/+$/, "");
|
|
33
34
|
}
|
|
34
|
-
},
|
|
35
|
-
let n =
|
|
35
|
+
}, A = (e, t) => {
|
|
36
|
+
let n = k(t), { provider: r } = f(e);
|
|
36
37
|
if (r) {
|
|
37
|
-
let e =
|
|
38
|
+
let e = O[r];
|
|
38
39
|
if (e) return e.has(n);
|
|
39
40
|
}
|
|
40
|
-
return Object.values(
|
|
41
|
+
return Object.values(O).some((e) => e?.has(n));
|
|
41
42
|
};
|
|
42
|
-
function
|
|
43
|
+
function j({ testId: n }) {
|
|
43
44
|
let { t: r } = e("openhands");
|
|
44
|
-
return /* @__PURE__ */
|
|
45
|
+
return /* @__PURE__ */ C(p, {
|
|
45
46
|
testId: n,
|
|
46
47
|
text: r(t.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT),
|
|
47
48
|
linkText: r(t.SETTINGS$NAV_API_KEYS),
|
|
@@ -49,108 +50,164 @@ function w({ testId: n }) {
|
|
|
49
50
|
suffix: ` ${r(t.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
|
-
function
|
|
53
|
-
let { t:
|
|
54
|
-
|
|
53
|
+
function M({ scope: f = "personal", onSaveSuccess: O, initialValueOverrides: k, embedded: M, hideSaveButton: N, suppressSuccessToast: P, onSaveControlChange: F }) {
|
|
54
|
+
let { t: I } = e("openhands"), { data: L } = l(f), { data: R } = h(L?.agent_settings_schema), z = L?.agent_settings?.llm, B = c(k?.["llm.auth_type"] ?? z?.auth_type), [V, H] = x.useState(B === a), { data: U, isLoading: W, isFetching: G } = b({ enabled: V }), K = V && !U && (W || G), q = x.useRef(null), J = x.useRef(null);
|
|
55
|
+
x.useEffect(() => {
|
|
56
|
+
B === "subscription" && H(!0);
|
|
57
|
+
}, [B]);
|
|
58
|
+
let Y = String(n.agent_settings?.llm?.model ?? ""), X = x.useCallback((e, t) => {
|
|
59
|
+
let n = v(e, t);
|
|
55
60
|
if (n !== "basic") return n;
|
|
56
61
|
let r = e.llm_model ?? "", i = e.llm_base_url?.trim() ?? "";
|
|
57
|
-
return i.length > 0 && !
|
|
58
|
-
}, []),
|
|
59
|
-
let
|
|
62
|
+
return i.length > 0 && !A(r, i) ? "all" : "basic";
|
|
63
|
+
}, []), Z = x.useCallback(({ values: e, isDisabled: n, view: l, onChange: f }) => {
|
|
64
|
+
let h = typeof e["llm.model"] == "string" ? e["llm.model"] : "", v = typeof e["llm.base_url"] == "string" ? e["llm.base_url"] : "", y = h.startsWith("openhands/"), b = c(e[i]), x = b === a, T = n || x && K, D = U?.includes(h) ? h : U?.[0] ?? "", O = typeof e["llm.api_key"] == "string" ? e["llm.api_key"] : "", k = M ? O.length > 0 : !!L?.llm_api_key_set, A = (e, r) => /* @__PURE__ */ w(S, { children: [/* @__PURE__ */ C(u, {
|
|
60
65
|
testId: e,
|
|
61
|
-
label:
|
|
66
|
+
label: I(t.SETTINGS_FORM$API_KEY),
|
|
62
67
|
type: "password",
|
|
63
68
|
className: "w-full",
|
|
64
|
-
value:
|
|
65
|
-
placeholder:
|
|
66
|
-
onChange: (e) =>
|
|
69
|
+
value: O,
|
|
70
|
+
placeholder: k ? "<hidden>" : "",
|
|
71
|
+
onChange: (e) => f("llm.api_key", e),
|
|
67
72
|
isDisabled: n,
|
|
68
|
-
startContent:
|
|
69
|
-
}), /* @__PURE__ */
|
|
73
|
+
startContent: k ? /* @__PURE__ */ C(_, { isSet: k }) : void 0
|
|
74
|
+
}), /* @__PURE__ */ C(p, {
|
|
70
75
|
testId: r,
|
|
71
|
-
text:
|
|
72
|
-
linkText:
|
|
76
|
+
text: I(t.SETTINGS$DONT_KNOW_API_KEY),
|
|
77
|
+
linkText: I(t.SETTINGS$CLICK_FOR_INSTRUCTIONS),
|
|
73
78
|
href: "https://docs.openhands.dev/usage/local-setup#getting-an-api-key"
|
|
74
|
-
})] })
|
|
75
|
-
|
|
79
|
+
})] }), N = (e) => {
|
|
80
|
+
let t = e === "subscription" ? a : r;
|
|
81
|
+
if (f(i, t), t === "subscription") {
|
|
82
|
+
H(!0), h && !U?.includes(h) && (q.current = h);
|
|
83
|
+
let e = J.current && U?.includes(J.current) ? J.current : U?.[0];
|
|
84
|
+
f(o, s), !U?.includes(h) && e && f("llm.model", e);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
h && U?.includes(h) && (J.current = h, f("llm.model", q.current ?? Y));
|
|
88
|
+
}, P = () => /* @__PURE__ */ C(d, {
|
|
89
|
+
testId: "llm-auth-type-input",
|
|
90
|
+
name: i,
|
|
91
|
+
label: I(t.SETTINGS$LLM_AUTH_TYPE),
|
|
92
|
+
items: [{
|
|
93
|
+
key: r,
|
|
94
|
+
label: I(t.SETTINGS$LLM_AUTH_TYPE_API_KEY)
|
|
95
|
+
}, {
|
|
96
|
+
key: a,
|
|
97
|
+
label: I(t.SETTINGS$LLM_AUTH_TYPE_SUBSCRIPTION)
|
|
98
|
+
}],
|
|
99
|
+
selectedKey: b,
|
|
100
|
+
isClearable: !1,
|
|
101
|
+
required: !0,
|
|
102
|
+
isDisabled: T,
|
|
103
|
+
onSelectionChange: N
|
|
104
|
+
}), F = () => /* @__PURE__ */ w("div", {
|
|
76
105
|
className: "flex flex-col gap-6",
|
|
77
|
-
|
|
106
|
+
"data-testid": "llm-subscription-settings",
|
|
107
|
+
children: [/* @__PURE__ */ C(d, {
|
|
108
|
+
testId: "llm-subscription-model-input",
|
|
109
|
+
name: "llm.subscription_model",
|
|
110
|
+
label: I(t.SETTINGS$SUBSCRIPTION_MODEL),
|
|
111
|
+
items: (U ?? []).map((e) => ({
|
|
112
|
+
key: e,
|
|
113
|
+
label: e
|
|
114
|
+
})),
|
|
115
|
+
selectedKey: D,
|
|
116
|
+
isClearable: !1,
|
|
117
|
+
required: !0,
|
|
118
|
+
isDisabled: T || !U?.length,
|
|
119
|
+
onSelectionChange: (e) => {
|
|
120
|
+
let t = typeof e == "string" ? e : U?.[0];
|
|
121
|
+
t && f("llm.model", t);
|
|
122
|
+
}
|
|
123
|
+
}), /* @__PURE__ */ C(g, { isDisabled: n })]
|
|
124
|
+
});
|
|
125
|
+
return /* @__PURE__ */ C("div", {
|
|
126
|
+
className: "flex flex-col gap-6",
|
|
127
|
+
children: l === "basic" ? /* @__PURE__ */ w("div", {
|
|
78
128
|
className: "flex flex-col gap-6",
|
|
79
129
|
"data-testid": "llm-settings-form-basic",
|
|
80
|
-
children: [
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
currentModel:
|
|
83
|
-
currentBaseUrl: c || void 0,
|
|
130
|
+
children: [P(), x ? F() : /* @__PURE__ */ w(S, { children: [
|
|
131
|
+
/* @__PURE__ */ C(m, {
|
|
132
|
+
currentModel: h || void 0,
|
|
84
133
|
onChange: (e, t) => {
|
|
85
|
-
let n =
|
|
86
|
-
n &&
|
|
134
|
+
let n = E(e, t);
|
|
135
|
+
n && f("llm.model", n);
|
|
87
136
|
},
|
|
88
137
|
wrapperClassName: "!flex-col !gap-6",
|
|
89
138
|
isDisabled: n
|
|
90
139
|
}),
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
]
|
|
94
|
-
}) : /* @__PURE__ */
|
|
140
|
+
y ? /* @__PURE__ */ C(j, { testId: "openhands-api-key-help" }) : null,
|
|
141
|
+
A("llm-api-key-input", "llm-api-key-help-anchor")
|
|
142
|
+
] })]
|
|
143
|
+
}) : /* @__PURE__ */ w("div", {
|
|
95
144
|
className: "flex flex-col gap-6",
|
|
96
145
|
"data-testid": "llm-settings-form-advanced",
|
|
97
|
-
children: [
|
|
98
|
-
/* @__PURE__ */
|
|
146
|
+
children: [P(), x ? F() : /* @__PURE__ */ w(S, { children: [
|
|
147
|
+
/* @__PURE__ */ C(u, {
|
|
99
148
|
testId: "llm-custom-model-input",
|
|
100
|
-
label:
|
|
149
|
+
label: I(t.SETTINGS$CUSTOM_MODEL),
|
|
101
150
|
type: "text",
|
|
102
151
|
className: "w-full",
|
|
103
|
-
value:
|
|
104
|
-
placeholder:
|
|
105
|
-
onChange: (e) =>
|
|
152
|
+
value: h,
|
|
153
|
+
placeholder: Y,
|
|
154
|
+
onChange: (e) => f("llm.model", e),
|
|
106
155
|
isDisabled: n
|
|
107
156
|
}),
|
|
108
|
-
|
|
109
|
-
/* @__PURE__ */
|
|
157
|
+
y ? /* @__PURE__ */ C(j, { testId: "openhands-api-key-help-2" }) : null,
|
|
158
|
+
/* @__PURE__ */ C(u, {
|
|
110
159
|
testId: "base-url-input",
|
|
111
|
-
label:
|
|
160
|
+
label: I(t.SETTINGS$BASE_URL),
|
|
112
161
|
type: "text",
|
|
113
162
|
className: "w-full",
|
|
114
|
-
value:
|
|
163
|
+
value: v,
|
|
115
164
|
placeholder: "https://api.openai.com",
|
|
116
|
-
onChange: (e) =>
|
|
165
|
+
onChange: (e) => f("llm.base_url", e),
|
|
117
166
|
isDisabled: n
|
|
118
167
|
}),
|
|
119
|
-
|
|
120
|
-
]
|
|
168
|
+
A("llm-api-key-input", "llm-api-key-help-anchor-advanced")
|
|
169
|
+
] })]
|
|
121
170
|
})
|
|
122
171
|
});
|
|
123
172
|
}, [
|
|
173
|
+
Y,
|
|
124
174
|
M,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
175
|
+
K,
|
|
176
|
+
L?.llm_api_key_set,
|
|
177
|
+
U,
|
|
178
|
+
I
|
|
179
|
+
]), Q = x.useCallback((e, t) => {
|
|
180
|
+
let n = structuredClone(e.agent_settings_diff ?? {}), i = n.llm ?? {};
|
|
181
|
+
if (c(t.values["llm.auth_type"]) === "subscription") {
|
|
182
|
+
i.auth_type = a, i.subscription_vendor = s;
|
|
183
|
+
let e = typeof i.model == "string" ? i.model : String(t.values["llm.model"] ?? ""), n = U?.[0];
|
|
184
|
+
if (!U?.includes(e) && !n) throw Error("Subscription models are not loaded yet.");
|
|
185
|
+
i.model = U?.includes(e) ? e : n, delete i.api_key, delete i.base_url;
|
|
186
|
+
} else t.dirty["llm.auth_type"] && (i.auth_type = r, i.subscription_vendor = null), t.view === "basic" && i.model !== void 0 && (i.base_url = D(R, "llm.base_url"));
|
|
187
|
+
return n.llm = i, { agent_settings_diff: n };
|
|
188
|
+
}, [R, U]);
|
|
189
|
+
return /* @__PURE__ */ C(y, {
|
|
190
|
+
scope: f,
|
|
134
191
|
settingsSources: [{
|
|
135
192
|
settingsSource: "agent_settings",
|
|
136
193
|
sectionKeys: ["llm"],
|
|
137
|
-
excludeKeys:
|
|
194
|
+
excludeKeys: T
|
|
138
195
|
}],
|
|
139
|
-
header:
|
|
140
|
-
buildPayload:
|
|
141
|
-
getInitialView:
|
|
196
|
+
header: Z,
|
|
197
|
+
buildPayload: Q,
|
|
198
|
+
getInitialView: X,
|
|
142
199
|
forceShowAdvancedView: !0,
|
|
143
200
|
allowAllView: !0,
|
|
144
|
-
onSaveSuccess:
|
|
145
|
-
initialValueOverrides:
|
|
146
|
-
embedded:
|
|
147
|
-
hideSaveButton:
|
|
148
|
-
suppressSuccessToast:
|
|
149
|
-
onSaveControlChange:
|
|
201
|
+
onSaveSuccess: O,
|
|
202
|
+
initialValueOverrides: k,
|
|
203
|
+
embedded: M,
|
|
204
|
+
hideSaveButton: N,
|
|
205
|
+
suppressSuccessToast: P,
|
|
206
|
+
onSaveControlChange: F,
|
|
150
207
|
testId: "llm-settings-screen"
|
|
151
208
|
});
|
|
152
209
|
}
|
|
153
210
|
//#endregion
|
|
154
|
-
export {
|
|
211
|
+
export { M as LlmSettingsScreen };
|
|
155
212
|
|
|
156
213
|
//# sourceMappingURL=llm-settings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-settings.js","names":[],"sources":["../../src/routes/llm-settings.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModelSelector } from \"#/components/shared/modals/settings/model-selector\";\nimport { useAgentSettingsSchema } from \"#/hooks/query/use-agent-settings-schema\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { KeyStatusIcon } from \"#/components/features/settings/key-status-icon\";\nimport {\n SdkSectionHeaderProps,\n SdkSectionPage,\n SdkSectionSaveControl,\n} from \"#/components/features/settings/sdk-settings/sdk-section-page\";\nimport { LlmSettingsLocalView } from \"#/components/features/settings/llm-profiles\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { Settings, SettingsSchema, SettingsScope } from \"#/types/settings\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport {\n inferInitialView,\n type SettingsFormValues,\n type SettingsView,\n} from \"#/utils/sdk-settings-schema\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport {\n OPENHANDS_LLM_PROXY_BASE_URL,\n isOpenHandsProxyModel,\n} from \"#/utils/openhands-llm\";\n\nconst LLM_EXCLUDED_KEYS = new Set([\"llm.model\", \"llm.api_key\", \"llm.base_url\"]);\n\nconst buildModelId = (provider: string | null, model: string | null) => {\n if (!provider || !model) return null;\n return `${provider}/${model}`;\n};\n\nconst getSchemaFieldDefaultValue = (\n schema: SettingsSchema | null | undefined,\n fieldKey: string,\n) =>\n schema?.sections\n .flatMap((section) => section.fields)\n .find((field) => field.key === fieldKey)?.default ?? null;\n\nconst KNOWN_PROVIDER_DEFAULT_BASE_URLS: Partial<Record<string, Set<string>>> = {\n openai: new Set([\"https://api.openai.com\", \"https://api.openai.com/v1\"]),\n openhands: new Set([\n OPENHANDS_LLM_PROXY_BASE_URL,\n \"https://llm-proxy.app.all-hands.dev/v1\",\n ]),\n litellm_proxy: new Set([\n OPENHANDS_LLM_PROXY_BASE_URL,\n \"https://llm-proxy.app.all-hands.dev/v1\",\n ]),\n};\n\nconst normalizeBaseUrl = (baseUrl: string) => {\n try {\n const parsedUrl = new URL(baseUrl);\n const normalizedPath = parsedUrl.pathname.replace(/\\/+$/, \"\") || \"\";\n return `${parsedUrl.origin}${normalizedPath}`;\n } catch {\n return baseUrl.trim().replace(/\\/+$/, \"\");\n }\n};\n\nconst isProviderDefaultBaseUrl = (model: string, baseUrl: string) => {\n const normalizedBaseUrl = normalizeBaseUrl(baseUrl);\n const { provider } = extractModelAndProvider(model);\n\n if (provider) {\n const knownDefaults = KNOWN_PROVIDER_DEFAULT_BASE_URLS[provider];\n if (knownDefaults) {\n return knownDefaults.has(normalizedBaseUrl);\n }\n }\n\n return Object.values(KNOWN_PROVIDER_DEFAULT_BASE_URLS).some((knownDefaults) =>\n knownDefaults?.has(normalizedBaseUrl),\n );\n};\n\ninterface OpenHandsApiKeyHelpProps {\n testId: string;\n}\n\nfunction OpenHandsApiKeyHelp({ testId }: OpenHandsApiKeyHelpProps) {\n const { t } = useTranslation(\"openhands\");\n\n return (\n <HelpLink\n testId={testId}\n text={t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT)}\n linkText={t(I18nKey.SETTINGS$NAV_API_KEYS)}\n href=\"https://app.all-hands.dev/settings/api-keys\"\n suffix={` ${t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`}\n />\n );\n}\n\nexport function LlmSettingsScreen({\n scope = \"personal\",\n onSaveSuccess,\n initialValueOverrides,\n embedded,\n hideSaveButton,\n suppressSuccessToast,\n onSaveControlChange,\n}: {\n scope?: SettingsScope;\n /** Optional hook fired after a successful save (e.g. advance an onboarding step). */\n onSaveSuccess?: () => void;\n /** Forwarded to {@link SdkSectionPage}. */\n initialValueOverrides?: SettingsFormValues;\n /** Forwarded to {@link SdkSectionPage}. */\n embedded?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n hideSaveButton?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n suppressSuccessToast?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n onSaveControlChange?: (control: SdkSectionSaveControl) => void;\n}) {\n const { t } = useTranslation(\"openhands\");\n\n const { data: settings } = useSettings(scope);\n const { data: schema } = useAgentSettingsSchema(\n settings?.agent_settings_schema,\n );\n\n const defaultModel = String(\n (DEFAULT_SETTINGS.agent_settings?.llm as Record<string, unknown>)?.model ??\n \"\",\n );\n\n const getInitialView = React.useCallback(\n (\n currentSettings: Settings,\n filteredSchema: SettingsSchema,\n ): SettingsView => {\n const schemaView = inferInitialView(currentSettings, filteredSchema);\n if (schemaView !== \"basic\") {\n return schemaView;\n }\n\n const currentModel = currentSettings.llm_model ?? \"\";\n const trimmedBaseUrl = currentSettings.llm_base_url?.trim() ?? \"\";\n const hasCustomBaseUrl =\n trimmedBaseUrl.length > 0 &&\n !isProviderDefaultBaseUrl(currentModel, trimmedBaseUrl);\n\n return hasCustomBaseUrl ? \"all\" : \"basic\";\n },\n [],\n );\n\n const buildHeader = React.useCallback(\n ({ values, isDisabled, view, onChange }: SdkSectionHeaderProps) => {\n const modelValue =\n typeof values[\"llm.model\"] === \"string\" ? values[\"llm.model\"] : \"\";\n const baseUrlValue =\n typeof values[\"llm.base_url\"] === \"string\"\n ? values[\"llm.base_url\"]\n : \"\";\n const showOpenHandsApiKeyHelp = modelValue.startsWith(\"openhands/\");\n\n const apiKeyValue =\n typeof values[\"llm.api_key\"] === \"string\" ? values[\"llm.api_key\"] : \"\";\n // For embedded profile forms (create/edit) the global\n // `llm_api_key_set` flag is misleading: a brand-new profile would show a\n // \"key set\" indicator just because some other profile has a key. Reflect\n // the form's own key state instead so create mode starts visibly unset.\n const apiKeyIsSet = embedded\n ? apiKeyValue.length > 0\n : Boolean(settings?.llm_api_key_set);\n\n const renderApiKeyInput = (testId: string, helpTestId: string) => (\n <>\n <SettingsInput\n testId={testId}\n label={t(I18nKey.SETTINGS_FORM$API_KEY)}\n type=\"password\"\n className=\"w-full\"\n value={apiKeyValue}\n placeholder={apiKeyIsSet ? \"<hidden>\" : \"\"}\n onChange={(value) => onChange(\"llm.api_key\", value)}\n isDisabled={isDisabled}\n startContent={\n apiKeyIsSet ? <KeyStatusIcon isSet={apiKeyIsSet} /> : undefined\n }\n />\n\n <HelpLink\n testId={helpTestId}\n text={t(I18nKey.SETTINGS$DONT_KNOW_API_KEY)}\n linkText={t(I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS)}\n href=\"https://docs.openhands.dev/usage/local-setup#getting-an-api-key\"\n />\n </>\n );\n\n return (\n <div className=\"flex flex-col gap-6\">\n {view === \"basic\" ? (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-basic\"\n >\n <ModelSelector\n currentModel={modelValue || undefined}\n currentBaseUrl={baseUrlValue || undefined}\n onChange={(provider, model) => {\n const nextModel = buildModelId(provider, model);\n if (nextModel) {\n onChange(\"llm.model\", nextModel);\n }\n }}\n wrapperClassName=\"!flex-col !gap-6\"\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help\" />\n ) : null}\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor\",\n )}\n </div>\n ) : (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-advanced\"\n >\n <SettingsInput\n testId=\"llm-custom-model-input\"\n label={t(I18nKey.SETTINGS$CUSTOM_MODEL)}\n type=\"text\"\n className=\"w-full\"\n value={modelValue}\n placeholder={defaultModel}\n onChange={(value) => onChange(\"llm.model\", value)}\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help-2\" />\n ) : null}\n\n <SettingsInput\n testId=\"base-url-input\"\n label={t(I18nKey.SETTINGS$BASE_URL)}\n type=\"text\"\n className=\"w-full\"\n value={baseUrlValue}\n placeholder=\"https://api.openai.com\"\n onChange={(value) => onChange(\"llm.base_url\", value)}\n isDisabled={isDisabled}\n />\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor-advanced\",\n )}\n </div>\n )}\n </div>\n );\n },\n [defaultModel, embedded, settings?.llm_api_key_set, t],\n );\n\n const buildPayload = React.useCallback(\n (\n defaultPayload: Record<string, unknown>,\n context: {\n values: Record<string, string | boolean>;\n view: SettingsView;\n },\n ) => {\n // defaultPayload is the wrapped diff (e.g.\n // `{ agent_settings_diff: { llm: { model: \"gpt-4\" } } }`); we only\n // mutate the inner `llm` object below.\n const agentSettings = structuredClone(\n (defaultPayload.agent_settings_diff as Record<string, unknown>) ?? {},\n );\n\n const llm = (agentSettings.llm ?? {}) as Record<string, unknown>;\n\n if (context.view === \"basic\") {\n const model = llm.model ?? context.values[\"llm.model\"];\n const baseUrl = llm.base_url ?? context.values[\"llm.base_url\"];\n llm.base_url = isOpenHandsProxyModel(model, baseUrl)\n ? OPENHANDS_LLM_PROXY_BASE_URL\n : getSchemaFieldDefaultValue(schema, \"llm.base_url\");\n agentSettings.llm = llm;\n }\n\n return { agent_settings_diff: agentSettings };\n },\n [schema],\n );\n\n return (\n <SdkSectionPage\n scope={scope}\n settingsSources={[\n {\n settingsSource: \"agent_settings\",\n sectionKeys: [\"llm\"],\n excludeKeys: LLM_EXCLUDED_KEYS,\n },\n ]}\n header={buildHeader}\n buildPayload={buildPayload}\n getInitialView={getInitialView}\n forceShowAdvancedView\n allowAllView\n onSaveSuccess={onSaveSuccess}\n initialValueOverrides={initialValueOverrides}\n embedded={embedded}\n hideSaveButton={hideSaveButton}\n suppressSuccessToast={suppressSuccessToast}\n onSaveControlChange={onSaveControlChange}\n testId=\"llm-settings-screen\"\n />\n );\n}\n\n/**\n * Default export for the route renders different views based on backend type:\n * - Local backends: LlmSettingsLocalView with profile management\n * - Cloud backends: Standard LlmSettingsScreen (profiles are not supported)\n *\n * The LlmSettingsScreen component is also exported for embedded use cases\n * (e.g., onboarding, profile editing forms).\n *\n * Note: This is a route file, only the router should import the default export.\n * Other consumers should use the named export `LlmSettingsScreen` for embedded\n * use cases.\n */\nexport default function LlmSettingsRoute() {\n const { backend } = useActiveBackend();\n const isCloud = backend.kind === \"cloud\";\n\n // Cloud backends use the standard LLM settings form (no profiles support)\n if (isCloud) {\n return <LlmSettingsScreen />;\n }\n\n // Local backends use the profile management view\n return <LlmSettingsLocalView />;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"llm-settings.js","names":[],"sources":["../../src/routes/llm-settings.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModelSelector } from \"#/components/shared/modals/settings/model-selector\";\nimport { useAgentSettingsSchema } from \"#/hooks/query/use-agent-settings-schema\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { SettingsDropdownInput } from \"#/components/features/settings/settings-dropdown-input\";\nimport { OpenAISubscriptionAuthCard } from \"#/components/features/settings/llm-settings/openai-subscription-auth-card\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { KeyStatusIcon } from \"#/components/features/settings/key-status-icon\";\nimport {\n SdkSectionHeaderProps,\n SdkSectionPage,\n SdkSectionSaveControl,\n} from \"#/components/features/settings/sdk-settings/sdk-section-page\";\nimport { LlmSettingsLocalView } from \"#/components/features/settings/llm-profiles\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { Settings, SettingsSchema, SettingsScope } from \"#/types/settings\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport {\n inferInitialView,\n type SettingsFormValues,\n type SettingsView,\n} from \"#/utils/sdk-settings-schema\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport {\n LLM_AUTH_TYPE_API_KEY,\n LLM_AUTH_TYPE_KEY,\n LLM_AUTH_TYPE_SUBSCRIPTION,\n LLM_SUBSCRIPTION_VENDOR_KEY,\n OPENAI_SUBSCRIPTION_VENDOR,\n resolveLlmAuthType,\n} from \"#/constants/llm-subscription\";\nimport { useOpenAISubscriptionModels } from \"#/hooks/query/use-llm-subscription-models\";\n\nconst LLM_EXCLUDED_KEYS = new Set([\n \"llm.model\",\n \"llm.api_key\",\n \"llm.base_url\",\n LLM_AUTH_TYPE_KEY,\n LLM_SUBSCRIPTION_VENDOR_KEY,\n]);\n\nconst buildModelId = (provider: string | null, model: string | null) => {\n if (!provider || !model) return null;\n return `${provider}/${model}`;\n};\n\nconst getSchemaFieldDefaultValue = (\n schema: SettingsSchema | null | undefined,\n fieldKey: string,\n) =>\n schema?.sections\n .flatMap((section) => section.fields)\n .find((field) => field.key === fieldKey)?.default ?? null;\n\nconst KNOWN_PROVIDER_DEFAULT_BASE_URLS: Partial<Record<string, Set<string>>> = {\n openai: new Set([\"https://api.openai.com\", \"https://api.openai.com/v1\"]),\n};\n\nconst normalizeBaseUrl = (baseUrl: string) => {\n try {\n const parsedUrl = new URL(baseUrl);\n const normalizedPath = parsedUrl.pathname.replace(/\\/+$/, \"\") || \"\";\n return `${parsedUrl.origin}${normalizedPath}`;\n } catch {\n return baseUrl.trim().replace(/\\/+$/, \"\");\n }\n};\n\nconst isProviderDefaultBaseUrl = (model: string, baseUrl: string) => {\n const normalizedBaseUrl = normalizeBaseUrl(baseUrl);\n const { provider } = extractModelAndProvider(model);\n\n if (provider) {\n const knownDefaults = KNOWN_PROVIDER_DEFAULT_BASE_URLS[provider];\n if (knownDefaults) {\n return knownDefaults.has(normalizedBaseUrl);\n }\n }\n\n return Object.values(KNOWN_PROVIDER_DEFAULT_BASE_URLS).some((knownDefaults) =>\n knownDefaults?.has(normalizedBaseUrl),\n );\n};\n\ninterface OpenHandsApiKeyHelpProps {\n testId: string;\n}\n\nfunction OpenHandsApiKeyHelp({ testId }: OpenHandsApiKeyHelpProps) {\n const { t } = useTranslation(\"openhands\");\n\n return (\n <HelpLink\n testId={testId}\n text={t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_TEXT)}\n linkText={t(I18nKey.SETTINGS$NAV_API_KEYS)}\n href=\"https://app.all-hands.dev/settings/api-keys\"\n suffix={` ${t(I18nKey.SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX)}`}\n />\n );\n}\n\nexport function LlmSettingsScreen({\n scope = \"personal\",\n onSaveSuccess,\n initialValueOverrides,\n embedded,\n hideSaveButton,\n suppressSuccessToast,\n onSaveControlChange,\n}: {\n scope?: SettingsScope;\n /** Optional hook fired after a successful save (e.g. advance an onboarding step). */\n onSaveSuccess?: () => void;\n /** Forwarded to {@link SdkSectionPage}. */\n initialValueOverrides?: SettingsFormValues;\n /** Forwarded to {@link SdkSectionPage}. */\n embedded?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n hideSaveButton?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n suppressSuccessToast?: boolean;\n /** Forwarded to {@link SdkSectionPage}. */\n onSaveControlChange?: (control: SdkSectionSaveControl) => void;\n}) {\n const { t } = useTranslation(\"openhands\");\n\n const { data: settings } = useSettings(scope);\n const { data: schema } = useAgentSettingsSchema(\n settings?.agent_settings_schema,\n );\n const persistedLlmSettings = settings?.agent_settings?.llm as\n | Record<string, unknown>\n | undefined;\n const initialAuthType = resolveLlmAuthType(\n initialValueOverrides?.[LLM_AUTH_TYPE_KEY] ??\n persistedLlmSettings?.auth_type,\n );\n const [enableSubscriptionModels, setEnableSubscriptionModels] =\n React.useState(initialAuthType === LLM_AUTH_TYPE_SUBSCRIPTION);\n const {\n data: subscriptionModels,\n isLoading: isSubscriptionModelsLoading,\n isFetching: isSubscriptionModelsFetching,\n } = useOpenAISubscriptionModels({ enabled: enableSubscriptionModels });\n const isWaitingForSubscriptionModels =\n enableSubscriptionModels &&\n !subscriptionModels &&\n (isSubscriptionModelsLoading || isSubscriptionModelsFetching);\n const lastApiKeyModelRef = React.useRef<string | null>(null);\n const lastSubscriptionModelRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n if (initialAuthType === LLM_AUTH_TYPE_SUBSCRIPTION) {\n setEnableSubscriptionModels(true);\n }\n }, [initialAuthType]);\n\n const defaultModel = String(\n (DEFAULT_SETTINGS.agent_settings?.llm as Record<string, unknown>)?.model ??\n \"\",\n );\n\n const getInitialView = React.useCallback(\n (\n currentSettings: Settings,\n filteredSchema: SettingsSchema,\n ): SettingsView => {\n const schemaView = inferInitialView(currentSettings, filteredSchema);\n if (schemaView !== \"basic\") {\n return schemaView;\n }\n\n const currentModel = currentSettings.llm_model ?? \"\";\n const trimmedBaseUrl = currentSettings.llm_base_url?.trim() ?? \"\";\n const hasCustomBaseUrl =\n trimmedBaseUrl.length > 0 &&\n !isProviderDefaultBaseUrl(currentModel, trimmedBaseUrl);\n\n return hasCustomBaseUrl ? \"all\" : \"basic\";\n },\n [],\n );\n\n const buildHeader = React.useCallback(\n ({ values, isDisabled, view, onChange }: SdkSectionHeaderProps) => {\n const modelValue =\n typeof values[\"llm.model\"] === \"string\" ? values[\"llm.model\"] : \"\";\n const baseUrlValue =\n typeof values[\"llm.base_url\"] === \"string\"\n ? values[\"llm.base_url\"]\n : \"\";\n const showOpenHandsApiKeyHelp = modelValue.startsWith(\"openhands/\");\n const authType = resolveLlmAuthType(values[LLM_AUTH_TYPE_KEY]);\n const isSubscriptionAuth = authType === LLM_AUTH_TYPE_SUBSCRIPTION;\n const shouldDisableSubscriptionControls =\n isDisabled || (isSubscriptionAuth && isWaitingForSubscriptionModels);\n const subscriptionModelValue = subscriptionModels?.includes(modelValue)\n ? modelValue\n : (subscriptionModels?.[0] ?? \"\");\n\n const apiKeyValue =\n typeof values[\"llm.api_key\"] === \"string\" ? values[\"llm.api_key\"] : \"\";\n // For embedded profile forms (create/edit) the global\n // `llm_api_key_set` flag is misleading: a brand-new profile would show a\n // \"key set\" indicator just because some other profile has a key. Reflect\n // the form's own key state instead so create mode starts visibly unset.\n const apiKeyIsSet = embedded\n ? apiKeyValue.length > 0\n : Boolean(settings?.llm_api_key_set);\n\n const renderApiKeyInput = (testId: string, helpTestId: string) => (\n <>\n <SettingsInput\n testId={testId}\n label={t(I18nKey.SETTINGS_FORM$API_KEY)}\n type=\"password\"\n className=\"w-full\"\n value={apiKeyValue}\n placeholder={apiKeyIsSet ? \"<hidden>\" : \"\"}\n onChange={(value) => onChange(\"llm.api_key\", value)}\n isDisabled={isDisabled}\n startContent={\n apiKeyIsSet ? <KeyStatusIcon isSet={apiKeyIsSet} /> : undefined\n }\n />\n\n <HelpLink\n testId={helpTestId}\n text={t(I18nKey.SETTINGS$DONT_KNOW_API_KEY)}\n linkText={t(I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS)}\n href=\"https://docs.openhands.dev/usage/local-setup#getting-an-api-key\"\n />\n </>\n );\n\n const handleAuthTypeChange = (selectedKey: React.Key | null) => {\n const nextAuthType =\n selectedKey === LLM_AUTH_TYPE_SUBSCRIPTION\n ? LLM_AUTH_TYPE_SUBSCRIPTION\n : LLM_AUTH_TYPE_API_KEY;\n onChange(LLM_AUTH_TYPE_KEY, nextAuthType);\n\n if (nextAuthType === LLM_AUTH_TYPE_SUBSCRIPTION) {\n setEnableSubscriptionModels(true);\n if (modelValue && !subscriptionModels?.includes(modelValue)) {\n lastApiKeyModelRef.current = modelValue;\n }\n const restoredSubscriptionModel =\n lastSubscriptionModelRef.current &&\n subscriptionModels?.includes(lastSubscriptionModelRef.current)\n ? lastSubscriptionModelRef.current\n : subscriptionModels?.[0];\n onChange(LLM_SUBSCRIPTION_VENDOR_KEY, OPENAI_SUBSCRIPTION_VENDOR);\n if (\n !subscriptionModels?.includes(modelValue) &&\n restoredSubscriptionModel\n ) {\n onChange(\"llm.model\", restoredSubscriptionModel);\n }\n return;\n }\n\n if (modelValue && subscriptionModels?.includes(modelValue)) {\n lastSubscriptionModelRef.current = modelValue;\n onChange(\"llm.model\", lastApiKeyModelRef.current ?? defaultModel);\n }\n };\n\n const renderAuthTypeInput = () => (\n <SettingsDropdownInput\n testId=\"llm-auth-type-input\"\n name={LLM_AUTH_TYPE_KEY}\n label={t(I18nKey.SETTINGS$LLM_AUTH_TYPE)}\n items={[\n {\n key: LLM_AUTH_TYPE_API_KEY,\n label: t(I18nKey.SETTINGS$LLM_AUTH_TYPE_API_KEY),\n },\n {\n key: LLM_AUTH_TYPE_SUBSCRIPTION,\n label: t(I18nKey.SETTINGS$LLM_AUTH_TYPE_SUBSCRIPTION),\n },\n ]}\n selectedKey={authType}\n isClearable={false}\n required\n isDisabled={shouldDisableSubscriptionControls}\n onSelectionChange={handleAuthTypeChange}\n />\n );\n\n const renderSubscriptionSettings = () => (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-subscription-settings\"\n >\n <SettingsDropdownInput\n testId=\"llm-subscription-model-input\"\n name=\"llm.subscription_model\"\n label={t(I18nKey.SETTINGS$SUBSCRIPTION_MODEL)}\n items={(subscriptionModels ?? []).map((model) => ({\n key: model,\n label: model,\n }))}\n selectedKey={subscriptionModelValue}\n isClearable={false}\n required\n isDisabled={\n shouldDisableSubscriptionControls || !subscriptionModels?.length\n }\n onSelectionChange={(selectedKey) => {\n const nextModel =\n typeof selectedKey === \"string\"\n ? selectedKey\n : subscriptionModels?.[0];\n if (nextModel) {\n onChange(\"llm.model\", nextModel);\n }\n }}\n />\n <OpenAISubscriptionAuthCard isDisabled={isDisabled} />\n </div>\n );\n\n return (\n <div className=\"flex flex-col gap-6\">\n {view === \"basic\" ? (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-basic\"\n >\n {renderAuthTypeInput()}\n\n {isSubscriptionAuth ? (\n renderSubscriptionSettings()\n ) : (\n <>\n <ModelSelector\n currentModel={modelValue || undefined}\n onChange={(provider, model) => {\n const nextModel = buildModelId(provider, model);\n if (nextModel) {\n onChange(\"llm.model\", nextModel);\n }\n }}\n wrapperClassName=\"!flex-col !gap-6\"\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help\" />\n ) : null}\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor\",\n )}\n </>\n )}\n </div>\n ) : (\n <div\n className=\"flex flex-col gap-6\"\n data-testid=\"llm-settings-form-advanced\"\n >\n {renderAuthTypeInput()}\n\n {isSubscriptionAuth ? (\n renderSubscriptionSettings()\n ) : (\n <>\n <SettingsInput\n testId=\"llm-custom-model-input\"\n label={t(I18nKey.SETTINGS$CUSTOM_MODEL)}\n type=\"text\"\n className=\"w-full\"\n value={modelValue}\n placeholder={defaultModel}\n onChange={(value) => onChange(\"llm.model\", value)}\n isDisabled={isDisabled}\n />\n\n {showOpenHandsApiKeyHelp ? (\n <OpenHandsApiKeyHelp testId=\"openhands-api-key-help-2\" />\n ) : null}\n\n <SettingsInput\n testId=\"base-url-input\"\n label={t(I18nKey.SETTINGS$BASE_URL)}\n type=\"text\"\n className=\"w-full\"\n value={baseUrlValue}\n placeholder=\"https://api.openai.com\"\n onChange={(value) => onChange(\"llm.base_url\", value)}\n isDisabled={isDisabled}\n />\n\n {renderApiKeyInput(\n \"llm-api-key-input\",\n \"llm-api-key-help-anchor-advanced\",\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n },\n [\n defaultModel,\n embedded,\n isWaitingForSubscriptionModels,\n settings?.llm_api_key_set,\n subscriptionModels,\n t,\n ],\n );\n\n const buildPayload = React.useCallback(\n (\n defaultPayload: Record<string, unknown>,\n context: {\n values: Record<string, string | boolean>;\n dirty: Record<string, boolean>;\n view: SettingsView;\n },\n ) => {\n // defaultPayload is the wrapped diff (e.g.\n // `{ agent_settings_diff: { llm: { model: \"gpt-4\" } } }`); we only\n // mutate the inner `llm` object below.\n const agentSettings = structuredClone(\n (defaultPayload.agent_settings_diff as Record<string, unknown>) ?? {},\n );\n const llm = (agentSettings.llm ?? {}) as Record<string, unknown>;\n const authType = resolveLlmAuthType(context.values[LLM_AUTH_TYPE_KEY]);\n\n if (authType === LLM_AUTH_TYPE_SUBSCRIPTION) {\n llm.auth_type = LLM_AUTH_TYPE_SUBSCRIPTION;\n llm.subscription_vendor = OPENAI_SUBSCRIPTION_VENDOR;\n const model =\n typeof llm.model === \"string\"\n ? llm.model\n : String(context.values[\"llm.model\"] ?? \"\");\n const fallbackSubscriptionModel = subscriptionModels?.[0];\n if (\n !subscriptionModels?.includes(model) &&\n !fallbackSubscriptionModel\n ) {\n throw new Error(\"Subscription models are not loaded yet.\");\n }\n llm.model = subscriptionModels?.includes(model)\n ? model\n : fallbackSubscriptionModel;\n delete llm.api_key;\n delete llm.base_url;\n } else {\n if (context.dirty[LLM_AUTH_TYPE_KEY]) {\n llm.auth_type = LLM_AUTH_TYPE_API_KEY;\n llm.subscription_vendor = null;\n }\n if (context.view === \"basic\" && llm.model !== undefined) {\n llm.base_url = getSchemaFieldDefaultValue(schema, \"llm.base_url\");\n }\n }\n\n agentSettings.llm = llm;\n return { agent_settings_diff: agentSettings };\n },\n [schema, subscriptionModels],\n );\n\n return (\n <SdkSectionPage\n scope={scope}\n settingsSources={[\n {\n settingsSource: \"agent_settings\",\n sectionKeys: [\"llm\"],\n excludeKeys: LLM_EXCLUDED_KEYS,\n },\n ]}\n header={buildHeader}\n buildPayload={buildPayload}\n getInitialView={getInitialView}\n forceShowAdvancedView\n allowAllView\n onSaveSuccess={onSaveSuccess}\n initialValueOverrides={initialValueOverrides}\n embedded={embedded}\n hideSaveButton={hideSaveButton}\n suppressSuccessToast={suppressSuccessToast}\n onSaveControlChange={onSaveControlChange}\n testId=\"llm-settings-screen\"\n />\n );\n}\n\n/**\n * Default export for the route renders different views based on backend type:\n * - Local backends: LlmSettingsLocalView with profile management\n * - Cloud backends: Standard LlmSettingsScreen (profiles are not supported)\n *\n * The LlmSettingsScreen component is also exported for embedded use cases\n * (e.g., onboarding, profile editing forms).\n *\n * Note: This is a route file, only the router should import the default export.\n * Other consumers should use the named export `LlmSettingsScreen` for embedded\n * use cases.\n */\nexport default function LlmSettingsRoute() {\n const { backend } = useActiveBackend();\n const isCloud = backend.kind === \"cloud\";\n\n // Cloud backends use the standard LLM settings form (no profiles support)\n if (isCloud) {\n return <LlmSettingsScreen />;\n }\n\n // Local backends use the profile management view\n return <LlmSettingsLocalView />;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../stores/conversation-store.cjs`),t=require(`../stores/files-tab-store.cjs`);var n=new Set([`files`,`browser`,`terminal`,`planner`,`tasklist`]);function r(t){let n=e.useConversationStore.getState();n.setSelectedTab(t),n.isRightPanelShown||(n.setHasRightPanelToggled(!0),n.setIsRightPanelShown(!0))}function i(e){return n.has(e)}function a(e){switch(e.command){case`navigate_to_file`:case`show_preview`:r(`files`),e.path&&t.useFilesTabStore.getState().setSelectedPath(e.path);return;case`open_tab`:e.tab===`vscode`?r(`files`):e.tab&&i(e.tab)?r(e.tab):e.tab&&console.warn(`[canvas_ui] Ignoring open_tab with unknown tab: ${e.tab}`);return}}exports.handleCanvasUIAction=a;
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../stores/conversation-store.cjs`),t=require(`../stores/files-tab-store.cjs`);var n=new Set([`files`,`browser`,`terminal`,`planner`,`tasklist`]);function r(t){let n=e.useConversationStore.getState();n.setSelectedTab(t),n.isRightPanelShown||(n.setHasRightPanelToggled(!0),n.setIsRightPanelShown(!0))}function i(e){return n.has(e)}function a(e,n=null){switch(e.command){case`navigate_to_file`:case`show_preview`:r(`files`),e.path&&t.useFilesTabStore.getState().setSelectedPath(e.path,n);return;case`open_tab`:e.tab===`vscode`?r(`files`):e.tab&&i(e.tab)?r(e.tab):e.tab&&console.warn(`[canvas_ui] Ignoring open_tab with unknown tab: ${e.tab}`);return}}exports.handleCanvasUIAction=a;
|
|
2
2
|
//# sourceMappingURL=canvas-ui.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-ui.cjs","names":[],"sources":["../../src/services/canvas-ui.ts"],"sourcesContent":["import {\n ConversationTab,\n useConversationStore,\n} from \"#/stores/conversation-store\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport type { CanvasUIAction } from \"#/types/agent-server/core\";\n\nconst VALID_TABS: ReadonlySet<ConversationTab> = new Set<ConversationTab>([\n \"files\",\n \"browser\",\n \"terminal\",\n \"planner\",\n \"tasklist\",\n]);\n\n// Mirrors src/hooks/use-select-conversation-tab.ts so a non-React caller (the\n// WebSocket dispatch) gets the same \"reveal the right panel if collapsed\"\n// behavior as in-app tab switches.\nfunction navigateToTab(tab: ConversationTab) {\n const store = useConversationStore.getState();\n store.setSelectedTab(tab);\n if (!store.isRightPanelShown) {\n store.setHasRightPanelToggled(true);\n store.setIsRightPanelShown(true);\n }\n}\n\nfunction isValidTab(value: string): value is ConversationTab {\n return VALID_TABS.has(value as ConversationTab);\n}\n\nexport function handleCanvasUIAction(action: CanvasUIAction): void {\n switch (action.command) {\n case \"navigate_to_file\":\n case \"show_preview\":\n navigateToTab(\"files\");\n if (action.path) {\n useFilesTabStore.getState().setSelectedPath(action.path);\n }\n return;\n case \"open_tab\":\n if (action.tab === \"vscode\") {\n // The in-app VS Code tab was removed — on cloud backends VS Code\n // now opens in a new browser window via the link in the drawer tab\n // row. Route agent requests to Files so the drawer still opens.\n navigateToTab(\"files\");\n } else if (action.tab && isValidTab(action.tab)) {\n navigateToTab(action.tab);\n } else if (action.tab) {\n // Surface unknown tab names so they're diagnosable from the browser\n // console rather than failing silently. Valid tabs are listed in\n // VALID_TABS above and mirror ConversationTab.\n console.warn(\n `[canvas_ui] Ignoring open_tab with unknown tab: ${action.tab}`,\n );\n }\n return;\n }\n}\n"],"mappings":"4IAOA,IAAM,EAA2C,IAAI,IAAqB,CACxE,QACA,UACA,WACA,UACA,WACD,CAAC,CAKF,SAAS,EAAc,EAAsB,CAC3C,IAAM,EAAQ,EAAA,qBAAqB,UAAU,CAC7C,EAAM,eAAe,EAAI,CACpB,EAAM,oBACT,EAAM,wBAAwB,GAAK,CACnC,EAAM,qBAAqB,GAAK,EAIpC,SAAS,EAAW,EAAyC,CAC3D,OAAO,EAAW,IAAI,EAAyB,CAGjD,SAAgB,
|
|
1
|
+
{"version":3,"file":"canvas-ui.cjs","names":[],"sources":["../../src/services/canvas-ui.ts"],"sourcesContent":["import {\n ConversationTab,\n useConversationStore,\n} from \"#/stores/conversation-store\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport type { CanvasUIAction } from \"#/types/agent-server/core\";\n\nconst VALID_TABS: ReadonlySet<ConversationTab> = new Set<ConversationTab>([\n \"files\",\n \"browser\",\n \"terminal\",\n \"planner\",\n \"tasklist\",\n]);\n\n// Mirrors src/hooks/use-select-conversation-tab.ts so a non-React caller (the\n// WebSocket dispatch) gets the same \"reveal the right panel if collapsed\"\n// behavior as in-app tab switches.\nfunction navigateToTab(tab: ConversationTab) {\n const store = useConversationStore.getState();\n store.setSelectedTab(tab);\n if (!store.isRightPanelShown) {\n store.setHasRightPanelToggled(true);\n store.setIsRightPanelShown(true);\n }\n}\n\nfunction isValidTab(value: string): value is ConversationTab {\n return VALID_TABS.has(value as ConversationTab);\n}\n\nexport function handleCanvasUIAction(\n action: CanvasUIAction,\n conversationId: string | null = null,\n): void {\n switch (action.command) {\n case \"navigate_to_file\":\n case \"show_preview\":\n navigateToTab(\"files\");\n if (action.path) {\n useFilesTabStore\n .getState()\n .setSelectedPath(action.path, conversationId);\n }\n return;\n case \"open_tab\":\n if (action.tab === \"vscode\") {\n // The in-app VS Code tab was removed — on cloud backends VS Code\n // now opens in a new browser window via the link in the drawer tab\n // row. Route agent requests to Files so the drawer still opens.\n navigateToTab(\"files\");\n } else if (action.tab && isValidTab(action.tab)) {\n navigateToTab(action.tab);\n } else if (action.tab) {\n // Surface unknown tab names so they're diagnosable from the browser\n // console rather than failing silently. Valid tabs are listed in\n // VALID_TABS above and mirror ConversationTab.\n console.warn(\n `[canvas_ui] Ignoring open_tab with unknown tab: ${action.tab}`,\n );\n }\n return;\n }\n}\n"],"mappings":"4IAOA,IAAM,EAA2C,IAAI,IAAqB,CACxE,QACA,UACA,WACA,UACA,WACD,CAAC,CAKF,SAAS,EAAc,EAAsB,CAC3C,IAAM,EAAQ,EAAA,qBAAqB,UAAU,CAC7C,EAAM,eAAe,EAAI,CACpB,EAAM,oBACT,EAAM,wBAAwB,GAAK,CACnC,EAAM,qBAAqB,GAAK,EAIpC,SAAS,EAAW,EAAyC,CAC3D,OAAO,EAAW,IAAI,EAAyB,CAGjD,SAAgB,EACd,EACA,EAAgC,KAC1B,CACN,OAAQ,EAAO,QAAf,CACE,IAAK,mBACL,IAAK,eACH,EAAc,QAAQ,CAClB,EAAO,MACT,EAAA,iBACG,UAAU,CACV,gBAAgB,EAAO,KAAM,EAAe,CAEjD,OACF,IAAK,WACC,EAAO,MAAQ,SAIjB,EAAc,QAAQ,CACb,EAAO,KAAO,EAAW,EAAO,IAAI,CAC7C,EAAc,EAAO,IAAI,CAChB,EAAO,KAIhB,QAAQ,KACN,mDAAmD,EAAO,MAC3D,CAEH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { CanvasUIAction } from "#/types/agent-server/core";
|
|
2
|
-
export declare function handleCanvasUIAction(action: CanvasUIAction): void;
|
|
2
|
+
export declare function handleCanvasUIAction(action: CanvasUIAction, conversationId?: string | null): void;
|
|
@@ -15,11 +15,11 @@ function r(t) {
|
|
|
15
15
|
function i(e) {
|
|
16
16
|
return n.has(e);
|
|
17
17
|
}
|
|
18
|
-
function a(e) {
|
|
18
|
+
function a(e, n = null) {
|
|
19
19
|
switch (e.command) {
|
|
20
20
|
case "navigate_to_file":
|
|
21
21
|
case "show_preview":
|
|
22
|
-
r("files"), e.path && t.getState().setSelectedPath(e.path);
|
|
22
|
+
r("files"), e.path && t.getState().setSelectedPath(e.path, n);
|
|
23
23
|
return;
|
|
24
24
|
case "open_tab":
|
|
25
25
|
e.tab === "vscode" ? r("files") : e.tab && i(e.tab) ? r(e.tab) : e.tab && console.warn(`[canvas_ui] Ignoring open_tab with unknown tab: ${e.tab}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-ui.js","names":[],"sources":["../../src/services/canvas-ui.ts"],"sourcesContent":["import {\n ConversationTab,\n useConversationStore,\n} from \"#/stores/conversation-store\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport type { CanvasUIAction } from \"#/types/agent-server/core\";\n\nconst VALID_TABS: ReadonlySet<ConversationTab> = new Set<ConversationTab>([\n \"files\",\n \"browser\",\n \"terminal\",\n \"planner\",\n \"tasklist\",\n]);\n\n// Mirrors src/hooks/use-select-conversation-tab.ts so a non-React caller (the\n// WebSocket dispatch) gets the same \"reveal the right panel if collapsed\"\n// behavior as in-app tab switches.\nfunction navigateToTab(tab: ConversationTab) {\n const store = useConversationStore.getState();\n store.setSelectedTab(tab);\n if (!store.isRightPanelShown) {\n store.setHasRightPanelToggled(true);\n store.setIsRightPanelShown(true);\n }\n}\n\nfunction isValidTab(value: string): value is ConversationTab {\n return VALID_TABS.has(value as ConversationTab);\n}\n\nexport function handleCanvasUIAction(action: CanvasUIAction): void {\n switch (action.command) {\n case \"navigate_to_file\":\n case \"show_preview\":\n navigateToTab(\"files\");\n if (action.path) {\n useFilesTabStore.getState().setSelectedPath(action.path);\n }\n return;\n case \"open_tab\":\n if (action.tab === \"vscode\") {\n // The in-app VS Code tab was removed — on cloud backends VS Code\n // now opens in a new browser window via the link in the drawer tab\n // row. Route agent requests to Files so the drawer still opens.\n navigateToTab(\"files\");\n } else if (action.tab && isValidTab(action.tab)) {\n navigateToTab(action.tab);\n } else if (action.tab) {\n // Surface unknown tab names so they're diagnosable from the browser\n // console rather than failing silently. Valid tabs are listed in\n // VALID_TABS above and mirror ConversationTab.\n console.warn(\n `[canvas_ui] Ignoring open_tab with unknown tab: ${action.tab}`,\n );\n }\n return;\n }\n}\n"],"mappings":";;;AAOA,IAAM,IAA2C,IAAI,IAAqB;CACxE;CACA;CACA;CACA;CACA;CACD,CAAC;AAKF,SAAS,EAAc,GAAsB;CAC3C,IAAM,IAAQ,EAAqB,UAAU;AAE7C,CADA,EAAM,eAAe,EAAI,EACpB,EAAM,sBACT,EAAM,wBAAwB,GAAK,EACnC,EAAM,qBAAqB,GAAK;;AAIpC,SAAS,EAAW,GAAyC;AAC3D,QAAO,EAAW,IAAI,EAAyB;;AAGjD,SAAgB,
|
|
1
|
+
{"version":3,"file":"canvas-ui.js","names":[],"sources":["../../src/services/canvas-ui.ts"],"sourcesContent":["import {\n ConversationTab,\n useConversationStore,\n} from \"#/stores/conversation-store\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport type { CanvasUIAction } from \"#/types/agent-server/core\";\n\nconst VALID_TABS: ReadonlySet<ConversationTab> = new Set<ConversationTab>([\n \"files\",\n \"browser\",\n \"terminal\",\n \"planner\",\n \"tasklist\",\n]);\n\n// Mirrors src/hooks/use-select-conversation-tab.ts so a non-React caller (the\n// WebSocket dispatch) gets the same \"reveal the right panel if collapsed\"\n// behavior as in-app tab switches.\nfunction navigateToTab(tab: ConversationTab) {\n const store = useConversationStore.getState();\n store.setSelectedTab(tab);\n if (!store.isRightPanelShown) {\n store.setHasRightPanelToggled(true);\n store.setIsRightPanelShown(true);\n }\n}\n\nfunction isValidTab(value: string): value is ConversationTab {\n return VALID_TABS.has(value as ConversationTab);\n}\n\nexport function handleCanvasUIAction(\n action: CanvasUIAction,\n conversationId: string | null = null,\n): void {\n switch (action.command) {\n case \"navigate_to_file\":\n case \"show_preview\":\n navigateToTab(\"files\");\n if (action.path) {\n useFilesTabStore\n .getState()\n .setSelectedPath(action.path, conversationId);\n }\n return;\n case \"open_tab\":\n if (action.tab === \"vscode\") {\n // The in-app VS Code tab was removed — on cloud backends VS Code\n // now opens in a new browser window via the link in the drawer tab\n // row. Route agent requests to Files so the drawer still opens.\n navigateToTab(\"files\");\n } else if (action.tab && isValidTab(action.tab)) {\n navigateToTab(action.tab);\n } else if (action.tab) {\n // Surface unknown tab names so they're diagnosable from the browser\n // console rather than failing silently. Valid tabs are listed in\n // VALID_TABS above and mirror ConversationTab.\n console.warn(\n `[canvas_ui] Ignoring open_tab with unknown tab: ${action.tab}`,\n );\n }\n return;\n }\n}\n"],"mappings":";;;AAOA,IAAM,IAA2C,IAAI,IAAqB;CACxE;CACA;CACA;CACA;CACA;CACD,CAAC;AAKF,SAAS,EAAc,GAAsB;CAC3C,IAAM,IAAQ,EAAqB,UAAU;AAE7C,CADA,EAAM,eAAe,EAAI,EACpB,EAAM,sBACT,EAAM,wBAAwB,GAAK,EACnC,EAAM,qBAAqB,GAAK;;AAIpC,SAAS,EAAW,GAAyC;AAC3D,QAAO,EAAW,IAAI,EAAyB;;AAGjD,SAAgB,EACd,GACA,IAAgC,MAC1B;AACN,SAAQ,EAAO,SAAf;EACE,KAAK;EACL,KAAK;AAEH,GADA,EAAc,QAAQ,EAClB,EAAO,QACT,EACG,UAAU,CACV,gBAAgB,EAAO,MAAM,EAAe;AAEjD;EACF,KAAK;AACH,GAAI,EAAO,QAAQ,WAIjB,EAAc,QAAQ,GACb,EAAO,OAAO,EAAW,EAAO,IAAI,GAC7C,EAAc,EAAO,IAAI,GAChB,EAAO,OAIhB,QAAQ,KACN,mDAAmD,EAAO,MAC3D;AAEH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);var e=require(`../node_modules/zustand/esm/react.cjs`).create(e=>({selectedPath:null,setSelectedPath:t=>e({selectedPath:t})}));exports.useFilesTabStore=e;
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);var e=require(`../node_modules/zustand/esm/react.cjs`).create(e=>({selectedPath:null,selectedConversationId:null,setSelectedPath:(t,n=null)=>e({selectedPath:t,selectedConversationId:n})}));exports.useFilesTabStore=e;
|
|
2
2
|
//# sourceMappingURL=files-tab-store.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-tab-store.cjs","names":[],"sources":["../../src/stores/files-tab-store.ts"],"sourcesContent":["import { create } from \"zustand\";\n\ninterface FilesTabState {\n selectedPath: string | null;\n setSelectedPath: (path: string | null) => void;\n}\n\n// Hoisted out of files-tab.tsx local state so non-React callers (e.g. the\n// canvas_ui tool dispatcher in the WebSocket context) can drive selection.\nexport const useFilesTabStore = create<FilesTabState>((set) => ({\n selectedPath: null,\n setSelectedPath: (selectedPath)
|
|
1
|
+
{"version":3,"file":"files-tab-store.cjs","names":[],"sources":["../../src/stores/files-tab-store.ts"],"sourcesContent":["import { create } from \"zustand\";\n\ninterface FilesTabState {\n selectedPath: string | null;\n // The conversation a selection belongs to. A file picked in one\n // conversation must not leak into another (it usually doesn't exist in the\n // other conversation's workspace, see issue #1350), so every selection is\n // tagged with its conversation and the files tab ignores a path owned by a\n // different conversation.\n selectedConversationId: string | null;\n setSelectedPath: (\n path: string | null,\n conversationId?: string | null,\n ) => void;\n}\n\n// Hoisted out of files-tab.tsx local state so non-React callers (e.g. the\n// canvas_ui tool dispatcher in the WebSocket context) can drive selection.\nexport const useFilesTabStore = create<FilesTabState>((set) => ({\n selectedPath: null,\n selectedConversationId: null,\n setSelectedPath: (selectedPath, conversationId = null) =>\n set({ selectedPath, selectedConversationId: conversationId }),\n}));\n"],"mappings":"6CAkBA,IAAa,kDAAmB,CAAA,OAAuB,IAAS,CAC9D,aAAc,KACd,uBAAwB,KACxB,iBAAkB,EAAc,EAAiB,OAC/C,EAAI,CAAE,eAAc,uBAAwB,EAAgB,CAAC,CAChE,EAAE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
interface FilesTabState {
|
|
2
2
|
selectedPath: string | null;
|
|
3
|
-
|
|
3
|
+
selectedConversationId: string | null;
|
|
4
|
+
setSelectedPath: (path: string | null, conversationId?: string | null) => void;
|
|
4
5
|
}
|
|
5
6
|
export declare const useFilesTabStore: import("zustand").UseBoundStore<import("zustand").StoreApi<FilesTabState>>;
|
|
6
7
|
export {};
|