@openhands/agent-canvas 1.0.0-alpha.9 → 1.0.0-beta.2
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 +2 -2
- package/bin/agent-canvas.mjs +22 -2
- package/build/assets/{QueryClientProvider-B7kl84Kj.js → QueryClientProvider-CkGuhXg-.js} +1 -1
- package/build/assets/{Trans-1j65oy9O.js → Trans-Cvm_-SMi.js} +1 -1
- package/build/assets/acp-providers-CbiRekh9.js +1 -0
- package/build/assets/{acp-route-guard-CQTmeJwM.js → acp-route-guard-B2yoBZ_4.js} +1 -1
- package/build/assets/{active-backend-context-TVbjnvmP.js → active-backend-context-cCM1vYYZ.js} +1 -1
- package/build/assets/add-backend-modal-DIUQzMPa.js +1 -0
- package/build/assets/agent-server-client-options-Bc5ZorQZ.js +1 -0
- package/build/assets/agent-server-compatibility-BlkUsrX2.js +1 -0
- package/build/assets/agent-server-conversation-service.api-DFvqqEDo.js +5 -0
- package/build/assets/{agent-settings-B247S9G3.js → agent-settings-CnGSCmK8.js} +1 -1
- package/build/assets/{alert-banner-BWoqueRw.js → alert-banner-DtzAX654.js} +1 -1
- package/build/assets/{analytics-consent-form-modal-C7sXfxRh.js → analytics-consent-form-modal-CHZ3I37v.js} +1 -1
- package/build/assets/api-key-entry-screen-B2gynaCp.js +1 -0
- package/build/assets/{app-settings-BVeSaty9.js → app-settings-Db9ITeJH.js} +1 -1
- package/build/assets/{automation-detail-R-99FUce.js → automation-detail-Di7EOIZD.js} +1 -1
- package/build/assets/{automations-list-Dfu2c-_D.js → automations-list-IsIWdDiw.js} +1 -1
- package/build/assets/{backend-form-modal-DxYjqqAK.js → backend-form-modal-Dnk33xA_.js} +1 -1
- package/build/assets/{backend-synced-settings-badge-nAfiUWvM.js → backend-synced-settings-badge-Dc6c7GT4.js} +1 -1
- package/build/assets/{base-modal-CQRvRHu1.js → base-modal-_dYTw1ri.js} +1 -1
- package/build/assets/{brand-button-C2nEKopC.js → brand-button-Br7f0kZJ.js} +1 -1
- package/build/assets/{browser-HrYc5Gce.js → browser-D810xUYt.js} +2 -2
- package/build/assets/browser-store-Couc4S5D.js +1 -0
- package/build/assets/browser-tab-B-aIqXRl.js +1 -0
- package/build/assets/{checkmark-BJJrZUF8.js → checkmark-DL7acQA7.js} +1 -1
- package/build/assets/{chevron-left-small-CSh-sE9L.js → chevron-left-small-CVWf8TI6.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-qs8Va1cC.js → circle-plus-check-toggle-P7ZZToV4.js} +1 -1
- package/build/assets/{clock-ZR4Kn-_Y.js → clock-BRjCgHTc.js} +1 -1
- package/build/assets/{close-BdmyeRqS.js → close-B5LROHR3.js} +1 -1
- package/build/assets/{combobox-caret-B53O9Hsq.js → combobox-caret-to1O8irE.js} +1 -1
- package/build/assets/{condenser-settings-A35V3yng.js → condenser-settings-wnEKhBof.js} +1 -1
- package/build/assets/{confirmation-modal-C9-La0h3.js → confirmation-modal-Dau3w_sa.js} +1 -1
- package/build/assets/{context-menu-list-item-Buu9nc0q.js → context-menu-list-item-CWNFpuiC.js} +1 -1
- package/build/assets/conversation-HlncOV7n.js +19 -0
- package/build/assets/conversation-MtnkpqA9.js +1 -0
- package/build/assets/conversation-panel-DxnM6tRe.js +1 -0
- package/build/assets/{conversation-service.api--f8WglOC.js → conversation-service.api-nb5W1PqR.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-D8dNvo-V.js → conversation-tab-empty-state-DyssnnWa.js} +1 -1
- package/build/assets/conversation-websocket-context-C8_PkGLi.js +3 -0
- package/build/assets/{copy-C7Ti2d8C.js → copy-DYgmUdIw.js} +1 -1
- package/build/assets/{custom-toast-handlers-BOc3qeQ7.js → custom-toast-handlers-C-SZFmto.js} +1 -1
- package/build/assets/declaration-BNMqORFE.js +1 -0
- package/build/assets/{device-verify-CMusn8nX.js → device-verify-DqDlphsG.js} +1 -1
- package/build/assets/{dist-DZHSA2e6.js → dist-C6t0EXL7.js} +1 -1
- package/build/assets/{edit-automation-modal-Dnjxbjn7.js → edit-automation-modal-BGzR3nfZ.js} +1 -1
- package/build/assets/{ellipsis-button-ugUATsNo.js → ellipsis-button-ZyLMPURn.js} +1 -1
- package/build/assets/{entry.client-CqqXOSvd.js → entry.client-1VMHpktY.js} +2 -2
- package/build/assets/{enum-filter-dropdown-1vpOGySB.js → enum-filter-dropdown-CEgCdu4A.js} +1 -1
- package/build/assets/{environment-switch-overlay-CTCTQikP.js → environment-switch-overlay-XL8yCGP6.js} +1 -1
- package/build/assets/{extensions-hub-BSUseHVF.js → extensions-hub-C651jsVh.js} +1 -1
- package/build/assets/{extensions-navigation-CT1kc1u_.js → extensions-navigation-BYR8Giqq.js} +1 -1
- package/build/assets/files-tab-BhnLgimi.js +1 -0
- package/build/assets/{folder-0WSMImNX.js → folder-ZZJVGgd7.js} +1 -1
- package/build/assets/{git-control-bar-branch-button-C8u5rzjc.js → git-control-bar-branch-button-M34A5_vX.js} +2 -2
- package/build/assets/{git-provider-icon-D-a-rcLm.js → git-provider-icon-D5dCNy-k.js} +1 -1
- package/build/assets/home-CYQv7yc_.js +1 -0
- package/build/assets/{i18n-DjAGhTis.js → i18n-CTohRuoO.js} +1 -1
- package/build/assets/install-server-modal-f31_CLrW.js +1 -0
- package/build/assets/{launch-B2mbfOSm.js → launch-DHEUYn2A.js} +1 -1
- package/build/assets/{lesson-plan-DRYG5SLI.js → lesson-plan-dH5Bj0pN.js} +1 -1
- package/build/assets/{link-external-C9d6Fo3x.js → link-external-D2POYx4c.js} +1 -1
- package/build/assets/{llm-client-ChQzg4wX.js → llm-client-DaH1TuyR.js} +1 -1
- package/build/assets/llm-settings-Bql-vydt.js +1 -0
- package/build/assets/llm-settings-C_tal6Ds.js +1 -0
- package/build/assets/{loading-spinner-C04FGh14.js → loading-spinner-BPtYORNK.js} +1 -1
- package/build/assets/{manage-backends-modal-s22zCdEW.js → manage-backends-modal-l7RkKfwX.js} +1 -1
- package/build/assets/{manage-workspaces-modal-C5EuW8m1.js → manage-workspaces-modal-DhKF_8z3.js} +1 -1
- package/build/assets/manifest-6b31008e.js +1 -0
- package/build/assets/{markdown-renderer-CEX4Becj.js → markdown-renderer-DMzf2i4x.js} +1 -1
- package/build/assets/mcp-D2onbwVk.js +9 -0
- package/build/assets/{messages-6aOyUu3r.js → messages-BMzyOW2V.js} +1 -1
- package/build/assets/{modal-backdrop-DTYGVmOR.js → modal-backdrop-BAbgYsqB.js} +1 -1
- package/build/assets/{modal-body-YElmM1dV.js → modal-body-BI6Ru2Qr.js} +1 -1
- package/build/assets/{modal-close-button-C_GpQt9F.js → modal-close-button-t1Gh3qmL.js} +1 -1
- package/build/assets/{model-selector-DeMmw-Xa.js → model-selector-SM9IUz-q.js} +1 -1
- package/build/assets/{mutation-Cz7N4XAo.js → mutation-D0OogFCz.js} +1 -1
- package/build/assets/{navigation-context-DeIPtGPp.js → navigation-context-D0YWpT8d.js} +1 -1
- package/build/assets/{navigation-link-C9JD4PYD.js → navigation-link-Cn7KP3c5.js} +1 -1
- package/build/assets/{openhands-logo-CI5Fhn1W.js → openhands-logo-CnrF6LKb.js} +1 -1
- package/build/assets/{option-service.api-DsI1UW7N.js → option-service.api-KvY_mZMY.js} +1 -1
- package/build/assets/{organization-service.api-COwMPFg5.js → organization-service.api-DzYTHTYC.js} +1 -1
- package/build/assets/{path-utils-BVbe598W.js → path-utils-YohAYyMv.js} +1 -1
- package/build/assets/{plan-components-DEjMuDDG.js → plan-components-atxXCF0R.js} +1 -1
- package/build/assets/{planner-tab-bN6r1G-1.js → planner-tab-CFc-hV07.js} +1 -1
- package/build/assets/{profiles-client-BGkKEV9j.js → profiles-client-D6IkTJof.js} +1 -1
- package/build/assets/{providers-DXvCAN_u.js → providers-Bx6EfrzZ.js} +1 -1
- package/build/assets/{proxy-CurRmrqf.js → proxy-CxydCnis.js} +1 -1
- package/build/assets/{query-client-config-Ba7qAAoO.js → query-client-config-B7u9asM0.js} +1 -1
- package/build/assets/{recommended-automations-launcher-mJhK6Atl.js → recommended-automations-launcher-sgvfU62c.js} +3 -3
- package/build/assets/root-E6pcRIYp.js +2 -0
- package/build/assets/{root-layout-BjVwHmta.js → root-layout-DVepR4To.js} +2 -2
- package/build/assets/sdk-section-page-DOIKvwSL.js +1 -0
- package/build/assets/{sdk-settings-schema-QBYH-ONX.js → sdk-settings-schema-DsUf9wu1.js} +1 -1
- package/build/assets/{search-Cq_cFrDt.js → search-27Owlc3A.js} +1 -1
- package/build/assets/{secrets-service-Bwd5DeUs.js → secrets-service-BsnKFc2x.js} +1 -1
- package/build/assets/secrets-settings-Bz_UohPJ.js +1 -0
- package/build/assets/{server-client-C3mC8Hl3.js → server-client-DyAQ3NZ_.js} +1 -1
- package/build/assets/{settings-D7E2U5tK.js → settings-BYkVX7vW.js} +1 -1
- package/build/assets/{settings-client-CwjfwoiB.js → settings-client-C73C7IgV.js} +1 -1
- package/build/assets/{settings-dropdown-input-VwAXNrOb.js → settings-dropdown-input-BJYvGdg-.js} +1 -1
- package/build/assets/{settings-gear-BJwWR1ej.js → settings-gear-C77PgE_O.js} +1 -1
- package/build/assets/{settings-index-J-3BNR0W.js → settings-index-Dz0BmdJD.js} +1 -1
- package/build/assets/{settings-input-DBywAnA7.js → settings-input-Bn7F5C75.js} +1 -1
- package/build/assets/{settings-list-classes-BOS092DR.js → settings-list-classes-Bf80tWtc.js} +1 -1
- package/build/assets/{settings-modal-B8vgWDTe.js → settings-modal-Brzgh5Yw.js} +1 -1
- package/build/assets/{settings-section-header-context-32x6WTyL.js → settings-section-header-context-BgZe5YkE.js} +1 -1
- package/build/assets/{settings-service.api-FvJGK45W.js → settings-service.api-CZ3uWx4v.js} +1 -1
- package/build/assets/{settings-switch-DTKmHC8F.js → settings-switch-BeIKrWms.js} +1 -1
- package/build/assets/{shared-conversation-EZV0FRIf.js → shared-conversation-DChOdb0t.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-BnbzzpQl.js → sidebar-mobile-menu-toggle-BWuf4PRH.js} +1 -1
- package/build/assets/{sidebar-nav-link-CnWoZcwc.js → sidebar-nav-link-BGjiJq-4.js} +1 -1
- package/build/assets/{skill-card-pill-row-tZ599jli.js → skill-card-pill-row-DF1axQCG.js} +1 -1
- package/build/assets/{skills-ZyAO5dyK.js → skills-ChIKZPK4.js} +1 -1
- package/build/assets/{skills-plugins-BSRz041I.js → skills-plugins-CcI_19lM.js} +1 -1
- package/build/assets/{skills-settings-CG2hu34D.js → skills-settings-DlA5hlXw.js} +1 -1
- package/build/assets/{status-CsatcFbK.js → status-hp6M6E7E.js} +1 -1
- package/build/assets/{styled-tooltip-CS3mB_1X.js → styled-tooltip-CBzrri6o.js} +1 -1
- package/build/assets/{switch-skeleton-C-CfhYYV.js → switch-skeleton-DnC9wLp7.js} +1 -1
- package/build/assets/{task-list-tab-465DDju0.js → task-list-tab-DUJn1sgz.js} +1 -1
- package/build/assets/{terminal-CcgBEVnC.js → terminal-CRf9S0Z2.js} +1 -1
- package/build/assets/{terminal-LNa-iU5c.js → terminal-RmuaSdhJ.js} +1 -1
- package/build/assets/{toggle-switch-k-IZCDbt.js → toggle-switch-Pvyp2RAN.js} +1 -1
- package/build/assets/{typography-vVUMoNUg.js → typography-gpuWmrQO.js} +1 -1
- package/build/assets/{u-check-circle-DplbarS5.js → u-check-circle-IUIfACQQ.js} +1 -1
- package/build/assets/{u-check-circle-half-yDuiSZHC.js → u-check-circle-half-C1YxB6py.js} +1 -1
- package/build/assets/{u-circuit-C9tYkpeK.js → u-circuit-BmVikJHu.js} +1 -1
- package/build/assets/{u-edit-KAUlufD8.js → u-edit-CFvXHqZk.js} +1 -1
- package/build/assets/use-active-conversation-Db3IWSPK.js +1 -0
- package/build/assets/{use-agent-settings-schema-Bvp5UzV8.js → use-agent-settings-schema-33Un7UF2.js} +1 -1
- package/build/assets/{use-agent-state-D2C9SeGw.js → use-agent-state-Bn8vS5sY.js} +1 -1
- package/build/assets/{use-cloud-current-user-id-DWVar4st.js → use-cloud-current-user-id-CvkXFnTT.js} +1 -1
- package/build/assets/use-config-Co1O8-Ey.js +1 -0
- package/build/assets/{use-create-conversation-BEZg__Vv.js → use-create-conversation-CKS3EAHu.js} +1 -1
- package/build/assets/use-get-secrets-DuhdIA59.js +1 -0
- package/build/assets/{use-handle-plan-click-uOpew2LO.js → use-handle-plan-click-C9zJpK8A.js} +1 -1
- package/build/assets/use-is-authed-BggE5wPj.js +1 -0
- package/build/assets/{use-is-creating-conversation-DhDeeWfA.js → use-is-creating-conversation-BZ5hB_Bg.js} +1 -1
- package/build/assets/{use-launch-skill-in-chat-DVGPFrbI.js → use-launch-skill-in-chat-fNN_xGZG.js} +1 -1
- package/build/assets/{use-llm-profiles-O4a9V6RC.js → use-llm-profiles-DDOol3gK.js} +1 -1
- package/build/assets/use-runtime-is-ready-CQCE3xZC.js +1 -0
- package/build/assets/{use-save-settings-CEEKSTWG.js → use-save-settings-VUrj_QNG.js} +1 -1
- package/build/assets/{use-settings-DQ7Oo1Hj.js → use-settings-DQIZmIov.js} +1 -1
- package/build/assets/{use-settings-nav-items-YmrXrjn9.js → use-settings-nav-items-1ZvovKSr.js} +1 -1
- package/build/assets/{use-skills-BIvlWblA.js → use-skills-DAMLFjKU.js} +1 -1
- package/build/assets/use-unified-vscode-url-sZt29HrC.js +1 -0
- package/build/assets/use-user-conversation-DfgEB6RW.js +1 -0
- package/build/assets/{useMutation-B4OUESdw.js → useMutation-DqrumCWD.js} +1 -1
- package/build/assets/{useTranslation-CpIcQBq6.js → useTranslation-DCOdSSMl.js} +1 -1
- package/build/assets/{utils-D-HX7JCe.js → utils-i18rdUj2.js} +1 -1
- package/build/assets/v4-CNn21NXa.js +1 -0
- package/build/assets/{vendor~browser-Dr71AdrG.js → vendor~browser-BNjNhjFU.js} +1 -1
- package/build/assets/{vendor~browser-tab-BiVxfjJo.js → vendor~browser-tab-BgwV1mxF.js} +1 -1
- package/build/assets/{vendor~conversation-panel~conversation-BlCIz9XQ.js → vendor~conversation-panel~conversation-a9SyrrhV.js} +1 -1
- package/build/assets/{vendor~files-tab-DtLR-QD9.js → vendor~files-tab-BGKayPiK.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Ds9quNZ9.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-smY2r837.js} +1 -1
- package/build/assets/{vendor~home~mcp~automations-list-C5PoHCy6.js → vendor~home~mcp~automations-list-Ccy2I0KU.js} +1 -1
- package/build/assets/{vendor~home~mcp~automations-list-BUBGGGYz.js → vendor~home~mcp~automations-list-DoPfwaXj.js} +1 -1
- package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-CGlZoBKa.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-DbfELDJu.js} +2 -2
- package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-DE11mPxp.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-Z3nsiNNq.js} +1 -1
- package/build/assets/{vendor~launch-Dg--Ssk6.js → vendor~launch-vdeRTWFu.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-DrXgiSCq.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-DW31UyBp.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-8b8V5bfO.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-BkQGKpye.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-Dy7L6fMG.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-DzIXV3Ui.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-D40EXhZx.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-Bbs7UJ5U.js} +2 -2
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-CHrEOFl6.js → vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-DTwbEEcX.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-BP1SKG0F.js → vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-d2oallMa.js} +1 -1
- package/build/assets/{vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~kyz9p27j-CyUbhpbm.js → vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~f2l2lr17-CDXvdvb2.js} +1 -1
- package/build/assets/{verification-settings-BtlTiHP8.js → verification-settings-CsbvQcYS.js} +1 -1
- package/build/assets/{vscode-tab-B0vdh9gU.js → vscode-tab-Zb-QbTuV.js} +1 -1
- package/build/assets/{waiting-for-runtime-message-DWPl_Yby.js → waiting-for-runtime-message-CntjExbU.js} +1 -1
- package/build/assets/{x-mark-CWI0f9yI.js → x-mark-CrpjscNc.js} +1 -1
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +7 -0
- package/build/locales/ca/openhands.json +7 -0
- package/build/locales/de/openhands.json +7 -0
- package/build/locales/en/openhands.json +7 -0
- package/build/locales/es/openhands.json +7 -0
- package/build/locales/fr/openhands.json +7 -0
- package/build/locales/it/openhands.json +7 -0
- package/build/locales/ja/openhands.json +7 -0
- package/build/locales/ko-KR/openhands.json +7 -0
- package/build/locales/no/openhands.json +7 -0
- package/build/locales/pt/openhands.json +7 -0
- package/build/locales/tr/openhands.json +7 -0
- package/build/locales/uk/openhands.json +7 -0
- package/build/locales/zh-CN/openhands.json +7 -0
- package/build/locales/zh-TW/openhands.json +7 -0
- package/config/defaults.json +0 -4
- package/dist/api/agent-server-adapter.cjs +1 -1
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.js +1 -1
- 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 +16 -0
- package/dist/api/agent-server-compatibility.js +31 -20
- package/dist/api/agent-server-compatibility.js.map +1 -1
- package/dist/api/agent-server-config.cjs +1 -1
- package/dist/api/agent-server-config.cjs.map +1 -1
- package/dist/api/agent-server-config.d.ts +45 -0
- package/dist/api/agent-server-config.js +49 -21
- package/dist/api/agent-server-config.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 +34 -32
- package/dist/api/backend-registry/storage.js.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +5 -4
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +70 -76
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/components/features/backends/api-key-entry-screen.d.ts +10 -0
- package/dist/components/features/backends/backend-form-modal.cjs +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
- package/dist/components/features/backends/backend-form-modal.d.ts +23 -2
- package/dist/components/features/backends/backend-form-modal.js +43 -38
- package/dist/components/features/backends/backend-form-modal.js.map +1 -1
- package/dist/components/features/browser/browser.cjs +1 -1
- package/dist/components/features/browser/browser.cjs.map +1 -1
- package/dist/components/features/browser/browser.js +10 -16
- package/dist/components/features/browser/browser.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 +123 -116
- package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
- package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
- package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
- package/dist/components/features/mcp-page/installed-server-card.js +40 -40
- package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
- package/dist/components/features/mcp-page/marketplace-card.cjs +1 -1
- package/dist/components/features/mcp-page/marketplace-card.cjs.map +1 -1
- package/dist/components/features/mcp-page/marketplace-card.js +2 -3
- package/dist/components/features/mcp-page/marketplace-card.js.map +1 -1
- package/dist/components/features/mcp-page/marketplace-section.cjs +1 -1
- package/dist/components/features/mcp-page/marketplace-section.cjs.map +1 -1
- package/dist/components/features/mcp-page/marketplace-section.js +21 -21
- package/dist/components/features/mcp-page/marketplace-section.js.map +1 -1
- package/dist/components/features/onboarding/steps/setup-acp-secrets-step.d.ts +27 -0
- package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
- package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +2 -0
- package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs.map +1 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.d.ts +10 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.js +87 -84
- package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
- package/dist/constants/acp-providers.cjs +1 -1
- package/dist/constants/acp-providers.cjs.map +1 -1
- package/dist/constants/acp-providers.d.ts +25 -0
- package/dist/constants/acp-providers.js +1 -0
- package/dist/constants/acp-providers.js.map +1 -1
- package/dist/contexts/conversation-websocket-context.cjs +3 -3
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js +136 -132
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/hooks/chat/use-model-interceptor.cjs.map +1 -1
- package/dist/hooks/chat/use-model-interceptor.js.map +1 -1
- package/dist/hooks/mutation/use-switch-llm-profile.cjs.map +1 -1
- package/dist/hooks/mutation/use-switch-llm-profile.d.ts +1 -1
- package/dist/hooks/mutation/use-switch-llm-profile.js.map +1 -1
- package/dist/hooks/query/use-config.cjs +1 -1
- package/dist/hooks/query/use-config.cjs.map +1 -1
- package/dist/hooks/query/use-config.js +10 -10
- package/dist/hooks/query/use-config.js.map +1 -1
- package/dist/hooks/query/use-local-git-info.cjs +3 -3
- package/dist/hooks/query/use-local-git-info.cjs.map +1 -1
- package/dist/hooks/query/use-local-git-info.js +24 -25
- package/dist/hooks/query/use-local-git-info.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 +7 -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 +119 -0
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +7 -0
- package/dist/locales/ca/openhands.json +7 -0
- package/dist/locales/de/openhands.json +7 -0
- package/dist/locales/en/openhands.json +7 -0
- package/dist/locales/es/openhands.json +7 -0
- package/dist/locales/fr/openhands.json +7 -0
- package/dist/locales/it/openhands.json +7 -0
- package/dist/locales/ja/openhands.json +7 -0
- package/dist/locales/ko-KR/openhands.json +7 -0
- package/dist/locales/no/openhands.json +7 -0
- package/dist/locales/pt/openhands.json +7 -0
- package/dist/locales/tr/openhands.json +7 -0
- package/dist/locales/uk/openhands.json +7 -0
- package/dist/locales/zh-CN/openhands.json +7 -0
- package/dist/locales/zh-TW/openhands.json +7 -0
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/dist/routes/mcp.cjs +1 -1
- package/dist/routes/mcp.cjs.map +1 -1
- package/dist/routes/mcp.js +64 -64
- package/dist/routes/mcp.js.map +1 -1
- package/dist/stores/browser-store.cjs +1 -1
- package/dist/stores/browser-store.cjs.map +1 -1
- package/dist/stores/browser-store.js +1 -1
- package/dist/stores/browser-store.js.map +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
- package/dist/utils/mcp-marketplace-utils.d.ts +13 -22
- package/dist/utils/mcp-marketplace-utils.js +46 -28
- 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.d.ts +1 -0
- package/dist/utils/sdk-settings-schema.js +1 -1
- package/dist/utils/sdk-settings-schema.js.map +1 -1
- package/package.json +1 -1
- package/scripts/dev-safe.mjs +59 -40
- package/scripts/dev-static.mjs +2 -3
- package/scripts/dev-with-automation.mjs +75 -19
- package/scripts/static-server.mjs +77 -35
- package/tools/canvas_ui_tool.py +4 -0
- package/build/assets/acp-providers-DauuOsW9.js +0 -1
- package/build/assets/add-backend-modal-FsnpTTgO.js +0 -1
- package/build/assets/agent-server-client-options-DT2GP6VJ.js +0 -1
- package/build/assets/agent-server-compatibility-2aOx5iWd.js +0 -1
- package/build/assets/agent-server-conversation-service.api-BZmUqtiO.js +0 -5
- package/build/assets/browser-store-C3AqxAO7.js +0 -1
- package/build/assets/browser-tab-B_BuTvrO.js +0 -1
- package/build/assets/conversation--ldUK72N.js +0 -19
- package/build/assets/conversation-eNrhH94O.js +0 -1
- package/build/assets/conversation-panel-B49Jpqpb.js +0 -1
- package/build/assets/conversation-websocket-context-BW68-J8o.js +0 -3
- package/build/assets/declaration-D378OjpZ.js +0 -1
- package/build/assets/files-tab-CQHdWpQt.js +0 -1
- package/build/assets/home-DD0GroCu.js +0 -1
- package/build/assets/install-server-modal-z5VaHeXd.js +0 -1
- package/build/assets/llm-settings-BEyqixPI.js +0 -1
- package/build/assets/llm-settings-BdiaGFbg.js +0 -1
- package/build/assets/manifest-9d1c34fb.js +0 -1
- package/build/assets/mcp-C06YssEI.js +0 -9
- package/build/assets/root-3t9rxEpE.js +0 -2
- package/build/assets/sdk-section-page-CJW0G04-.js +0 -1
- package/build/assets/secrets-settings-MLXqOtX2.js +0 -1
- package/build/assets/use-active-conversation-DS5j9R4q.js +0 -1
- package/build/assets/use-config-BSu_53GL.js +0 -1
- package/build/assets/use-conversation-id-DajhCn2A.js +0 -1
- package/build/assets/use-is-authed-hXC8vxgT.js +0 -1
- package/build/assets/use-runtime-is-ready-pGSbPddC.js +0 -1
- package/build/assets/use-unified-vscode-url-wAMzv8Sn.js +0 -1
- package/build/assets/use-user-conversation-B_zDoSeh.js +0 -1
- /package/build/assets/{automation-XLxhq3I8.js → automation-IdgZq6ZK.js} +0 -0
- /package/build/assets/{common-SMkEaBSr.js → common-DR1t-EeP.js} +0 -0
- /package/build/assets/{conversation-state-store-Bc0slAjL.js → conversation-state-store-u5jepov0.js} +0 -0
- /package/build/assets/{dist-yMQV8IUk.js → dist-BxBP7tFD.js} +0 -0
- /package/build/assets/{git-status-mapper-BI8FyUVp.js → git-status-mapper-DnL9OC8_.js} +0 -0
- /package/build/assets/{handle-capture-consent-BfZATzpI.js → handle-capture-consent-3XrjZ8wi.js} +0 -0
- /package/build/assets/{iconBase-C7N9pPOs.js → iconBase-DE30Zj_-.js} +0 -0
- /package/build/assets/{settings-D5am1n6X.js → settings-D_H-qsRm.js} +0 -0
- /package/build/assets/{settings-like-page-layout-classes-Bn-M9oOa.js → settings-like-page-layout-classes-I0BDBEoq.js} +0 -0
- /package/build/assets/{settings-utils-BsvSU3OM.js → settings-utils-B6Nl07io.js} +0 -0
- /package/build/assets/{sidebar-store-cOeaKmIm.js → sidebar-store-Uy3v0AOV.js} +0 -0
- /package/build/assets/{use-breakpoint-B86yKT9n.js → use-breakpoint-DbJ6FkQ-.js} +0 -0
- /package/build/assets/{use-click-outside-element-835W9pC6.js → use-click-outside-element-DffgWWoZ.js} +0 -0
- /package/build/assets/{use-task-list-DDeNHprj.js → use-task-list-CLJbuJgM.js} +0 -0
- /package/build/assets/{vendor~browser-BpdPBhgZ.js → vendor~browser-DDiZgqD3.js} +0 -0
- /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-Df7_G0zR.js → vendor~conversation-panel~conversation~alert-banner-DbvX3OcM.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~b4cctr4k-B7YVdv1X.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~g56ukk6u-DsSvIDZQ.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~i9dbt75i-CI82Did1.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~hkqzh1hb-BZ0HXuHD.js} +0 -0
- /package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~pfbaerbd-zhv9fooy.js → vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~ninslayh-D9P8e98a.js} +0 -0
- /package/build/assets/{vendor~terminal-BUxzHKcC.js → vendor~terminal-DUrOWGFE.js} +0 -0
- /package/build/assets/{vscode-url-helper-jesbpos5.js → vscode-url-helper-Cwy1A62q.js} +0 -0
|
@@ -2,15 +2,15 @@ import { useTranslation as e } from "../../../node_modules/react-i18next/dist/es
|
|
|
2
2
|
import { I18nKey as t } from "../../../i18n/declaration.js";
|
|
3
3
|
import { cn as n } from "../../../utils/utils.js";
|
|
4
4
|
import { Puzzle as r } from "../../../node_modules/lucide-react/dist/esm/icons/puzzle.js";
|
|
5
|
-
import { findCatalogEntryForServer as i } from "../../../utils/mcp-marketplace-utils.js";
|
|
6
|
-
import
|
|
7
|
-
import { McpLogoBadge as
|
|
8
|
-
import { CirclePlusCheckToggle as
|
|
9
|
-
import { extensionModuleCardInteractiveClassName as
|
|
5
|
+
import { findCatalogEntryForServer as i, getMcpMarketplaceCatalog as a } from "../../../utils/mcp-marketplace-utils.js";
|
|
6
|
+
import o from "../../../node_modules/@openhands/extensions/integrations/index.js";
|
|
7
|
+
import { McpLogoBadge as s } from "../mcp-logo-badge.js";
|
|
8
|
+
import { CirclePlusCheckToggle as c } from "../../shared/buttons/circle-plus-check-toggle.js";
|
|
9
|
+
import { extensionModuleCardInteractiveClassName as l, extensionModuleCardSurfaceClassName as u } from "../../../utils/extension-module-card-classes.js";
|
|
10
10
|
import "react";
|
|
11
|
-
import { jsx as
|
|
11
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
12
12
|
//#region src/components/features/mcp-page/installed-server-card.tsx
|
|
13
|
-
function
|
|
13
|
+
function p(e) {
|
|
14
14
|
switch (e) {
|
|
15
15
|
case "sse": return "SSE";
|
|
16
16
|
case "shttp": return "HTTP";
|
|
@@ -18,69 +18,69 @@ function f(e) {
|
|
|
18
18
|
default: return e;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function m(e) {
|
|
22
22
|
return e.type === "stdio" ? e.name ?? e.command ?? "" : e.url ?? "";
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function h(e) {
|
|
25
25
|
if (e.type === "stdio") {
|
|
26
26
|
let t = e.args && e.args.length > 0 ? ` ${e.args.join(" ")}` : "";
|
|
27
27
|
return `${e.command ?? ""}${t}`.trim();
|
|
28
28
|
}
|
|
29
29
|
return e.url ?? "";
|
|
30
30
|
}
|
|
31
|
-
function
|
|
32
|
-
let { t:
|
|
33
|
-
return /* @__PURE__ */
|
|
31
|
+
function g({ server: g, onEdit: _, onDelete: v }) {
|
|
32
|
+
let { t: y } = e("openhands"), b = i(g, a(o)), x = b?.name ?? m(g), S = h(g), C = p(g.type);
|
|
33
|
+
return /* @__PURE__ */ d("div", {
|
|
34
34
|
"data-testid": "mcp-server-item",
|
|
35
|
-
"data-server-id":
|
|
35
|
+
"data-server-id": g.id,
|
|
36
36
|
role: "button",
|
|
37
37
|
tabIndex: 0,
|
|
38
|
-
onClick:
|
|
38
|
+
onClick: _,
|
|
39
39
|
onKeyDown: (e) => {
|
|
40
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(),
|
|
40
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), _());
|
|
41
41
|
},
|
|
42
|
-
"aria-label":
|
|
43
|
-
className: n("flex min-h-[132px] flex-col overflow-hidden p-4 text-left",
|
|
44
|
-
children: /* @__PURE__ */
|
|
42
|
+
"aria-label": y(t.MCP$EDIT_SERVER_ARIA, { name: x }),
|
|
43
|
+
className: n("flex min-h-[132px] flex-col overflow-hidden p-4 text-left", u, l),
|
|
44
|
+
children: /* @__PURE__ */ f("div", {
|
|
45
45
|
className: "flex items-start gap-3",
|
|
46
|
-
children: [/* @__PURE__ */
|
|
47
|
-
entry:
|
|
48
|
-
fallback: /* @__PURE__ */
|
|
49
|
-
}), /* @__PURE__ */
|
|
46
|
+
children: [/* @__PURE__ */ d(s, {
|
|
47
|
+
entry: b,
|
|
48
|
+
fallback: /* @__PURE__ */ d(r, { strokeWidth: 2.25 })
|
|
49
|
+
}), /* @__PURE__ */ f("div", {
|
|
50
50
|
className: "flex min-w-0 flex-1 flex-col gap-3",
|
|
51
51
|
children: [
|
|
52
|
-
/* @__PURE__ */
|
|
52
|
+
/* @__PURE__ */ f("header", {
|
|
53
53
|
className: "flex items-start justify-between gap-3",
|
|
54
|
-
children: [/* @__PURE__ */
|
|
54
|
+
children: [/* @__PURE__ */ f("div", {
|
|
55
55
|
className: "min-w-0 flex-1",
|
|
56
|
-
children: [/* @__PURE__ */
|
|
56
|
+
children: [/* @__PURE__ */ d("h3", {
|
|
57
57
|
className: "truncate text-sm font-semibold",
|
|
58
|
-
title:
|
|
59
|
-
children:
|
|
60
|
-
}), /* @__PURE__ */
|
|
58
|
+
title: x,
|
|
59
|
+
children: x
|
|
60
|
+
}), /* @__PURE__ */ d("p", {
|
|
61
61
|
className: "mt-0.5 text-xs text-tertiary-alt",
|
|
62
|
-
children:
|
|
62
|
+
children: C
|
|
63
63
|
})]
|
|
64
|
-
}), /* @__PURE__ */
|
|
65
|
-
testId: `mcp-installed-toggle-${
|
|
64
|
+
}), /* @__PURE__ */ d(c, {
|
|
65
|
+
testId: `mcp-installed-toggle-${g.id}`,
|
|
66
66
|
isSelected: !0,
|
|
67
67
|
onToggle: (e) => {
|
|
68
|
-
e ||
|
|
68
|
+
e || v();
|
|
69
69
|
},
|
|
70
70
|
enableLabelKey: t.MCP$TOGGLE_ADD_SERVER,
|
|
71
71
|
disableLabelKey: t.MCP$TOGGLE_REMOVE_SERVER
|
|
72
72
|
})]
|
|
73
73
|
}),
|
|
74
|
-
|
|
75
|
-
"data-testid": `mcp-server-description-${
|
|
74
|
+
b?.description ? /* @__PURE__ */ d("p", {
|
|
75
|
+
"data-testid": `mcp-server-description-${g.id}`,
|
|
76
76
|
className: "line-clamp-2 break-words text-xs leading-relaxed text-tertiary-light",
|
|
77
|
-
children:
|
|
77
|
+
children: b.description
|
|
78
78
|
}) : null,
|
|
79
|
-
|
|
80
|
-
"data-testid": `mcp-server-detail-${
|
|
79
|
+
S ? /* @__PURE__ */ d("p", {
|
|
80
|
+
"data-testid": `mcp-server-detail-${g.id}`,
|
|
81
81
|
className: "truncate text-xs text-tertiary-alt",
|
|
82
|
-
title:
|
|
83
|
-
children:
|
|
82
|
+
title: S,
|
|
83
|
+
children: S
|
|
84
84
|
}) : null
|
|
85
85
|
]
|
|
86
86
|
})]
|
|
@@ -88,6 +88,6 @@ function h({ server: h, onEdit: g, onDelete: _ }) {
|
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
//#endregion
|
|
91
|
-
export {
|
|
91
|
+
export { g as InstalledServerCard };
|
|
92
92
|
|
|
93
93
|
//# sourceMappingURL=installed-server-card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installed-server-card.js","names":[],"sources":["../../../../src/components/features/mcp-page/installed-server-card.tsx"],"sourcesContent":["import React from \"react\";\nimport { Puzzle } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { CirclePlusCheckToggle } from \"#/components/shared/buttons/circle-plus-check-toggle\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport { INTEGRATION_CATALOG as
|
|
1
|
+
{"version":3,"file":"installed-server-card.js","names":[],"sources":["../../../../src/components/features/mcp-page/installed-server-card.tsx"],"sourcesContent":["import React from \"react\";\nimport { Puzzle } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { CirclePlusCheckToggle } from \"#/components/shared/buttons/circle-plus-check-toggle\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport { INTEGRATION_CATALOG as MCP_MARKETPLACE } from \"@openhands/extensions/integrations\";\nimport {\n findCatalogEntryForServer,\n getMcpMarketplaceCatalog,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { cn } from \"#/utils/utils\";\nimport {\n extensionModuleCardInteractiveClassName,\n extensionModuleCardSurfaceClassName,\n} from \"#/utils/extension-module-card-classes\";\n\ninterface InstalledServerCardProps {\n server: MCPServerConfig;\n onEdit: () => void;\n onDelete: () => void;\n}\n\nfunction getServerTransportLabel(type: MCPServerConfig[\"type\"]) {\n switch (type) {\n case \"sse\":\n return \"SSE\";\n case \"shttp\":\n return \"HTTP\";\n case \"stdio\":\n return \"STDIO\";\n default:\n return type;\n }\n}\n\nfunction getServerTitle(server: MCPServerConfig): string {\n if (server.type === \"stdio\") return server.name ?? server.command ?? \"\";\n return server.url ?? \"\";\n}\n\nfunction getServerDetailLine(server: MCPServerConfig): string {\n if (server.type === \"stdio\") {\n const args =\n server.args && server.args.length > 0 ? ` ${server.args.join(\" \")}` : \"\";\n return `${server.command ?? \"\"}${args}`.trim();\n }\n return server.url ?? \"\";\n}\n\nexport function InstalledServerCard({\n server,\n onEdit,\n onDelete,\n}: InstalledServerCardProps) {\n const { t } = useTranslation(\"openhands\");\n const catalog = findCatalogEntryForServer(\n server,\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n );\n\n const title = catalog?.name ?? getServerTitle(server);\n const detailLine = getServerDetailLine(server);\n const transport = getServerTransportLabel(server.type);\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onEdit();\n }\n };\n\n return (\n <div\n data-testid=\"mcp-server-item\"\n data-server-id={server.id}\n role=\"button\"\n tabIndex={0}\n onClick={onEdit}\n onKeyDown={handleKeyDown}\n aria-label={t(I18nKey.MCP$EDIT_SERVER_ARIA, { name: title })}\n className={cn(\n \"flex min-h-[132px] flex-col overflow-hidden p-4 text-left\",\n extensionModuleCardSurfaceClassName,\n extensionModuleCardInteractiveClassName,\n )}\n >\n <div className=\"flex items-start gap-3\">\n <McpLogoBadge\n entry={catalog}\n fallback={<Puzzle strokeWidth={2.25} />}\n />\n\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n <header className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate text-sm font-semibold\" title={title}>\n {title}\n </h3>\n <p className=\"mt-0.5 text-xs text-tertiary-alt\">{transport}</p>\n </div>\n <CirclePlusCheckToggle\n testId={`mcp-installed-toggle-${server.id}`}\n isSelected\n onToggle={(selected) => {\n if (!selected) {\n onDelete();\n }\n }}\n enableLabelKey={I18nKey.MCP$TOGGLE_ADD_SERVER}\n disableLabelKey={I18nKey.MCP$TOGGLE_REMOVE_SERVER}\n />\n </header>\n\n {catalog?.description ? (\n <p\n data-testid={`mcp-server-description-${server.id}`}\n className=\"line-clamp-2 break-words text-xs leading-relaxed text-tertiary-light\"\n >\n {catalog.description}\n </p>\n ) : null}\n\n {detailLine ? (\n <p\n data-testid={`mcp-server-detail-${server.id}`}\n className=\"truncate text-xs text-tertiary-alt\"\n title={detailLine}\n >\n {detailLine}\n </p>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAwBA,SAAS,EAAwB,GAA+B;AAC9D,SAAQ,GAAR;EACE,KAAK,MACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAS,EAAe,GAAiC;AAEvD,QADI,EAAO,SAAS,UAAgB,EAAO,QAAQ,EAAO,WAAW,KAC9D,EAAO,OAAO;;AAGvB,SAAS,EAAoB,GAAiC;AAC5D,KAAI,EAAO,SAAS,SAAS;EAC3B,IAAM,IACJ,EAAO,QAAQ,EAAO,KAAK,SAAS,IAAI,IAAI,EAAO,KAAK,KAAK,IAAI,KAAK;AACxE,SAAO,GAAG,EAAO,WAAW,KAAK,IAAO,MAAM;;AAEhD,QAAO,EAAO,OAAO;;AAGvB,SAAgB,EAAoB,EAClC,WACA,WACA,eAC2B;CAC3B,IAAM,EAAE,SAAM,EAAe,YAAY,EACnC,IAAU,EACd,GACA,EAAyB,EAAgB,CAC1C,EAEK,IAAQ,GAAS,QAAQ,EAAe,EAAO,EAC/C,IAAa,EAAoB,EAAO,EACxC,IAAY,EAAwB,EAAO,KAAK;AAStD,QACE,kBAAC,OAAD;EACE,eAAY;EACZ,kBAAgB,EAAO;EACvB,MAAK;EACL,UAAU;EACV,SAAS;EACT,YAdmB,MAA+B;AACpD,IAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EACtB,GAAQ;;EAYR,cAAY,EAAE,EAAQ,sBAAsB,EAAE,MAAM,GAAO,CAAC;EAC5D,WAAW,EACT,6DACA,GACA,EACD;YAED,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IACE,OAAO;IACP,UAAU,kBAAC,GAAD,EAAQ,aAAa,MAAQ,CAAA;IACvC,CAAA,EAEF,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,UAAD;MAAQ,WAAU;gBAAlB,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,MAAD;QAAI,WAAU;QAAwC;kBACnD;QACE,CAAA,EACL,kBAAC,KAAD;QAAG,WAAU;kBAAoC;QAAc,CAAA,CAC3D;UACN,kBAAC,GAAD;OACE,QAAQ,wBAAwB,EAAO;OACvC,YAAA;OACA,WAAW,MAAa;AACtB,QAAK,KACH,GAAU;;OAGd,gBAAgB,EAAQ;OACxB,iBAAiB,EAAQ;OACzB,CAAA,CACK;;KAER,GAAS,cACR,kBAAC,KAAD;MACE,eAAa,0BAA0B,EAAO;MAC9C,WAAU;gBAET,EAAQ;MACP,CAAA,GACF;KAEH,IACC,kBAAC,KAAD;MACE,eAAa,qBAAqB,EAAO;MACzC,WAAU;MACV,OAAO;gBAEN;MACC,CAAA,GACF;KACA;MACF;;EACF,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../i18n/declaration.cjs`),t=require(`../../../utils/utils.cjs`),n=require(`../../../utils/mcp-marketplace-utils.cjs`),r=require(`../mcp-logo-badge.cjs`),i=require(`../../shared/buttons/circle-plus-check-toggle.cjs`),a=require(`../../../utils/extension-module-card-classes.cjs`);let o=require(`react/jsx-runtime`);function s({entry:s,onClick:c,onAdd:l}){let u=n.
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../i18n/declaration.cjs`),t=require(`../../../utils/utils.cjs`),n=require(`../../../utils/mcp-marketplace-utils.cjs`),r=require(`../mcp-logo-badge.cjs`),i=require(`../../shared/buttons/circle-plus-check-toggle.cjs`),a=require(`../../../utils/extension-module-card-classes.cjs`);let o=require(`react/jsx-runtime`);function s({entry:s,onClick:c,onAdd:l}){let u=n.getDefaultMcpTransport(s),d=(()=>{switch(u?.kind){case`stdio`:return`STDIO`;case`shttp`:return`HTTP`;case`sse`:return`SSE`;default:return``}})();return(0,o.jsx)(`button`,{type:`button`,onClick:c,"data-testid":`mcp-marketplace-card-${s.id}`,className:t.cn(`flex min-h-[132px] flex-col overflow-hidden p-4 text-left`,a.extensionModuleCardSurfaceClassName,a.extensionModuleCardInteractiveClassName),children:(0,o.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,o.jsx)(r.McpLogoBadge,{entry:s}),(0,o.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-3`,children:[(0,o.jsxs)(`header`,{className:`flex items-start justify-between gap-3`,children:[(0,o.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,o.jsx)(`h3`,{className:`truncate text-sm font-semibold`,children:s.name}),(0,o.jsx)(`p`,{className:`mt-0.5 text-xs text-tertiary-alt`,children:d})]}),(0,o.jsx)(i.CirclePlusCheckToggle,{testId:`mcp-marketplace-toggle-${s.id}`,isSelected:!1,onToggle:e=>{e&&l()},enableLabelKey:e.I18nKey.MCP$TOGGLE_ADD_SERVER,disableLabelKey:e.I18nKey.MCP$TOGGLE_ADD_SERVER})]}),(0,o.jsx)(`p`,{className:`line-clamp-3 text-xs leading-relaxed text-tertiary-light`,children:s.description})]})]})})}exports.MarketplaceCard=s;
|
|
2
2
|
//# sourceMappingURL=marketplace-card.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-card.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-card.tsx"],"sourcesContent":["import { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport {
|
|
1
|
+
{"version":3,"file":"marketplace-card.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-card.tsx"],"sourcesContent":["import { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { CirclePlusCheckToggle } from \"#/components/shared/buttons/circle-plus-check-toggle\";\nimport { getDefaultMcpTransport } from \"#/utils/mcp-marketplace-utils\";\nimport { cn } from \"#/utils/utils\";\nimport {\n extensionModuleCardInteractiveClassName,\n extensionModuleCardSurfaceClassName,\n} from \"#/utils/extension-module-card-classes\";\n\ninterface MarketplaceCardProps {\n entry: MarketplaceEntry;\n onClick: () => void;\n onAdd: () => void;\n}\n\nexport function MarketplaceCard({\n entry,\n onClick,\n onAdd,\n}: MarketplaceCardProps) {\n const transport = getDefaultMcpTransport(entry);\n const transportLabel = (() => {\n switch (transport?.kind) {\n case \"stdio\":\n return \"STDIO\";\n case \"shttp\":\n return \"HTTP\";\n case \"sse\":\n return \"SSE\";\n default:\n return \"\";\n }\n })();\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n data-testid={`mcp-marketplace-card-${entry.id}`}\n className={cn(\n \"flex min-h-[132px] flex-col overflow-hidden p-4 text-left\",\n extensionModuleCardSurfaceClassName,\n extensionModuleCardInteractiveClassName,\n )}\n >\n <div className=\"flex items-start gap-3\">\n <McpLogoBadge entry={entry} />\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n <header className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate text-sm font-semibold\">{entry.name}</h3>\n <p className=\"mt-0.5 text-xs text-tertiary-alt\">\n {transportLabel}\n </p>\n </div>\n <CirclePlusCheckToggle\n testId={`mcp-marketplace-toggle-${entry.id}`}\n isSelected={false}\n onToggle={(selected) => {\n if (selected) {\n onAdd();\n }\n }}\n enableLabelKey={I18nKey.MCP$TOGGLE_ADD_SERVER}\n disableLabelKey={I18nKey.MCP$TOGGLE_ADD_SERVER}\n />\n </header>\n <p className=\"line-clamp-3 text-xs leading-relaxed text-tertiary-light\">\n {entry.description}\n </p>\n </div>\n </div>\n </button>\n );\n}\n"],"mappings":"mYAiBA,SAAgB,EAAgB,CAC9B,QACA,UACA,SACuB,CACvB,IAAM,EAAY,EAAA,uBAAuB,EAAM,CACzC,OAAwB,CAC5B,OAAQ,GAAW,KAAnB,CACE,IAAK,QACH,MAAO,QACT,IAAK,QACH,MAAO,OACT,IAAK,MACH,MAAO,MACT,QACE,MAAO,OAET,CAEJ,OACE,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACI,UACT,cAAa,wBAAwB,EAAM,KAC3C,UAAW,EAAA,GACT,4DACA,EAAA,oCACA,EAAA,wCACD,WAED,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,KAAC,EAAA,aAAD,CAAqB,QAAS,CAAA,EAC9B,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,8CAAf,EACE,EAAA,EAAA,MAAC,SAAD,CAAQ,UAAU,kDAAlB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,0BAAf,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,0CAAkC,EAAM,KAAU,CAAA,EAChE,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,4CACV,EACC,CAAA,CACA,IACN,EAAA,EAAA,KAAC,EAAA,sBAAD,CACE,OAAQ,0BAA0B,EAAM,KACxC,WAAY,GACZ,SAAW,GAAa,CAClB,GACF,GAAO,EAGX,eAAgB,EAAA,QAAQ,sBACxB,gBAAiB,EAAA,QAAQ,sBACzB,CAAA,CACK,IACT,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,oEACV,EAAM,YACL,CAAA,CACA,GACF,GACC,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { I18nKey as e } from "../../../i18n/declaration.js";
|
|
2
2
|
import { cn as t } from "../../../utils/utils.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getDefaultMcpTransport as n } from "../../../utils/mcp-marketplace-utils.js";
|
|
4
4
|
import { McpLogoBadge as r } from "../mcp-logo-badge.js";
|
|
5
5
|
import { CirclePlusCheckToggle as i } from "../../shared/buttons/circle-plus-check-toggle.js";
|
|
6
6
|
import { extensionModuleCardInteractiveClassName as a, extensionModuleCardSurfaceClassName as o } from "../../../utils/extension-module-card-classes.js";
|
|
@@ -8,8 +8,7 @@ import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
|
8
8
|
//#region src/components/features/mcp-page/marketplace-card.tsx
|
|
9
9
|
function l({ entry: l, onClick: u, onAdd: d }) {
|
|
10
10
|
let f = n(l), p = (() => {
|
|
11
|
-
|
|
12
|
-
switch (f.kind) {
|
|
11
|
+
switch (f?.kind) {
|
|
13
12
|
case "stdio": return "STDIO";
|
|
14
13
|
case "shttp": return "HTTP";
|
|
15
14
|
case "sse": return "SSE";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-card.js","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-card.tsx"],"sourcesContent":["import { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport {
|
|
1
|
+
{"version":3,"file":"marketplace-card.js","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-card.tsx"],"sourcesContent":["import { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { CirclePlusCheckToggle } from \"#/components/shared/buttons/circle-plus-check-toggle\";\nimport { getDefaultMcpTransport } from \"#/utils/mcp-marketplace-utils\";\nimport { cn } from \"#/utils/utils\";\nimport {\n extensionModuleCardInteractiveClassName,\n extensionModuleCardSurfaceClassName,\n} from \"#/utils/extension-module-card-classes\";\n\ninterface MarketplaceCardProps {\n entry: MarketplaceEntry;\n onClick: () => void;\n onAdd: () => void;\n}\n\nexport function MarketplaceCard({\n entry,\n onClick,\n onAdd,\n}: MarketplaceCardProps) {\n const transport = getDefaultMcpTransport(entry);\n const transportLabel = (() => {\n switch (transport?.kind) {\n case \"stdio\":\n return \"STDIO\";\n case \"shttp\":\n return \"HTTP\";\n case \"sse\":\n return \"SSE\";\n default:\n return \"\";\n }\n })();\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n data-testid={`mcp-marketplace-card-${entry.id}`}\n className={cn(\n \"flex min-h-[132px] flex-col overflow-hidden p-4 text-left\",\n extensionModuleCardSurfaceClassName,\n extensionModuleCardInteractiveClassName,\n )}\n >\n <div className=\"flex items-start gap-3\">\n <McpLogoBadge entry={entry} />\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n <header className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate text-sm font-semibold\">{entry.name}</h3>\n <p className=\"mt-0.5 text-xs text-tertiary-alt\">\n {transportLabel}\n </p>\n </div>\n <CirclePlusCheckToggle\n testId={`mcp-marketplace-toggle-${entry.id}`}\n isSelected={false}\n onToggle={(selected) => {\n if (selected) {\n onAdd();\n }\n }}\n enableLabelKey={I18nKey.MCP$TOGGLE_ADD_SERVER}\n disableLabelKey={I18nKey.MCP$TOGGLE_ADD_SERVER}\n />\n </header>\n <p className=\"line-clamp-3 text-xs leading-relaxed text-tertiary-light\">\n {entry.description}\n </p>\n </div>\n </div>\n </button>\n );\n}\n"],"mappings":";;;;;;;;AAiBA,SAAgB,EAAgB,EAC9B,UACA,YACA,YACuB;CACvB,IAAM,IAAY,EAAuB,EAAM,EACzC,WAAwB;AAC5B,UAAQ,GAAW,MAAnB;GACE,KAAK,QACH,QAAO;GACT,KAAK,QACH,QAAO;GACT,KAAK,MACH,QAAO;GACT,QACE,QAAO;;KAET;AAEJ,QACE,kBAAC,UAAD;EACE,MAAK;EACI;EACT,eAAa,wBAAwB,EAAM;EAC3C,WAAW,EACT,6DACA,GACA,EACD;YAED,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAqB,UAAS,CAAA,EAC9B,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KAAQ,WAAU;eAAlB,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAAkC,EAAM;OAAU,CAAA,EAChE,kBAAC,KAAD;OAAG,WAAU;iBACV;OACC,CAAA,CACA;SACN,kBAAC,GAAD;MACE,QAAQ,0BAA0B,EAAM;MACxC,YAAY;MACZ,WAAW,MAAa;AACtB,OAAI,KACF,GAAO;;MAGX,gBAAgB,EAAQ;MACxB,iBAAiB,EAAQ;MACzB,CAAA,CACK;QACT,kBAAC,KAAD;KAAG,WAAU;eACV,EAAM;KACL,CAAA,CACA;MACF;;EACC,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),t=require(`../../../i18n/declaration.cjs`),n=require(`../../../utils/mcp-marketplace-utils.cjs`),r=require(`../../../node_modules/@openhands/extensions/integrations/index.cjs`),i=require(`../../../utils/extension-module-card-classes.cjs`),a=require(`./marketplace-card.cjs`);let o=require(`react/jsx-runtime`);function s({backendKind:s,onSelect:c,onAdd:l,query:u=``}){let{t:d}=e.useTranslation(`openhands`),f=n.getMarketplaceEntriesByPopularity(r.default).filter(e=>n.isMarketplaceEntryAvailable(e,s)&&n.marketplaceEntryMatchesQuery(e,u));return(0,o.jsxs)(`section`,{"data-testid":`mcp-marketplace-section`,className:`flex flex-col gap-3`,children:[(0,o.jsx)(`h2`,{className:`text-base font-medium text-foreground`,children:d(t.I18nKey.MCP$LIBRARY_TITLE)}),f.length===0?(0,o.jsx)(`div`,{"data-testid":`mcp-marketplace-empty`,className:`rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center`,children:(0,o.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:d(t.I18nKey.MCP$SEARCH_EMPTY)})}):(0,o.jsx)(`div`,{className:i.extensionModuleCardGridContainerClassName,children:(0,o.jsx)(`div`,{"data-testid":`mcp-marketplace-grid`,className:i.extensionModuleCardGridClassName,children:f.map(e=>(0,o.jsx)(a.MarketplaceCard,{entry:e,onClick:()=>c(e),onAdd:()=>l(e)},e.id))})})]})}exports.MarketplaceSection=s;
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),t=require(`../../../i18n/declaration.cjs`),n=require(`../../../utils/mcp-marketplace-utils.cjs`),r=require(`../../../node_modules/@openhands/extensions/integrations/index.cjs`),i=require(`../../../utils/extension-module-card-classes.cjs`),a=require(`./marketplace-card.cjs`);let o=require(`react/jsx-runtime`);function s({backendKind:s,onSelect:c,onAdd:l,query:u=``}){let{t:d}=e.useTranslation(`openhands`),f=n.getMarketplaceEntriesByPopularity(n.getMcpMarketplaceCatalog(r.default)).filter(e=>n.isMarketplaceEntryAvailable(e,s)&&n.marketplaceEntryMatchesQuery(e,u));return(0,o.jsxs)(`section`,{"data-testid":`mcp-marketplace-section`,className:`flex flex-col gap-3`,children:[(0,o.jsx)(`h2`,{className:`text-base font-medium text-foreground`,children:d(t.I18nKey.MCP$LIBRARY_TITLE)}),f.length===0?(0,o.jsx)(`div`,{"data-testid":`mcp-marketplace-empty`,className:`rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center`,children:(0,o.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:d(t.I18nKey.MCP$SEARCH_EMPTY)})}):(0,o.jsx)(`div`,{className:i.extensionModuleCardGridContainerClassName,children:(0,o.jsx)(`div`,{"data-testid":`mcp-marketplace-grid`,className:i.extensionModuleCardGridClassName,children:f.map(e=>(0,o.jsx)(a.MarketplaceCard,{entry:e,onClick:()=>c(e),onAdd:()=>l(e)},e.id))})})]})}exports.MarketplaceSection=s;
|
|
2
2
|
//# sourceMappingURL=marketplace-section.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-section.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-section.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n INTEGRATION_CATALOG as
|
|
1
|
+
{"version":3,"file":"marketplace-section.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-section.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n INTEGRATION_CATALOG as MCP_MARKETPLACE,\n type IntegrationCatalogEntry as MarketplaceEntry,\n} from \"@openhands/extensions/integrations\";\nimport {\n getMarketplaceEntriesByPopularity,\n getMcpMarketplaceCatalog,\n isMarketplaceEntryAvailable,\n marketplaceEntryMatchesQuery,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { MarketplaceCard } from \"./marketplace-card\";\nimport {\n extensionModuleCardGridClassName,\n extensionModuleCardGridContainerClassName,\n} from \"#/utils/extension-module-card-classes\";\n\ninterface MarketplaceSectionProps {\n backendKind: \"local\" | \"cloud\";\n onSelect: (entry: MarketplaceEntry) => void;\n onAdd: (entry: MarketplaceEntry) => void;\n /** Empty string = no filter. */\n query?: string;\n}\n\nexport function MarketplaceSection({\n backendKind,\n onSelect,\n onAdd,\n query = \"\",\n}: MarketplaceSectionProps) {\n const { t } = useTranslation(\"openhands\");\n\n const visibleEntries = getMarketplaceEntriesByPopularity(\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n ).filter(\n (entry) =>\n isMarketplaceEntryAvailable(entry, backendKind) &&\n marketplaceEntryMatchesQuery(entry, query),\n );\n\n return (\n <section\n data-testid=\"mcp-marketplace-section\"\n className=\"flex flex-col gap-3\"\n >\n <h2 className=\"text-base font-medium text-foreground\">\n {t(I18nKey.MCP$LIBRARY_TITLE)}\n </h2>\n\n {visibleEntries.length === 0 ? (\n <div\n data-testid=\"mcp-marketplace-empty\"\n className=\"rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center\"\n >\n <p className=\"text-xs text-tertiary-light\">\n {t(I18nKey.MCP$SEARCH_EMPTY)}\n </p>\n </div>\n ) : (\n <div className={extensionModuleCardGridContainerClassName}>\n <div\n data-testid=\"mcp-marketplace-grid\"\n className={extensionModuleCardGridClassName}\n >\n {visibleEntries.map((entry) => (\n <MarketplaceCard\n key={entry.id}\n entry={entry}\n onClick={() => onSelect(entry)}\n onAdd={() => onAdd(entry)}\n />\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n"],"mappings":"2bA0BA,SAAgB,EAAmB,CACjC,cACA,WACA,QACA,QAAQ,IACkB,CAC1B,GAAM,CAAE,KAAM,EAAA,eAAe,YAAY,CAEnC,EAAiB,EAAA,kCACrB,EAAA,yBAAyB,EAAA,QAAgB,CAC1C,CAAC,OACC,GACC,EAAA,4BAA4B,EAAO,EAAY,EAC/C,EAAA,6BAA6B,EAAO,EAAM,CAC7C,CAED,OACE,EAAA,EAAA,MAAC,UAAD,CACE,cAAY,0BACZ,UAAU,+BAFZ,EAIE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iDACX,EAAE,EAAA,QAAQ,kBAAkB,CAC1B,CAAA,CAEJ,EAAe,SAAW,GACzB,EAAA,EAAA,KAAC,MAAD,CACE,cAAY,wBACZ,UAAU,sFAEV,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,uCACV,EAAE,EAAA,QAAQ,iBAAiB,CAC1B,CAAA,CACA,CAAA,EAEN,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAA,oDACd,EAAA,EAAA,KAAC,MAAD,CACE,cAAY,uBACZ,UAAW,EAAA,0CAEV,EAAe,IAAK,IACnB,EAAA,EAAA,KAAC,EAAA,gBAAD,CAES,QACP,YAAe,EAAS,EAAM,CAC9B,UAAa,EAAM,EAAM,CACzB,CAJK,EAAM,GAIX,CACF,CACE,CAAA,CACF,CAAA,CAEA"}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
import { useTranslation as e } from "../../../node_modules/react-i18next/dist/es/useTranslation.js";
|
|
2
2
|
import { I18nKey as t } from "../../../i18n/declaration.js";
|
|
3
|
-
import { getMarketplaceEntriesByPopularity as n,
|
|
4
|
-
import
|
|
5
|
-
import { extensionModuleCardGridClassName as
|
|
6
|
-
import { MarketplaceCard as
|
|
7
|
-
import { jsx as
|
|
3
|
+
import { getMarketplaceEntriesByPopularity as n, getMcpMarketplaceCatalog as r, isMarketplaceEntryAvailable as i, marketplaceEntryMatchesQuery as a } from "../../../utils/mcp-marketplace-utils.js";
|
|
4
|
+
import o from "../../../node_modules/@openhands/extensions/integrations/index.js";
|
|
5
|
+
import { extensionModuleCardGridClassName as s, extensionModuleCardGridContainerClassName as c } from "../../../utils/extension-module-card-classes.js";
|
|
6
|
+
import { MarketplaceCard as l } from "./marketplace-card.js";
|
|
7
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/features/mcp-page/marketplace-section.tsx
|
|
9
|
-
function
|
|
10
|
-
let { t:
|
|
11
|
-
return /* @__PURE__ */
|
|
9
|
+
function f({ backendKind: f, onSelect: p, onAdd: m, query: h = "" }) {
|
|
10
|
+
let { t: g } = e("openhands"), _ = n(r(o)).filter((e) => i(e, f) && a(e, h));
|
|
11
|
+
return /* @__PURE__ */ d("section", {
|
|
12
12
|
"data-testid": "mcp-marketplace-section",
|
|
13
13
|
className: "flex flex-col gap-3",
|
|
14
|
-
children: [/* @__PURE__ */
|
|
14
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
15
15
|
className: "text-base font-medium text-foreground",
|
|
16
|
-
children:
|
|
17
|
-
}),
|
|
16
|
+
children: g(t.MCP$LIBRARY_TITLE)
|
|
17
|
+
}), _.length === 0 ? /* @__PURE__ */ u("div", {
|
|
18
18
|
"data-testid": "mcp-marketplace-empty",
|
|
19
19
|
className: "rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center",
|
|
20
|
-
children: /* @__PURE__ */
|
|
20
|
+
children: /* @__PURE__ */ u("p", {
|
|
21
21
|
className: "text-xs text-tertiary-light",
|
|
22
|
-
children:
|
|
22
|
+
children: g(t.MCP$SEARCH_EMPTY)
|
|
23
23
|
})
|
|
24
|
-
}) : /* @__PURE__ */
|
|
25
|
-
className:
|
|
26
|
-
children: /* @__PURE__ */
|
|
24
|
+
}) : /* @__PURE__ */ u("div", {
|
|
25
|
+
className: c,
|
|
26
|
+
children: /* @__PURE__ */ u("div", {
|
|
27
27
|
"data-testid": "mcp-marketplace-grid",
|
|
28
|
-
className:
|
|
29
|
-
children:
|
|
28
|
+
className: s,
|
|
29
|
+
children: _.map((e) => /* @__PURE__ */ u(l, {
|
|
30
30
|
entry: e,
|
|
31
|
-
onClick: () =>
|
|
32
|
-
onAdd: () =>
|
|
31
|
+
onClick: () => p(e),
|
|
32
|
+
onAdd: () => m(e)
|
|
33
33
|
}, e.id))
|
|
34
34
|
})
|
|
35
35
|
})]
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
//#endregion
|
|
39
|
-
export {
|
|
39
|
+
export { f as MarketplaceSection };
|
|
40
40
|
|
|
41
41
|
//# sourceMappingURL=marketplace-section.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-section.js","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-section.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n INTEGRATION_CATALOG as
|
|
1
|
+
{"version":3,"file":"marketplace-section.js","names":[],"sources":["../../../../src/components/features/mcp-page/marketplace-section.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n INTEGRATION_CATALOG as MCP_MARKETPLACE,\n type IntegrationCatalogEntry as MarketplaceEntry,\n} from \"@openhands/extensions/integrations\";\nimport {\n getMarketplaceEntriesByPopularity,\n getMcpMarketplaceCatalog,\n isMarketplaceEntryAvailable,\n marketplaceEntryMatchesQuery,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { MarketplaceCard } from \"./marketplace-card\";\nimport {\n extensionModuleCardGridClassName,\n extensionModuleCardGridContainerClassName,\n} from \"#/utils/extension-module-card-classes\";\n\ninterface MarketplaceSectionProps {\n backendKind: \"local\" | \"cloud\";\n onSelect: (entry: MarketplaceEntry) => void;\n onAdd: (entry: MarketplaceEntry) => void;\n /** Empty string = no filter. */\n query?: string;\n}\n\nexport function MarketplaceSection({\n backendKind,\n onSelect,\n onAdd,\n query = \"\",\n}: MarketplaceSectionProps) {\n const { t } = useTranslation(\"openhands\");\n\n const visibleEntries = getMarketplaceEntriesByPopularity(\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n ).filter(\n (entry) =>\n isMarketplaceEntryAvailable(entry, backendKind) &&\n marketplaceEntryMatchesQuery(entry, query),\n );\n\n return (\n <section\n data-testid=\"mcp-marketplace-section\"\n className=\"flex flex-col gap-3\"\n >\n <h2 className=\"text-base font-medium text-foreground\">\n {t(I18nKey.MCP$LIBRARY_TITLE)}\n </h2>\n\n {visibleEntries.length === 0 ? (\n <div\n data-testid=\"mcp-marketplace-empty\"\n className=\"rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center\"\n >\n <p className=\"text-xs text-tertiary-light\">\n {t(I18nKey.MCP$SEARCH_EMPTY)}\n </p>\n </div>\n ) : (\n <div className={extensionModuleCardGridContainerClassName}>\n <div\n data-testid=\"mcp-marketplace-grid\"\n className={extensionModuleCardGridClassName}\n >\n {visibleEntries.map((entry) => (\n <MarketplaceCard\n key={entry.id}\n entry={entry}\n onClick={() => onSelect(entry)}\n onAdd={() => onAdd(entry)}\n />\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n"],"mappings":";;;;;;;;AA0BA,SAAgB,EAAmB,EACjC,gBACA,aACA,UACA,WAAQ,MACkB;CAC1B,IAAM,EAAE,SAAM,EAAe,YAAY,EAEnC,IAAiB,EACrB,EAAyB,EAAgB,CAC1C,CAAC,QACC,MACC,EAA4B,GAAO,EAAY,IAC/C,EAA6B,GAAO,EAAM,CAC7C;AAED,QACE,kBAAC,WAAD;EACE,eAAY;EACZ,WAAU;YAFZ,CAIE,kBAAC,MAAD;GAAI,WAAU;aACX,EAAE,EAAQ,kBAAkB;GAC1B,CAAA,EAEJ,EAAe,WAAW,IACzB,kBAAC,OAAD;GACE,eAAY;GACZ,WAAU;aAEV,kBAAC,KAAD;IAAG,WAAU;cACV,EAAE,EAAQ,iBAAiB;IAC1B,CAAA;GACA,CAAA,GAEN,kBAAC,OAAD;GAAK,WAAW;aACd,kBAAC,OAAD;IACE,eAAY;IACZ,WAAW;cAEV,EAAe,KAAK,MACnB,kBAAC,GAAD;KAES;KACP,eAAe,EAAS,EAAM;KAC9B,aAAa,EAAM,EAAM;KACzB,EAJK,EAAM,GAIX,CACF;IACE,CAAA;GACF,CAAA,CAEA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type OnboardingAgentId } from "./choose-agent-step";
|
|
2
|
+
interface SetupAcpSecretsStepProps {
|
|
3
|
+
/** ACP provider whose credentials we're collecting (e.g. ``"claude-code"``).
|
|
4
|
+
* Typed as {@link OnboardingAgentId} — the same type the onboarding modal
|
|
5
|
+
* tracks — so a mistyped key is a compile error rather than a silently empty
|
|
6
|
+
* form. Providers without a credentials entry (``"openhands"``,
|
|
7
|
+
* ``"gemini-cli"``) simply yield no fields. */
|
|
8
|
+
providerKey: OnboardingAgentId;
|
|
9
|
+
onBack: () => void;
|
|
10
|
+
onNext: () => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Onboarding credentials step for ACP providers that authenticate via an
|
|
14
|
+
* env-var API key (Claude Code, Codex). The fields are derived from
|
|
15
|
+
* {@link getAcpProviderSecrets}; each one maps 1:1 to a **global secret**
|
|
16
|
+
* whose name equals the env var the agent-server exports into the provider
|
|
17
|
+
* subprocess. Saving here is therefore the same as adding the secret under
|
|
18
|
+
* Settings → Secrets — it shows up there afterwards.
|
|
19
|
+
*
|
|
20
|
+
* The step is intentionally skippable: a user may authenticate Claude Code via
|
|
21
|
+
* a subscription login, or already have the env var set on the backend, so we
|
|
22
|
+
* never block "Next" on a value. Empty fields are simply not written; a field
|
|
23
|
+
* whose secret already exists shows an "already saved" placeholder and is left
|
|
24
|
+
* untouched unless the user types a replacement.
|
|
25
|
+
*/
|
|
26
|
+
export declare function SetupAcpSecretsStep({ providerKey, onBack, onNext, }: SetupAcpSecretsStepProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../../../../_virtual/_rolldown/runtime.cjs`);require(`../../../../utils/custom-toast-handlers.cjs`),require(`../../../../api/profiles-service/profiles-service.api.cjs`),require(`../../../../hooks/query/use-llm-profiles.cjs`),require(`../../../../ui/typography.cjs`),require(`../brand-button.cjs`),require(`./profile-name-input.cjs`),require(`./llm-profiles-manager.cjs`),require(`../../../../hooks/mutation/use-save-llm-profile.cjs`),require(`../../../../contexts/settings-section-header-context.cjs`),require(`../../../../routes/llm-settings.cjs`);let t=require(`react`);t=e.__toESM(t,1),require(`react/jsx-runtime`);
|
|
1
|
+
const e=require(`../../../../_virtual/_rolldown/runtime.cjs`);require(`../../../../utils/custom-toast-handlers.cjs`),require(`../../../../api/profiles-service/profiles-service.api.cjs`),require(`../../../../hooks/query/use-llm-profiles.cjs`),require(`../../../../hooks/query/use-settings.cjs`),require(`../../../../ui/typography.cjs`),require(`../brand-button.cjs`),require(`../../../../hooks/query/use-agent-settings-schema.cjs`),require(`./profile-name-input.cjs`),require(`./llm-profiles-manager.cjs`),require(`../../../../hooks/mutation/use-save-llm-profile.cjs`),require(`../../../../contexts/settings-section-header-context.cjs`),require(`../../../../routes/llm-settings.cjs`);let t=require(`react`);t=e.__toESM(t,1),require(`react/jsx-runtime`);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import "../../../../utils/custom-toast-handlers.js";
|
|
2
2
|
import "../../../../api/profiles-service/profiles-service.api.js";
|
|
3
3
|
import "../../../../hooks/query/use-llm-profiles.js";
|
|
4
|
+
import "../../../../hooks/query/use-settings.js";
|
|
4
5
|
import "../../../../ui/typography.js";
|
|
5
6
|
import "../brand-button.js";
|
|
7
|
+
import "../../../../hooks/query/use-agent-settings-schema.js";
|
|
6
8
|
import "./profile-name-input.js";
|
|
7
9
|
import "./llm-profiles-manager.js";
|
|
8
10
|
import "../../../../hooks/mutation/use-save-llm-profile.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../../i18n/declaration.cjs`),r=require(`../../../../utils/custom-toast-handlers.cjs`),i=require(`../../../../node_modules/axios/index.cjs`),a=require(`../../../../hooks/query/use-settings.cjs`),o=require(`../../../../ui/typography.cjs`),s=require(`../brand-button.cjs`),c=require(`../../../../hooks/mutation/use-save-settings.cjs`),l=require(`../../../../utils/retrieve-axios-error-message.cjs`),u=require(`../../../../hooks/query/use-agent-settings-schema.cjs`),d=require(`../llm-settings/llm-settings-inputs-skeleton.cjs`),f=require(`../../../../utils/sdk-settings-schema.cjs`),p=require(`./schema-field.cjs`),m=require(`./view-toggle.cjs`);let h=require(`react`);h=e.__toESM(h,1);let g=require(`react/jsx-runtime`);var _=new Set,v={basic:0,advanced:1,all:2},ee=(e,t)=>v[t]<v[e]?t:e,te=(e,{showAdvanced:t,showAll:n})=>e===`all`?n?`all`:t?`advanced`:`basic`:e===`advanced`?t?`advanced`:n?`all`:`basic`:`basic`,y=(e,t)=>e instanceof i.AxiosError?e.response?.status===401?`${t} This agent server requires X-Session-API-Key. Set VITE_SESSION_API_KEY in the frontend to the same value used by the backend SESSION_API_KEY or OH_SESSION_API_KEYS_0.`:e.response?.status===404?`${t} This backend does not expose /api/settings/* schema endpoints. Upgrade to a recent openhands-agent-server release.`:t:t;function b({sectionKeys:e,excludeKeys:i=_,scope:v=`personal`,settingsSource:b=`agent_settings`,header:ne,extraDirty:x=!1,buildPayload:S,onSaveSuccess:C,getInitialView:w,forceShowAdvancedView:re=!1,allowAllView:ie=!0,initialValueOverrides:T,embedded:E=!1,hideSaveButton:D=!1,onSaveControlChange:O,testId:ae=`sdk-section-settings-screen`}){let{t:k}=t.useTranslation(`openhands`),{mutate:oe,isPending:A}=c.useSaveSettings(v),{data:j,isLoading:se,isFetching:ce}=a.useSettings(v),le=u.useAgentSettingsSchema(j?.agent_settings_schema),
|
|
1
|
+
const e=require(`../../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../../i18n/declaration.cjs`),r=require(`../../../../utils/custom-toast-handlers.cjs`),i=require(`../../../../node_modules/axios/index.cjs`),a=require(`../../../../hooks/query/use-settings.cjs`),o=require(`../../../../ui/typography.cjs`),s=require(`../brand-button.cjs`),c=require(`../../../../hooks/mutation/use-save-settings.cjs`),l=require(`../../../../utils/retrieve-axios-error-message.cjs`),u=require(`../../../../hooks/query/use-agent-settings-schema.cjs`),d=require(`../llm-settings/llm-settings-inputs-skeleton.cjs`),f=require(`../../../../utils/sdk-settings-schema.cjs`),p=require(`./schema-field.cjs`),m=require(`./view-toggle.cjs`);let h=require(`react`);h=e.__toESM(h,1);let g=require(`react/jsx-runtime`);var _=new Set,v={basic:0,advanced:1,all:2},ee=(e,t)=>v[t]<v[e]?t:e,te=(e,{showAdvanced:t,showAll:n})=>e===`all`?n?`all`:t?`advanced`:`basic`:e===`advanced`?t?`advanced`:n?`all`:`basic`:`basic`,y=(e,t)=>e instanceof i.AxiosError?e.response?.status===401?`${t} This agent server requires X-Session-API-Key. Set VITE_SESSION_API_KEY in the frontend to the same value used by the backend SESSION_API_KEY or OH_SESSION_API_KEYS_0.`:e.response?.status===404?`${t} This backend does not expose /api/settings/* schema endpoints. Upgrade to a recent openhands-agent-server release.`:t:t;function b({sectionKeys:e,excludeKeys:i=_,scope:v=`personal`,settingsSource:b=`agent_settings`,header:ne,extraDirty:x=!1,buildPayload:S,onSaveSuccess:C,getInitialView:w,forceShowAdvancedView:re=!1,allowAllView:ie=!0,initialValueOverrides:T,embedded:E=!1,hideSaveButton:D=!1,onSaveControlChange:O,testId:ae=`sdk-section-settings-screen`}){let{t:k}=t.useTranslation(`openhands`),{mutate:oe,isPending:A}=c.useSaveSettings(v),{data:j,isLoading:se,isFetching:ce}=a.useSettings(v),le=u.useAgentSettingsSchema(j?.agent_settings_schema),ue=u.useConversationSettingsSchema(j?.conversation_settings_schema),M=b===`conversation_settings`?ue:le,N=M.data,P=M.isLoading,[F,I]=h.default.useState(`basic`),[L,R]=h.default.useState({}),[z,B]=h.default.useState({}),V=h.default.useRef(!1),H=h.default.useMemo(()=>JSON.stringify(e),[e]),U=h.default.useMemo(()=>JSON.parse(H),[H]),W=h.default.useMemo(()=>{if(!f.isValidSettingsSchema(N))return null;let e=new Set(U);return{...N,sections:N.sections.filter(t=>e.has(t.key))}},[N,U]),G=re||f.hasAdvancedSettings(W),K=ie&&f.hasMinorSettings(W),de=h.default.useMemo(()=>y(M.error,k(n.I18nKey.SETTINGS$SDK_SCHEMA_UNAVAILABLE)),[M.error,k]),fe=h.default.useMemo(()=>T?JSON.stringify(T):``,[T]),q=h.default.useMemo(()=>{if(!j||!W)return null;let e=f.buildInitialSettingsFormValues(j,W,b);return T?{...e,...T}:e},[j,W,b,fe]),J=h.default.useMemo(()=>!j||!W?null:te(w?w(j,W):f.inferInitialView(j,W,b),{showAdvanced:G,showAll:K}),[j,W,w,b,G,K]);h.default.useEffect(()=>{V.current=!1,I(`basic`),R({}),B({})},[v,b,H]),h.default.useEffect(()=>{!q||!J||(R(q),B(T?Object.fromEntries(Object.keys(T).map(e=>[e,!0])):{}),I(e=>V.current?ee(e,J):(V.current=!0,J)))},[q,J]);let pe=h.default.useMemo(()=>W?f.getVisibleSettingsSections(W,L,F,i):[],[W,L,F,i]),Y=h.default.useCallback((e,t)=>{R(n=>({...n,[e]:t})),B(t=>({...t,[e]:!0}))},[]),me=h.default.useCallback(e=>{r.displayErrorToast(l.retrieveAxiosErrorMessage(e)||k(n.I18nKey.ERROR$GENERIC))},[k]),X=h.default.useRef(()=>{}),he=h.default.useCallback(()=>{X.current()},[]),Z=h.default.useRef(()=>({})),ge=h.default.useCallback(()=>Z.current(),[]),Q=()=>{if(!W)return;let e;try{let t=f.buildSdkSettingsPayloadForView(W,L,z,F),n;n=b===`conversation_settings`?{conversation_settings_diff:t}:{agent_settings_diff:t},e=S?S(t,{values:L,dirty:z,view:F}):n}catch(e){r.displayErrorToast(e instanceof Error?e.message:k(n.I18nKey.ERROR$GENERIC));return}Object.keys(e).length!==0&&oe(e,{onError:me,onSuccess:()=>{r.displaySuccessToast(k(n.I18nKey.SETTINGS$SAVED_WARNING)),B({}),C?.()}})};X.current=Q,Z.current=()=>W?f.buildSdkSettingsPayload(W,L,z):{};let $=Object.keys(z).length>0||x;return h.default.useEffect(()=>{O&&O({save:he,isSaving:A,isDirty:$,values:L,view:F,getDirtyPayload:ge})},[A,$,L,F]),se||ce||P?(0,g.jsx)(d.LlmSettingsInputsSkeleton,{}):!W||W.sections.length===0?(0,g.jsx)(o.Typography.Paragraph,{className:`text-tertiary-alt`,children:de}):Object.keys(L).length===0?(0,g.jsx)(d.LlmSettingsInputsSkeleton,{}):(0,g.jsxs)(`div`,{"data-testid":ae,className:E?`relative flex min-h-0 w-full flex-1 flex-col`:`relative w-full min-h-0`,children:[(0,g.jsx)(m.ViewToggle,{view:F,setView:I,showAdvanced:G,showAll:K,isDisabled:!1}),(0,g.jsxs)(`div`,{className:`flex flex-col gap-8`,children:[ne?.({values:L,isDisabled:!1,view:F,onChange:Y}),pe.map((e,t)=>(0,g.jsx)(`section`,{className:`flex flex-col gap-4`,children:(0,g.jsx)(`div`,{className:`flex flex-col gap-4`,children:e.fields.map(e=>(0,g.jsx)(p.SchemaField,{field:e,value:L[e.key],isDisabled:!1,onChange:t=>Y(e.key,t)},e.key))})},`${e.key}-${t}`)),D?null:(0,g.jsx)(`div`,{className:`flex justify-start pt-2`,children:(0,g.jsx)(s.BrandButton,{testId:`save-button`,type:`button`,variant:`primary`,isDisabled:A||Object.keys(z).length===0&&!x,onClick:Q,children:k(A?n.I18nKey.SETTINGS$SAVING:n.I18nKey.SETTINGS$SAVE_CHANGES)})})]})]})}exports.SdkSectionPage=b;
|
|
2
2
|
//# sourceMappingURL=sdk-section-page.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk-section-page.cjs","names":[],"sources":["../../../../../src/components/features/settings/sdk-settings/sdk-section-page.tsx"],"sourcesContent":["import React from \"react\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { LlmSettingsInputsSkeleton } from \"#/components/features/settings/llm-settings/llm-settings-inputs-skeleton\";\nimport { useSaveSettings } from \"#/hooks/mutation/use-save-settings\";\nimport {\n useAgentSettingsSchema,\n useConversationSettingsSchema,\n} from \"#/hooks/query/use-agent-settings-schema\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { Typography } from \"#/ui/typography\";\nimport { Settings, SettingsSchema, SettingsScope } from \"#/types/settings\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport {\n buildInitialSettingsFormValues,\n buildSdkSettingsPayloadForView,\n getVisibleSettingsSections,\n hasAdvancedSettings,\n hasMinorSettings,\n inferInitialView,\n isValidSettingsSchema,\n SettingsDirtyState,\n SettingsFormValues,\n type SettingsValueSource,\n type SettingsView,\n} from \"#/utils/sdk-settings-schema\";\nimport { SchemaField } from \"./schema-field\";\nimport { ViewToggle } from \"./view-toggle\";\n\nconst EMPTY_EXCLUDE_KEYS = new Set<string>();\n\nconst VIEW_ORDER: Record<SettingsView, number> = {\n basic: 0,\n advanced: 1,\n all: 2,\n};\n\nconst getLessDetailedView = (\n currentView: SettingsView,\n nextView: SettingsView,\n): SettingsView =>\n VIEW_ORDER[nextView] < VIEW_ORDER[currentView] ? nextView : currentView;\n\nconst normalizeView = (\n view: SettingsView,\n {\n showAdvanced,\n showAll,\n }: {\n showAdvanced: boolean;\n showAll: boolean;\n },\n): SettingsView => {\n if (view === \"all\") {\n if (showAll) {\n return \"all\";\n }\n\n return showAdvanced ? \"advanced\" : \"basic\";\n }\n\n if (view === \"advanced\") {\n if (showAdvanced) {\n return \"advanced\";\n }\n\n return showAll ? \"all\" : \"basic\";\n }\n\n return \"basic\";\n};\n\nconst getSchemaUnavailableMessage = (\n error: unknown,\n fallbackMessage: string,\n): string => {\n if (!(error instanceof AxiosError)) {\n return fallbackMessage;\n }\n\n if (error.response?.status === 401) {\n return `${fallbackMessage} This agent server requires X-Session-API-Key. Set VITE_SESSION_API_KEY in the frontend to the same value used by the backend SESSION_API_KEY or OH_SESSION_API_KEYS_0.`;\n }\n\n if (error.response?.status === 404) {\n return `${fallbackMessage} This backend does not expose /api/settings/* schema endpoints. Upgrade to a recent openhands-agent-server release.`;\n }\n\n return fallbackMessage;\n};\n\nexport interface SdkSectionHeaderProps {\n values: SettingsFormValues;\n isDisabled: boolean;\n view: SettingsView;\n onChange: (key: string, value: string | boolean) => void;\n}\n\n/**\n * Snapshot of the page's save state, surfaced to the parent so it can\n * render its own Save/Next button (e.g. in onboarding) when\n * {@link SdkSectionPage}'s built-in button is hidden via\n * `hideSaveButton`.\n */\nexport interface SdkSectionSaveControl {\n /** Trigger a save of the currently-dirty fields. No-op while `isSaving` or `!isDirty`. */\n save: () => void;\n /** A save mutation is in flight. */\n isSaving: boolean;\n /** At least one field is dirty (or `extraDirty` was passed in). */\n isDirty: boolean;\n /** Current form values (for custom save flows). */\n values: SettingsFormValues;\n}\n\n/**\n * A generic SDK-schema–driven settings page that renders fields\n * from one or more schema sections.\n *\n * @param sectionKeys - which schema section(s) this page owns (e.g. [\"condenser\"])\n * @param excludeKeys - field keys to skip (rendered elsewhere by the caller)\n * @param header - optional render prop receiving shared state to render above fields\n * @param testId - data-testid for the page wrapper\n */\nexport function SdkSectionPage({\n sectionKeys,\n excludeKeys = EMPTY_EXCLUDE_KEYS,\n scope = \"personal\",\n settingsSource = \"agent_settings\",\n header,\n extraDirty = false,\n buildPayload,\n onSaveSuccess,\n getInitialView,\n forceShowAdvancedView = false,\n allowAllView = true,\n initialValueOverrides,\n embedded = false,\n hideSaveButton = false,\n onSaveControlChange,\n testId = \"sdk-section-settings-screen\",\n}: {\n sectionKeys: string[];\n excludeKeys?: Set<string>;\n scope?: SettingsScope;\n settingsSource?: SettingsValueSource;\n\n header?: (props: SdkSectionHeaderProps) => React.ReactNode;\n extraDirty?: boolean;\n buildPayload?: (\n payload: ReturnType<typeof buildSdkSettingsPayloadForView>,\n context: {\n values: SettingsFormValues;\n dirty: SettingsDirtyState;\n view: SettingsView;\n },\n ) => Record<string, unknown>;\n onSaveSuccess?: () => void;\n getInitialView?: (\n settings: Settings,\n filteredSchema: SettingsSchema,\n ) => SettingsView;\n forceShowAdvancedView?: boolean;\n allowAllView?: boolean;\n /**\n * Per-field initial value overrides that win over the values\n * derived from `useSettings`. The keys of each override are also\n * marked dirty on hydration so the user can save the form without\n * having to touch the prefilled fields. Useful when the page is\n * embedded in a flow that wants to nudge brand-new users toward a\n * particular default (e.g. onboarding pre-filling Anthropic/Opus).\n */\n initialValueOverrides?: SettingsFormValues;\n /**\n * When true, the Save button container is rendered inline (no\n * sticky positioning, no contrasting `bg-base` band) so the page\n * can be dropped into a modal/card without a hard footer break.\n */\n embedded?: boolean;\n /**\n * Suppress the built-in Save Changes button entirely. Pair with\n * {@link onSaveControlChange} to drive saving from a parent-rendered\n * action (e.g. an onboarding \"Next\" button).\n */\n hideSaveButton?: boolean;\n /**\n * Fires whenever the save state changes (a mutation starts/finishes,\n * dirty status flips). Provides a stable `save()` callback the\n * parent can wire to its own button. Useful when the form is\n * embedded in a custom flow and the built-in Save button is hidden.\n */\n onSaveControlChange?: (control: SdkSectionSaveControl) => void;\n testId?: string;\n}) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: saveSettings, isPending } = useSaveSettings(scope);\n const { data: settings, isLoading, isFetching } = useSettings(scope);\n const agentSchemaQuery = useAgentSettingsSchema(\n settings?.agent_settings_schema,\n );\n const conversationSchemaQuery = useConversationSettingsSchema(\n settings?.conversation_settings_schema,\n );\n const activeSchemaQuery =\n settingsSource === \"conversation_settings\"\n ? conversationSchemaQuery\n : agentSchemaQuery;\n const schema = activeSchemaQuery.data;\n const isSchemaLoading = activeSchemaQuery.isLoading;\n const isReadOnly = false;\n\n const [view, setView] = React.useState<SettingsView>(\"basic\");\n const [values, setValues] = React.useState<SettingsFormValues>({});\n const [dirty, setDirty] = React.useState<SettingsDirtyState>({});\n const hasHydratedViewRef = React.useRef(false);\n\n const sectionKeysSignature = React.useMemo(\n () => JSON.stringify(sectionKeys),\n [sectionKeys],\n );\n const stableSectionKeys = React.useMemo(\n () => JSON.parse(sectionKeysSignature) as string[],\n [sectionKeysSignature],\n );\n\n // Build a filtered schema containing only the requested sections.\n // `isValidSettingsSchema` guards against truthy-but-malformed schema\n // responses (e.g. when the deployment is pointed at a host that does\n // not serve `/api/settings/agent-schema` and returns an SPA shell\n // that parses into an object without a `sections` array). Without\n // the guard, `schema.sections.filter(...)` would throw and React\n // Router would escalate the crash to a full-screen error.\n const filteredSchema = React.useMemo(() => {\n if (!isValidSettingsSchema(schema)) return null;\n const sectionSet = new Set(stableSectionKeys);\n return {\n ...schema,\n sections: schema.sections.filter((s) => sectionSet.has(s.key)),\n };\n }, [schema, stableSectionKeys]);\n\n const showAdvanced =\n forceShowAdvancedView || hasAdvancedSettings(filteredSchema);\n const showAll = allowAllView && hasMinorSettings(filteredSchema);\n const schemaUnavailableMessage = React.useMemo(\n () =>\n getSchemaUnavailableMessage(\n activeSchemaQuery.error,\n t(I18nKey.SETTINGS$SDK_SCHEMA_UNAVAILABLE),\n ),\n [activeSchemaQuery.error, t],\n );\n\n const overridesSignature = React.useMemo(\n () => (initialValueOverrides ? JSON.stringify(initialValueOverrides) : \"\"),\n [initialValueOverrides],\n );\n\n const initialValues = React.useMemo(() => {\n if (!settings || !filteredSchema) return null;\n const base = buildInitialSettingsFormValues(\n settings,\n filteredSchema,\n settingsSource,\n );\n if (!initialValueOverrides) return base;\n return { ...base, ...initialValueOverrides };\n // overridesSignature keeps the memo reactive without depending on\n // a (potentially recreated) object reference each render.\n }, [settings, filteredSchema, settingsSource, overridesSignature]);\n\n const initialView = React.useMemo(() => {\n if (!settings || !filteredSchema) return null;\n\n const resolvedInitialView = getInitialView\n ? getInitialView(settings, filteredSchema)\n : inferInitialView(settings, filteredSchema, settingsSource);\n\n return normalizeView(resolvedInitialView, { showAdvanced, showAll });\n }, [\n settings,\n filteredSchema,\n getInitialView,\n settingsSource,\n showAdvanced,\n showAll,\n ]);\n\n React.useEffect(() => {\n hasHydratedViewRef.current = false;\n setView(\"basic\");\n setValues({});\n setDirty({});\n }, [scope, settingsSource, sectionKeysSignature]);\n\n React.useEffect(() => {\n if (!initialValues || !initialView) return;\n\n setValues(initialValues);\n // Override-supplied keys are pre-populated for the user, so mark\n // them dirty up-front; otherwise the Save button stays disabled\n // until the user touches a field, defeating the point of the\n // override.\n const overrideDirty: SettingsDirtyState = initialValueOverrides\n ? Object.fromEntries(\n Object.keys(initialValueOverrides).map((key) => [key, true]),\n )\n : {};\n setDirty(overrideDirty);\n setView((currentView) => {\n if (!hasHydratedViewRef.current) {\n hasHydratedViewRef.current = true;\n return initialView;\n }\n\n return getLessDetailedView(currentView, initialView);\n });\n // initialValueOverrides is intentionally tracked via\n // overridesSignature on initialValues; including the object ref\n // here would re-fire the effect every render.\n }, [initialValues, initialView]);\n\n const visibleSections = React.useMemo(() => {\n if (!filteredSchema) return [];\n return getVisibleSettingsSections(\n filteredSchema,\n values,\n view,\n excludeKeys,\n );\n }, [filteredSchema, values, view, excludeKeys]);\n\n const handleFieldChange = React.useCallback(\n (fieldKey: string, nextValue: string | boolean) => {\n setValues((prev) => ({ ...prev, [fieldKey]: nextValue }));\n setDirty((prev) => ({ ...prev, [fieldKey]: true }));\n },\n [],\n );\n\n const handleError = React.useCallback(\n (error: AxiosError) => {\n const msg = retrieveAxiosErrorMessage(error);\n displayErrorToast(msg || t(I18nKey.ERROR$GENERIC));\n },\n [t],\n );\n\n // Stable save callback so `onSaveControlChange` can hand a single\n // function reference to the parent across renders. The latest\n // closure is kept up to date via `handleSaveRef`.\n const handleSaveRef = React.useRef<() => void>(() => {});\n const stableSave = React.useCallback(() => {\n handleSaveRef.current();\n }, []);\n\n const handleSave = () => {\n if (!filteredSchema || isReadOnly) return;\n\n let payload: Record<string, unknown>;\n try {\n const basePayload = buildSdkSettingsPayloadForView(\n filteredSchema,\n values,\n dirty,\n view,\n );\n let defaultPayload: Record<string, unknown>;\n if (settingsSource === \"conversation_settings\") {\n defaultPayload = { conversation_settings_diff: basePayload };\n } else {\n defaultPayload = { agent_settings_diff: basePayload };\n }\n payload = buildPayload\n ? buildPayload(basePayload, { values, dirty, view })\n : defaultPayload;\n } catch (error) {\n displayErrorToast(\n error instanceof Error ? error.message : t(I18nKey.ERROR$GENERIC),\n );\n return;\n }\n\n if (Object.keys(payload).length === 0) return;\n\n saveSettings(payload, {\n onError: handleError,\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.SETTINGS$SAVED_WARNING));\n setDirty({});\n onSaveSuccess?.();\n },\n });\n };\n\n handleSaveRef.current = handleSave;\n\n // Surface save state to the parent. Hooks must run before any\n // conditional early-returns below, so this lives here rather than\n // alongside the JSX. The dependency list deliberately excludes\n // `stableSave` (it never changes) and `onSaveControlChange` (we\n // tolerate ref-instability of the callback to avoid spamming the\n // parent on every render).\n const saveControlIsDirty = Object.keys(dirty).length > 0 || extraDirty;\n React.useEffect(() => {\n if (!onSaveControlChange) return;\n onSaveControlChange({\n save: stableSave,\n isSaving: isPending,\n isDirty: saveControlIsDirty,\n values,\n });\n }, [isPending, saveControlIsDirty, values]);\n\n if (isLoading || isFetching || isSchemaLoading) {\n return <LlmSettingsInputsSkeleton />;\n }\n\n if (!filteredSchema || filteredSchema.sections.length === 0) {\n return (\n <Typography.Paragraph className=\"text-tertiary-alt\">\n {schemaUnavailableMessage}\n </Typography.Paragraph>\n );\n }\n\n if (Object.keys(values).length === 0) return <LlmSettingsInputsSkeleton />;\n\n // Scrolling is owned by the settings shell (or onboarding wrapper), not a\n // nested scroll region. Save actions are inline after the last field.\n const bodyClassName = \"flex flex-col gap-8\";\n\n return (\n <div\n data-testid={testId}\n className={\n embedded\n ? \"relative flex min-h-0 w-full flex-1 flex-col\"\n : \"relative w-full min-h-0\"\n }\n >\n <ViewToggle\n view={view}\n setView={setView}\n showAdvanced={showAdvanced}\n showAll={showAll}\n isDisabled={isReadOnly}\n />\n\n <div className={bodyClassName}>\n {header?.({\n values,\n isDisabled: isReadOnly,\n view,\n onChange: handleFieldChange,\n })}\n\n {visibleSections.map((section, sectionIndex) => (\n <section\n key={`${section.key}-${sectionIndex}`}\n className=\"flex flex-col gap-4\"\n >\n <div className=\"flex flex-col gap-4\">\n {section.fields.map((field) => (\n <SchemaField\n key={field.key}\n field={field}\n value={values[field.key]}\n isDisabled={isReadOnly}\n onChange={(nextValue) =>\n handleFieldChange(field.key, nextValue)\n }\n />\n ))}\n </div>\n </section>\n ))}\n\n {!isReadOnly && !hideSaveButton ? (\n <div className=\"flex justify-start pt-2\">\n <BrandButton\n testId=\"save-button\"\n type=\"button\"\n variant=\"primary\"\n isDisabled={\n isPending || (Object.keys(dirty).length === 0 && !extraDirty)\n }\n onClick={handleSave}\n >\n {isPending\n ? t(I18nKey.SETTINGS$SAVING)\n : t(I18nKey.SETTINGS$SAVE_CHANGES)}\n </BrandButton>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n"],"mappings":"42BAmCA,IAAM,EAAqB,IAAI,IAEzB,EAA2C,CAC/C,MAAO,EACP,SAAU,EACV,IAAK,EACN,CAEK,IACJ,EACA,IAEA,EAAW,GAAY,EAAW,GAAe,EAAW,EAExD,IACJ,EACA,CACE,eACA,aAME,IAAS,MACP,EACK,MAGF,EAAe,WAAa,QAGjC,IAAS,WACP,EACK,WAGF,EAAU,MAAQ,QAGpB,QAGH,GACJ,EACA,IAEM,aAAiB,EAAA,WAInB,EAAM,UAAU,SAAW,IACtB,GAAG,EAAgB,yKAGxB,EAAM,UAAU,SAAW,IACtB,GAAG,EAAgB,qHAGrB,EAXE,EA+CX,SAAgB,EAAe,CAC7B,cACA,cAAc,EACd,QAAQ,WACR,iBAAiB,iBACjB,UACA,aAAa,GACb,eACA,gBACA,iBACA,yBAAwB,GACxB,gBAAe,GACf,wBACA,WAAW,GACX,iBAAiB,GACjB,sBACA,UAAS,+BAqDR,CACD,GAAM,CAAE,KAAM,EAAA,eAAe,YAAY,CACnC,CAAE,OAAQ,GAAc,aAAc,EAAA,gBAAgB,EAAM,CAC5D,CAAE,KAAM,EAAU,aAAW,eAAe,EAAA,YAAY,EAAM,CAC9D,GAAmB,EAAA,uBACvB,GAAU,sBACX,CACK,EAA0B,EAAA,8BAC9B,GAAU,6BACX,CACK,EACJ,IAAmB,wBACf,EACA,GACA,EAAS,EAAkB,KAC3B,EAAkB,EAAkB,UAGpC,CAAC,EAAM,GAAW,EAAA,QAAM,SAAuB,QAAQ,CACvD,CAAC,EAAQ,GAAa,EAAA,QAAM,SAA6B,EAAE,CAAC,CAC5D,CAAC,EAAO,GAAY,EAAA,QAAM,SAA6B,EAAE,CAAC,CAC1D,EAAqB,EAAA,QAAM,OAAO,GAAM,CAExC,EAAuB,EAAA,QAAM,YAC3B,KAAK,UAAU,EAAY,CACjC,CAAC,EAAY,CACd,CACK,EAAoB,EAAA,QAAM,YACxB,KAAK,MAAM,EAAqB,CACtC,CAAC,EAAqB,CACvB,CASK,EAAiB,EAAA,QAAM,YAAc,CACzC,GAAI,CAAC,EAAA,sBAAsB,EAAO,CAAE,OAAO,KAC3C,IAAM,EAAa,IAAI,IAAI,EAAkB,CAC7C,MAAO,CACL,GAAG,EACH,SAAU,EAAO,SAAS,OAAQ,GAAM,EAAW,IAAI,EAAE,IAAI,CAAC,CAC/D,EACA,CAAC,EAAQ,EAAkB,CAAC,CAEzB,EACJ,IAAyB,EAAA,oBAAoB,EAAe,CACxD,EAAU,IAAgB,EAAA,iBAAiB,EAAe,CAC1D,GAA2B,EAAA,QAAM,YAEnC,EACE,EAAkB,MAClB,EAAE,EAAA,QAAQ,gCAAgC,CAC3C,CACH,CAAC,EAAkB,MAAO,EAAE,CAC7B,CAEK,GAAqB,EAAA,QAAM,YACxB,EAAwB,KAAK,UAAU,EAAsB,CAAG,GACvE,CAAC,EAAsB,CACxB,CAEK,EAAgB,EAAA,QAAM,YAAc,CACxC,GAAI,CAAC,GAAY,CAAC,EAAgB,OAAO,KACzC,IAAM,EAAO,EAAA,+BACX,EACA,EACA,EACD,CAED,OADK,EACE,CAAE,GAAG,EAAM,GAAG,EAAuB,CADT,GAIlC,CAAC,EAAU,EAAgB,EAAgB,GAAmB,CAAC,CAE5D,EAAc,EAAA,QAAM,YACpB,CAAC,GAAY,CAAC,EAAuB,KAMlC,GAJqB,EACxB,EAAe,EAAU,EAAe,CACxC,EAAA,iBAAiB,EAAU,EAAgB,EAAe,CAEpB,CAAE,eAAc,UAAS,CAAC,CACnE,CACD,EACA,EACA,EACA,EACA,EACA,EACD,CAAC,CAEF,EAAA,QAAM,cAAgB,CACpB,EAAmB,QAAU,GAC7B,EAAQ,QAAQ,CAChB,EAAU,EAAE,CAAC,CACb,EAAS,EAAE,CAAC,EACX,CAAC,EAAO,EAAgB,EAAqB,CAAC,CAEjD,EAAA,QAAM,cAAgB,CAChB,CAAC,GAAiB,CAAC,IAEvB,EAAU,EAAc,CAUxB,EAL0C,EACtC,OAAO,YACL,OAAO,KAAK,EAAsB,CAAC,IAAK,GAAQ,CAAC,EAAK,GAAK,CAAC,CAC7D,CACD,EAAE,CACiB,CACvB,EAAS,GACF,EAAmB,QAKjB,GAAoB,EAAa,EAAY,EAJlD,EAAmB,QAAU,GACtB,GAIT,GAID,CAAC,EAAe,EAAY,CAAC,CAEhC,IAAM,GAAkB,EAAA,QAAM,YACvB,EACE,EAAA,2BACL,EACA,EACA,EACA,EACD,CAN2B,EAAE,CAO7B,CAAC,EAAgB,EAAQ,EAAM,EAAY,CAAC,CAEzC,EAAoB,EAAA,QAAM,aAC7B,EAAkB,IAAgC,CACjD,EAAW,IAAU,CAAE,GAAG,GAAO,GAAW,EAAW,EAAE,CACzD,EAAU,IAAU,CAAE,GAAG,GAAO,GAAW,GAAM,EAAE,EAErD,EAAE,CACH,CAEK,GAAc,EAAA,QAAM,YACvB,GAAsB,CAErB,EAAA,kBADY,EAAA,0BAA0B,EACpB,EAAO,EAAE,EAAA,QAAQ,cAAc,CAAC,EAEpD,CAAC,EAAE,CACJ,CAKK,EAAgB,EAAA,QAAM,WAAyB,GAAG,CAClD,GAAa,EAAA,QAAM,gBAAkB,CACzC,EAAc,SAAS,EACtB,EAAE,CAAC,CAEA,MAAmB,CACvB,GAAI,CAAC,EAA8B,OAEnC,IAAI,EACJ,GAAI,CACF,IAAM,EAAc,EAAA,+BAClB,EACA,EACA,EACA,EACD,CACG,EACJ,AAGE,EAHE,IAAmB,wBACJ,CAAE,2BAA4B,EAAa,CAE3C,CAAE,oBAAqB,EAAa,CAEvD,EAAU,EACN,EAAa,EAAa,CAAE,SAAQ,QAAO,OAAM,CAAC,CAClD,QACG,EAAO,CACd,EAAA,kBACE,aAAiB,MAAQ,EAAM,QAAU,EAAE,EAAA,QAAQ,cAAc,CAClE,CACD,OAGE,OAAO,KAAK,EAAQ,CAAC,SAAW,GAEpC,GAAa,EAAS,CACpB,QAAS,GACT,cAAiB,CACf,EAAA,oBAAoB,EAAE,EAAA,QAAQ,uBAAuB,CAAC,CACtD,EAAS,EAAE,CAAC,CACZ,KAAiB,EAEpB,CAAC,EAGJ,EAAc,QAAU,EAQxB,IAAM,EAAqB,OAAO,KAAK,EAAM,CAAC,OAAS,GAAK,EA6B5D,OA5BA,EAAA,QAAM,cAAgB,CACf,GACL,EAAoB,CAClB,KAAM,GACN,SAAU,EACV,QAAS,EACT,SACD,CAAC,EACD,CAAC,EAAW,EAAoB,EAAO,CAAC,CAEvC,IAAa,IAAc,GACtB,EAAA,EAAA,KAAC,EAAA,0BAAD,EAA6B,CAAA,CAGlC,CAAC,GAAkB,EAAe,SAAS,SAAW,GAEtD,EAAA,EAAA,KAAC,EAAA,WAAW,UAAZ,CAAsB,UAAU,6BAC7B,GACoB,CAAA,CAIvB,OAAO,KAAK,EAAO,CAAC,SAAW,GAAU,EAAA,EAAA,KAAC,EAAA,0BAAD,EAA6B,CAAA,EAOxE,EAAA,EAAA,MAAC,MAAD,CACE,cAAa,GACb,UACE,EACI,+CACA,mCALR,EAQE,EAAA,EAAA,KAAC,EAAA,WAAD,CACQ,OACG,UACK,eACL,UACT,WAAY,GACZ,CAAA,EAEF,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,+BAAhB,CACG,KAAS,CACR,SACA,WAAY,GACZ,OACA,SAAU,EACX,CAAC,CAED,GAAgB,KAAK,EAAS,KAC7B,EAAA,EAAA,KAAC,UAAD,CAEE,UAAU,gCAEV,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,+BACZ,EAAQ,OAAO,IAAK,IACnB,EAAA,EAAA,KAAC,EAAA,YAAD,CAES,QACP,MAAO,EAAO,EAAM,KACpB,WAAY,GACZ,SAAW,GACT,EAAkB,EAAM,IAAK,EAAU,CAEzC,CAPK,EAAM,IAOX,CACF,CACE,CAAA,CACE,CAhBH,GAAG,EAAQ,IAAI,GAAG,IAgBf,CACV,CAEe,EAgBb,MAfF,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oCACb,EAAA,EAAA,KAAC,EAAA,YAAD,CACE,OAAO,cACP,KAAK,SACL,QAAQ,UACR,WACE,GAAc,OAAO,KAAK,EAAM,CAAC,SAAW,GAAK,CAAC,EAEpD,QAAS,WAGL,EADH,EACK,EAAA,QAAQ,gBACR,EAAA,QAAQ,sBAAsB,CACxB,CAAA,CACV,CAAA,CAEJ,GACF"}
|
|
1
|
+
{"version":3,"file":"sdk-section-page.cjs","names":[],"sources":["../../../../../src/components/features/settings/sdk-settings/sdk-section-page.tsx"],"sourcesContent":["import React from \"react\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { LlmSettingsInputsSkeleton } from \"#/components/features/settings/llm-settings/llm-settings-inputs-skeleton\";\nimport { useSaveSettings } from \"#/hooks/mutation/use-save-settings\";\nimport {\n useAgentSettingsSchema,\n useConversationSettingsSchema,\n} from \"#/hooks/query/use-agent-settings-schema\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { Typography } from \"#/ui/typography\";\nimport { Settings, SettingsSchema, SettingsScope } from \"#/types/settings\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport {\n buildInitialSettingsFormValues,\n buildSdkSettingsPayload,\n buildSdkSettingsPayloadForView,\n getVisibleSettingsSections,\n hasAdvancedSettings,\n hasMinorSettings,\n inferInitialView,\n isValidSettingsSchema,\n SettingsDirtyState,\n SettingsFormValues,\n type SettingsValueSource,\n type SettingsView,\n} from \"#/utils/sdk-settings-schema\";\nimport { SchemaField } from \"./schema-field\";\nimport { ViewToggle } from \"./view-toggle\";\n\nconst EMPTY_EXCLUDE_KEYS = new Set<string>();\n\nconst VIEW_ORDER: Record<SettingsView, number> = {\n basic: 0,\n advanced: 1,\n all: 2,\n};\n\nconst getLessDetailedView = (\n currentView: SettingsView,\n nextView: SettingsView,\n): SettingsView =>\n VIEW_ORDER[nextView] < VIEW_ORDER[currentView] ? nextView : currentView;\n\nconst normalizeView = (\n view: SettingsView,\n {\n showAdvanced,\n showAll,\n }: {\n showAdvanced: boolean;\n showAll: boolean;\n },\n): SettingsView => {\n if (view === \"all\") {\n if (showAll) {\n return \"all\";\n }\n\n return showAdvanced ? \"advanced\" : \"basic\";\n }\n\n if (view === \"advanced\") {\n if (showAdvanced) {\n return \"advanced\";\n }\n\n return showAll ? \"all\" : \"basic\";\n }\n\n return \"basic\";\n};\n\nconst getSchemaUnavailableMessage = (\n error: unknown,\n fallbackMessage: string,\n): string => {\n if (!(error instanceof AxiosError)) {\n return fallbackMessage;\n }\n\n if (error.response?.status === 401) {\n return `${fallbackMessage} This agent server requires X-Session-API-Key. Set VITE_SESSION_API_KEY in the frontend to the same value used by the backend SESSION_API_KEY or OH_SESSION_API_KEYS_0.`;\n }\n\n if (error.response?.status === 404) {\n return `${fallbackMessage} This backend does not expose /api/settings/* schema endpoints. Upgrade to a recent openhands-agent-server release.`;\n }\n\n return fallbackMessage;\n};\n\nexport interface SdkSectionHeaderProps {\n values: SettingsFormValues;\n isDisabled: boolean;\n view: SettingsView;\n onChange: (key: string, value: string | boolean) => void;\n}\n\n/**\n * Snapshot of the page's save state, surfaced to the parent so it can\n * render its own Save/Next button (e.g. in onboarding) when\n * {@link SdkSectionPage}'s built-in button is hidden via\n * `hideSaveButton`.\n */\nexport interface SdkSectionSaveControl {\n /** Trigger a save of the currently-dirty fields. No-op while `isSaving` or `!isDirty`. */\n save: () => void;\n /** A save mutation is in flight. */\n isSaving: boolean;\n /** At least one field is dirty (or `extraDirty` was passed in). */\n isDirty: boolean;\n /** Current form values (for custom save flows). */\n values: SettingsFormValues;\n /** The active view tier (basic/advanced/all) the form is rendering. */\n view: SettingsView;\n /**\n * Returns the coerced, dirty-only payload as a nested object\n * (e.g. `{ llm: { temperature: 0.7 } }`). Lets a custom save flow persist\n * exactly the fields the user changed, with proper types, without\n * re-implementing schema-driven coercion. Throws if a field fails coercion.\n */\n getDirtyPayload: () => Record<string, unknown>;\n}\n\n/**\n * A generic SDK-schema–driven settings page that renders fields\n * from one or more schema sections.\n *\n * @param sectionKeys - which schema section(s) this page owns (e.g. [\"condenser\"])\n * @param excludeKeys - field keys to skip (rendered elsewhere by the caller)\n * @param header - optional render prop receiving shared state to render above fields\n * @param testId - data-testid for the page wrapper\n */\nexport function SdkSectionPage({\n sectionKeys,\n excludeKeys = EMPTY_EXCLUDE_KEYS,\n scope = \"personal\",\n settingsSource = \"agent_settings\",\n header,\n extraDirty = false,\n buildPayload,\n onSaveSuccess,\n getInitialView,\n forceShowAdvancedView = false,\n allowAllView = true,\n initialValueOverrides,\n embedded = false,\n hideSaveButton = false,\n onSaveControlChange,\n testId = \"sdk-section-settings-screen\",\n}: {\n sectionKeys: string[];\n excludeKeys?: Set<string>;\n scope?: SettingsScope;\n settingsSource?: SettingsValueSource;\n\n header?: (props: SdkSectionHeaderProps) => React.ReactNode;\n extraDirty?: boolean;\n buildPayload?: (\n payload: ReturnType<typeof buildSdkSettingsPayloadForView>,\n context: {\n values: SettingsFormValues;\n dirty: SettingsDirtyState;\n view: SettingsView;\n },\n ) => Record<string, unknown>;\n onSaveSuccess?: () => void;\n getInitialView?: (\n settings: Settings,\n filteredSchema: SettingsSchema,\n ) => SettingsView;\n forceShowAdvancedView?: boolean;\n allowAllView?: boolean;\n /**\n * Per-field initial value overrides that win over the values\n * derived from `useSettings`. The keys of each override are also\n * marked dirty on hydration so the user can save the form without\n * having to touch the prefilled fields. Useful when the page is\n * embedded in a flow that wants to nudge brand-new users toward a\n * particular default (e.g. onboarding pre-filling OpenHands/Opus).\n */\n initialValueOverrides?: SettingsFormValues;\n /**\n * When true, the Save button container is rendered inline (no\n * sticky positioning, no contrasting `bg-base` band) so the page\n * can be dropped into a modal/card without a hard footer break.\n */\n embedded?: boolean;\n /**\n * Suppress the built-in Save Changes button entirely. Pair with\n * {@link onSaveControlChange} to drive saving from a parent-rendered\n * action (e.g. an onboarding \"Next\" button).\n */\n hideSaveButton?: boolean;\n /**\n * Fires whenever the save state changes (a mutation starts/finishes,\n * dirty status flips). Provides a stable `save()` callback the\n * parent can wire to its own button. Useful when the form is\n * embedded in a custom flow and the built-in Save button is hidden.\n */\n onSaveControlChange?: (control: SdkSectionSaveControl) => void;\n testId?: string;\n}) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: saveSettings, isPending } = useSaveSettings(scope);\n const { data: settings, isLoading, isFetching } = useSettings(scope);\n const agentSchemaQuery = useAgentSettingsSchema(\n settings?.agent_settings_schema,\n );\n const conversationSchemaQuery = useConversationSettingsSchema(\n settings?.conversation_settings_schema,\n );\n const activeSchemaQuery =\n settingsSource === \"conversation_settings\"\n ? conversationSchemaQuery\n : agentSchemaQuery;\n const schema = activeSchemaQuery.data;\n const isSchemaLoading = activeSchemaQuery.isLoading;\n const isReadOnly = false;\n\n const [view, setView] = React.useState<SettingsView>(\"basic\");\n const [values, setValues] = React.useState<SettingsFormValues>({});\n const [dirty, setDirty] = React.useState<SettingsDirtyState>({});\n const hasHydratedViewRef = React.useRef(false);\n\n const sectionKeysSignature = React.useMemo(\n () => JSON.stringify(sectionKeys),\n [sectionKeys],\n );\n const stableSectionKeys = React.useMemo(\n () => JSON.parse(sectionKeysSignature) as string[],\n [sectionKeysSignature],\n );\n\n // Build a filtered schema containing only the requested sections.\n // `isValidSettingsSchema` guards against truthy-but-malformed schema\n // responses (e.g. when the deployment is pointed at a host that does\n // not serve `/api/settings/agent-schema` and returns an SPA shell\n // that parses into an object without a `sections` array). Without\n // the guard, `schema.sections.filter(...)` would throw and React\n // Router would escalate the crash to a full-screen error.\n const filteredSchema = React.useMemo(() => {\n if (!isValidSettingsSchema(schema)) return null;\n const sectionSet = new Set(stableSectionKeys);\n return {\n ...schema,\n sections: schema.sections.filter((s) => sectionSet.has(s.key)),\n };\n }, [schema, stableSectionKeys]);\n\n const showAdvanced =\n forceShowAdvancedView || hasAdvancedSettings(filteredSchema);\n const showAll = allowAllView && hasMinorSettings(filteredSchema);\n const schemaUnavailableMessage = React.useMemo(\n () =>\n getSchemaUnavailableMessage(\n activeSchemaQuery.error,\n t(I18nKey.SETTINGS$SDK_SCHEMA_UNAVAILABLE),\n ),\n [activeSchemaQuery.error, t],\n );\n\n const overridesSignature = React.useMemo(\n () => (initialValueOverrides ? JSON.stringify(initialValueOverrides) : \"\"),\n [initialValueOverrides],\n );\n\n const initialValues = React.useMemo(() => {\n if (!settings || !filteredSchema) return null;\n const base = buildInitialSettingsFormValues(\n settings,\n filteredSchema,\n settingsSource,\n );\n if (!initialValueOverrides) return base;\n return { ...base, ...initialValueOverrides };\n // overridesSignature keeps the memo reactive without depending on\n // a (potentially recreated) object reference each render.\n }, [settings, filteredSchema, settingsSource, overridesSignature]);\n\n const initialView = React.useMemo(() => {\n if (!settings || !filteredSchema) return null;\n\n const resolvedInitialView = getInitialView\n ? getInitialView(settings, filteredSchema)\n : inferInitialView(settings, filteredSchema, settingsSource);\n\n return normalizeView(resolvedInitialView, { showAdvanced, showAll });\n }, [\n settings,\n filteredSchema,\n getInitialView,\n settingsSource,\n showAdvanced,\n showAll,\n ]);\n\n React.useEffect(() => {\n hasHydratedViewRef.current = false;\n setView(\"basic\");\n setValues({});\n setDirty({});\n }, [scope, settingsSource, sectionKeysSignature]);\n\n React.useEffect(() => {\n if (!initialValues || !initialView) return;\n\n setValues(initialValues);\n // Override-supplied keys are pre-populated for the user, so mark\n // them dirty up-front; otherwise the Save button stays disabled\n // until the user touches a field, defeating the point of the\n // override.\n const overrideDirty: SettingsDirtyState = initialValueOverrides\n ? Object.fromEntries(\n Object.keys(initialValueOverrides).map((key) => [key, true]),\n )\n : {};\n setDirty(overrideDirty);\n setView((currentView) => {\n if (!hasHydratedViewRef.current) {\n hasHydratedViewRef.current = true;\n return initialView;\n }\n\n return getLessDetailedView(currentView, initialView);\n });\n // initialValueOverrides is intentionally tracked via\n // overridesSignature on initialValues; including the object ref\n // here would re-fire the effect every render.\n }, [initialValues, initialView]);\n\n const visibleSections = React.useMemo(() => {\n if (!filteredSchema) return [];\n return getVisibleSettingsSections(\n filteredSchema,\n values,\n view,\n excludeKeys,\n );\n }, [filteredSchema, values, view, excludeKeys]);\n\n const handleFieldChange = React.useCallback(\n (fieldKey: string, nextValue: string | boolean) => {\n setValues((prev) => ({ ...prev, [fieldKey]: nextValue }));\n setDirty((prev) => ({ ...prev, [fieldKey]: true }));\n },\n [],\n );\n\n const handleError = React.useCallback(\n (error: AxiosError) => {\n const msg = retrieveAxiosErrorMessage(error);\n displayErrorToast(msg || t(I18nKey.ERROR$GENERIC));\n },\n [t],\n );\n\n // Stable save callback so `onSaveControlChange` can hand a single\n // function reference to the parent across renders. The latest\n // closure is kept up to date via `handleSaveRef`.\n const handleSaveRef = React.useRef<() => void>(() => {});\n const stableSave = React.useCallback(() => {\n handleSaveRef.current();\n }, []);\n\n // Stable accessor for the coerced, dirty-only payload. Mirrors the\n // `handleSaveRef` pattern so the exposed function reference stays stable\n // across renders while always reading the latest closure at call time.\n const buildDirtyPayloadRef = React.useRef<() => Record<string, unknown>>(\n () => ({}),\n );\n const stableGetDirtyPayload = React.useCallback(\n () => buildDirtyPayloadRef.current(),\n [],\n );\n\n const handleSave = () => {\n if (!filteredSchema || isReadOnly) return;\n\n let payload: Record<string, unknown>;\n try {\n const basePayload = buildSdkSettingsPayloadForView(\n filteredSchema,\n values,\n dirty,\n view,\n );\n let defaultPayload: Record<string, unknown>;\n if (settingsSource === \"conversation_settings\") {\n defaultPayload = { conversation_settings_diff: basePayload };\n } else {\n defaultPayload = { agent_settings_diff: basePayload };\n }\n payload = buildPayload\n ? buildPayload(basePayload, { values, dirty, view })\n : defaultPayload;\n } catch (error) {\n displayErrorToast(\n error instanceof Error ? error.message : t(I18nKey.ERROR$GENERIC),\n );\n return;\n }\n\n if (Object.keys(payload).length === 0) return;\n\n saveSettings(payload, {\n onError: handleError,\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.SETTINGS$SAVED_WARNING));\n setDirty({});\n onSaveSuccess?.();\n },\n });\n };\n\n handleSaveRef.current = handleSave;\n // Dirty-only (NOT view-filtered): we must never inject defaults for\n // non-visible fields here, or a custom save flow would reset fields the\n // user never touched. `buildSdkSettingsPayloadForView` is reserved for the\n // built-in full-replace save above.\n buildDirtyPayloadRef.current = () =>\n filteredSchema\n ? buildSdkSettingsPayload(filteredSchema, values, dirty)\n : {};\n\n // Surface save state to the parent. Hooks must run before any\n // conditional early-returns below, so this lives here rather than\n // alongside the JSX. The dependency list deliberately excludes\n // `stableSave` (it never changes) and `onSaveControlChange` (we\n // tolerate ref-instability of the callback to avoid spamming the\n // parent on every render).\n const saveControlIsDirty = Object.keys(dirty).length > 0 || extraDirty;\n React.useEffect(() => {\n if (!onSaveControlChange) return;\n onSaveControlChange({\n save: stableSave,\n isSaving: isPending,\n isDirty: saveControlIsDirty,\n values,\n view,\n getDirtyPayload: stableGetDirtyPayload,\n });\n }, [isPending, saveControlIsDirty, values, view]);\n\n if (isLoading || isFetching || isSchemaLoading) {\n return <LlmSettingsInputsSkeleton />;\n }\n\n if (!filteredSchema || filteredSchema.sections.length === 0) {\n return (\n <Typography.Paragraph className=\"text-tertiary-alt\">\n {schemaUnavailableMessage}\n </Typography.Paragraph>\n );\n }\n\n if (Object.keys(values).length === 0) return <LlmSettingsInputsSkeleton />;\n\n // Scrolling is owned by the settings shell (or onboarding wrapper), not a\n // nested scroll region. Save actions are inline after the last field.\n const bodyClassName = \"flex flex-col gap-8\";\n\n return (\n <div\n data-testid={testId}\n className={\n embedded\n ? \"relative flex min-h-0 w-full flex-1 flex-col\"\n : \"relative w-full min-h-0\"\n }\n >\n <ViewToggle\n view={view}\n setView={setView}\n showAdvanced={showAdvanced}\n showAll={showAll}\n isDisabled={isReadOnly}\n />\n\n <div className={bodyClassName}>\n {header?.({\n values,\n isDisabled: isReadOnly,\n view,\n onChange: handleFieldChange,\n })}\n\n {visibleSections.map((section, sectionIndex) => (\n <section\n key={`${section.key}-${sectionIndex}`}\n className=\"flex flex-col gap-4\"\n >\n <div className=\"flex flex-col gap-4\">\n {section.fields.map((field) => (\n <SchemaField\n key={field.key}\n field={field}\n value={values[field.key]}\n isDisabled={isReadOnly}\n onChange={(nextValue) =>\n handleFieldChange(field.key, nextValue)\n }\n />\n ))}\n </div>\n </section>\n ))}\n\n {!isReadOnly && !hideSaveButton ? (\n <div className=\"flex justify-start pt-2\">\n <BrandButton\n testId=\"save-button\"\n type=\"button\"\n variant=\"primary\"\n isDisabled={\n isPending || (Object.keys(dirty).length === 0 && !extraDirty)\n }\n onClick={handleSave}\n >\n {isPending\n ? t(I18nKey.SETTINGS$SAVING)\n : t(I18nKey.SETTINGS$SAVE_CHANGES)}\n </BrandButton>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -22,6 +22,15 @@ export interface SdkSectionSaveControl {
|
|
|
22
22
|
isDirty: boolean;
|
|
23
23
|
/** Current form values (for custom save flows). */
|
|
24
24
|
values: SettingsFormValues;
|
|
25
|
+
/** The active view tier (basic/advanced/all) the form is rendering. */
|
|
26
|
+
view: SettingsView;
|
|
27
|
+
/**
|
|
28
|
+
* Returns the coerced, dirty-only payload as a nested object
|
|
29
|
+
* (e.g. `{ llm: { temperature: 0.7 } }`). Lets a custom save flow persist
|
|
30
|
+
* exactly the fields the user changed, with proper types, without
|
|
31
|
+
* re-implementing schema-driven coercion. Throws if a field fails coercion.
|
|
32
|
+
*/
|
|
33
|
+
getDirtyPayload: () => Record<string, unknown>;
|
|
25
34
|
}
|
|
26
35
|
/**
|
|
27
36
|
* A generic SDK-schema–driven settings page that renders fields
|
|
@@ -54,7 +63,7 @@ export declare function SdkSectionPage({ sectionKeys, excludeKeys, scope, settin
|
|
|
54
63
|
* marked dirty on hydration so the user can save the form without
|
|
55
64
|
* having to touch the prefilled fields. Useful when the page is
|
|
56
65
|
* embedded in a flow that wants to nudge brand-new users toward a
|
|
57
|
-
* particular default (e.g. onboarding pre-filling
|
|
66
|
+
* particular default (e.g. onboarding pre-filling OpenHands/Opus).
|
|
58
67
|
*/
|
|
59
68
|
initialValueOverrides?: SettingsFormValues;
|
|
60
69
|
/**
|