@openhands/agent-canvas 1.7.2 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.windows.md +2 -2
- package/build/assets/{Trans-DP5rcauH.js → Trans-Bwpzk1wT.js} +1 -1
- package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-C921BlYB.js} +1 -1
- package/build/assets/active-backend-context-BiwzkzDy.js +2 -0
- package/build/assets/agent-context-settings-DXNT_dcw.js +1 -0
- package/build/assets/agent-profiles-settings-BymJf3EP.js +1 -0
- package/build/assets/agent-server-conversation-service.api-CYSWw-2g.js +41 -0
- package/build/assets/agent-settings-BjgQQe-_.js +1 -0
- package/build/assets/{agent-settings-BIOsUglV.js → agent-settings-WzqXk6B4.js} +2 -2
- package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-DR8EVyZM.js} +1 -1
- package/build/assets/api-error-message-e16L1kwH.js +1 -0
- package/build/assets/api-key-entry-screen-DI0I04O3.js +1 -0
- package/build/assets/app-settings-DGistSFV.js +1 -0
- package/build/assets/automation-C_eCrGyP.js +1 -0
- package/build/assets/automation-detail-DY6x2FW1.js +2 -0
- package/build/assets/automation-export-C09f-Lua.js +2 -0
- package/build/assets/automation-setup-route-CqKp0717.js +1 -0
- package/build/assets/automations-list-CqWJ7qXW.js +1 -0
- package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-D4ngzpSh.js} +1 -1
- package/build/assets/backend-form-modal-B8D5hBzK.js +1 -0
- package/build/assets/{backend-synced-settings-badge-BNpEylNP.js → backend-synced-settings-badge-BnzI8Ysj.js} +1 -1
- package/build/assets/{badge-DwgrwohM.js → badge-1Mf1iPcX.js} +1 -1
- package/build/assets/{base-modal-CSHhJTSr.js → base-modal-BBuy0WQQ.js} +1 -1
- package/build/assets/{brand-button-CQO8oqVo.js → brand-button-DGN6Y9o6.js} +1 -1
- package/build/assets/browser-D_ekTlTS.js +6 -0
- package/build/assets/{browser-tab-CEApjoEV.js → browser-tab-D4a4Ou_w.js} +1 -1
- package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-CgbcjD97.js} +1 -1
- package/build/assets/check-CPLXgluF.js +1 -0
- package/build/assets/chevron-down-CP4QHvyc.js +1 -0
- package/build/assets/circle-check-Dpy2_xSI.js +1 -0
- package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-yTAS-nX3.js} +1 -1
- package/build/assets/cloud-funnel-analytics-CEOl5Gxr.js +1 -0
- package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Bd2yySnF.js} +1 -1
- package/build/assets/command-menu-Bj6X4ckE.js +1 -0
- package/build/assets/condenser-settings-EAXQNR2E.js +1 -0
- package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-NCUPr2-O.js} +1 -1
- package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-CrCrYuPF.js} +1 -1
- package/build/assets/conversation-BzyIcSwr.js +1 -0
- package/build/assets/conversation-CUJ0Vo8g.js +90 -0
- package/build/assets/conversation-panel-BzyIcSwr.js +1 -0
- package/build/assets/conversation-state-store-F62HvuI1.js +1 -0
- package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-BCZ7rUMH.js} +1 -1
- package/build/assets/{copy-B8Y5ufoR.js → copy-DCmZtz6n.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-D_Lp6-Fl.js} +1 -1
- package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-DLmolX8Q.js} +1 -1
- package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-BB8rzqXL.js} +1 -1
- package/build/assets/{entry.client-DETaouwO.js → entry.client-BbIYOsIg.js} +2 -2
- package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-C08-srev.js} +1 -1
- package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-BepBBX66.js} +1 -1
- package/build/assets/extensions-hub-R3KNv-5V.js +1 -0
- package/build/assets/extensions-navigation-CfWFmI1I.js +1 -0
- package/build/assets/{external-link-Cnnd6ikC.js → external-link-BdBSg8rk.js} +1 -1
- package/build/assets/files-tab-DEq8MbHu.js +1 -0
- package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-DAfsCJTe.js} +1 -1
- package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-CxfPJpzC.js} +1 -1
- package/build/assets/git-provider-icon-BZqqUPlm.js +1 -0
- package/build/assets/git-repo-dropdown-9WKINV6J.js +1 -0
- package/build/assets/git-repo-dropdown-DEpOwUez.js +1 -0
- package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-CX9oIoVT.js} +1 -1
- package/build/assets/home-CY0JaxiY.js +1 -0
- package/build/assets/home-CaNWlVvB.js +1 -0
- package/build/assets/home-store-Ch1ErdBc.js +1 -0
- package/build/assets/index-home-CaNWlVvB.js +1 -0
- package/build/assets/info-CmWQXtRQ.js +1 -0
- package/build/assets/install-server-modal-BWrudmZU.js +1 -0
- package/build/assets/{launch-Ccnhte5b.js → launch-B1POpHuP.js} +1 -1
- package/build/assets/{list-todo-_BXQzOiB.js → list-todo-DtiL3lTp.js} +1 -1
- package/build/assets/llm-not-configured-banner-3tMsM4K6.js +27 -0
- package/build/assets/llm-settings-CXo8iPNW.js +1 -0
- package/build/assets/llm-settings-D0W8mJDk.js +1 -0
- package/build/assets/{llm-subscription-service-W5BprsNA.js → llm-subscription-service-DBJbfd8Z.js} +1 -1
- package/build/assets/loader-circle-B4QDBARx.js +1 -0
- package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DfZ_bhV7.js} +1 -1
- package/build/assets/manage-backends-modal-CwyWsiag.js +1 -0
- package/build/assets/manifest-39f4789d.js +1 -0
- package/build/assets/{markdown-renderer-CvOO0YIr.js → markdown-renderer-DgiLLhW6.js} +6 -6
- package/build/assets/mcp-DXG9LWrI.js +9 -0
- package/build/assets/mcp-marketplace-utils-DFmhKc5s.js +1 -0
- package/build/assets/messages-kBjKaAeA.js +40 -0
- package/build/assets/{modal-body-DQhiw-AR.js → modal-body-CMsDpalT.js} +1 -1
- package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-B6PDrxXo.js} +1 -1
- package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-DyxBZaAb.js} +1 -1
- package/build/assets/{onboarding-BegDrOKn.js → onboarding-47hh2IHA.js} +1 -1
- package/build/assets/onboarding-modal-9BuvvROo.js +1 -0
- package/build/assets/organization-service.api-UDy63-oC.js +1 -0
- package/build/assets/{pencil-8_lvWDoZ.js → pencil-BjgtZmWp.js} +1 -1
- package/build/assets/{planner-tab-w6HT0N_A.js → planner-tab-BWk8885v.js} +1 -1
- package/build/assets/plugins-management-service-CjkgF2dd.js +1 -0
- package/build/assets/plus-DrKuuvMe.js +1 -0
- package/build/assets/profiles-service.api-CukSFLzz.js +1 -0
- package/build/assets/providers-CqUWC85T.js +1 -0
- package/build/assets/proxy-BBUG3sd2.js +1 -0
- package/build/assets/{puzzle-DXWdfaa7.js → puzzle-BoNc6zZ8.js} +1 -1
- package/build/assets/recommended-automations-launcher-ejxy1P27.js +1 -0
- package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-BrM5ZAZD.js} +1 -1
- package/build/assets/root-5S-M8SYa.js +2 -0
- package/build/assets/root-DZ39lS5f.css +1 -0
- package/build/assets/root-layout-BPqoa0gv.js +3 -0
- package/build/assets/schema-field-nImDoY6-.js +1 -0
- package/build/assets/{sdk-section-page-BW-i45yr.js → sdk-section-page-BxMrtUNV.js} +1 -1
- package/build/assets/search-Dc2qR4O2.js +1 -0
- package/build/assets/secrets-service-Dhjh3HhH.js +1 -0
- package/build/assets/{secrets-settings-D7U1ErCH.js → secrets-settings-CPdxceT_.js} +1 -1
- package/build/assets/segmented-toggle-Do6oyepX.js +1 -0
- package/build/assets/settings-BRbnfKEm.js +1 -0
- package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-DYCULKpp.js} +1 -1
- package/build/assets/{settings-index-COAdxm2Q.js → settings-index-C9o2NBO0.js} +1 -1
- package/build/assets/settings-input-B-q2gkVy.js +1 -0
- package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-WpQi0q1L.js} +1 -1
- package/build/assets/{settings-modal-CFnbQ8_4.js → settings-modal-CEK0AIx6.js} +1 -1
- package/build/assets/settings-service.api-CZiPD8__.js +1 -0
- package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-LqKdGxHL.js} +1 -1
- package/build/assets/shared-conversation-Bu-dQlgp.js +1 -0
- package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-oHBGQmLh.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-U78hQRJ1.js → sidebar-mobile-menu-toggle-ND-hgygu.js} +1 -1
- package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-CrujNA09.js} +1 -1
- package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-Bui-WNEr.js} +1 -1
- package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-CZBI7OqH.js} +1 -1
- package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-BOov_phZ.js} +1 -1
- package/build/assets/{skills-plugins-BPhaNpfx.js → skills-plugins-D0PiHWAD.js} +1 -1
- package/build/assets/{skills-settings-CcwMtnnJ.js → skills-settings-B43KArIz.js} +2 -2
- package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-C7grwnOX.js} +1 -1
- package/build/assets/{task-list-tab-BmaTwjaS.js → task-list-tab-R3ac6m7O.js} +1 -1
- package/build/assets/{terminal-BRcoba5B.js → terminal-yqkNdEAx.js} +1 -1
- package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-BeSrbgCg.js} +1 -1
- package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-wW5TWcdN.js} +1 -1
- package/build/assets/{typography-C6fuRTTT.js → typography-iYhzLlHO.js} +1 -1
- package/build/assets/{use-acp-credential-form-B0_pZ_uS.js → use-acp-credential-form-DUxbxmbq.js} +1 -1
- package/build/assets/use-activate-agent-profile-CDHA52tC.js +1 -0
- package/build/assets/use-agent-profiles-TsOdIyw5.js +1 -0
- package/build/assets/{use-can-manage-org-profiles-CrG1km7R.js → use-can-manage-org-profiles-Bt1M71u5.js} +1 -1
- package/build/assets/use-cloud-current-user-id-DWt7HCgf.js +1 -0
- package/build/assets/{use-config-Csy8EAP9.js → use-config-CxlEdf_v.js} +1 -1
- package/build/assets/{use-create-conversation-Dsa4nzU9.js → use-create-conversation-nOJ6Um5h.js} +1 -1
- package/build/assets/{use-create-secret-BnxuAjDt.js → use-create-secret-Dj5ang9x.js} +1 -1
- package/build/assets/use-is-authed-BT7Iud4U.js +1 -0
- package/build/assets/{use-is-creating-conversation-CIAcnd8M.js → use-is-creating-conversation-CAggrM75.js} +1 -1
- package/build/assets/use-llm-profiles-2Wc2db8u.js +1 -0
- package/build/assets/use-onboarding-completion-gxQlcEy2.js +1 -0
- package/build/assets/use-plugins-marketplace-CVO7sXYR.js +1 -0
- package/build/assets/use-save-agent-profile-D0wC5ExW.js +1 -0
- package/build/assets/{use-save-settings-BRh9p_fv.js → use-save-settings-L3aMaDeS.js} +1 -1
- package/build/assets/use-settings-8nt3DGxW.js +1 -0
- package/build/assets/use-settings-nav-items-DHAAD-zk.js +16 -0
- package/build/assets/use-skills-CE6miQ3r.js +1 -0
- package/build/assets/use-tracking-BGboadaZ.js +68 -0
- package/build/assets/{use-user-conversation-GnGhs_Ob.js → use-user-conversation-BIIpGUgM.js} +1 -1
- package/build/assets/useInfiniteQuery-BLRVmVPU.js +1 -0
- package/build/assets/{useMutation-DyQXZFEF.js → useMutation-CaSHLnX0.js} +1 -1
- package/build/assets/{useQueries-B3T1a7qt.js → useQueries--d_WWAzc.js} +1 -1
- package/build/assets/{useQuery-B38jBavx.js → useQuery-DiPh8LRJ.js} +1 -1
- package/build/assets/utils-BgGG1znF.js +1 -0
- package/build/assets/{vendor~browser-CIoZCqGs.js → vendor~browser-IVYgIgG1.js} +1 -1
- package/build/assets/{vendor~entry.client-Di4qO77Y.js → vendor~entry.client-BcYIVQvB.js} +1 -1
- package/build/assets/{vendor~entry.client-BfviqoVc.js → vendor~entry.client-CXM9oiAk.js} +1 -1
- package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0bpqexo-CbTboogo.js} +2 -2
- package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f9xdmd0z-DLMP7bZx.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~d4by102p-C2f0ZhS-.js} +1 -1
- package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-C7RmQJwN.js} +1 -1
- package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-Bqp1ZqJM.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-BCn8lzeG.js} +1 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~automation-setup-route-B_L-gcOG.js +1 -0
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-sjx0x5ac.js +1 -0
- package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~automation-setup-route~onboarding-modal-D7IDevqN.js +1 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~bi2r7bko-Bw4AuHN1.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~dfc8ddxy-tTyxnjXT.js} +1 -1
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hakxo2tj-ClV0p9g3.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gy8zbn65-CGt6bWRT.js} +1 -1
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~eywn6ulz-BKxxr74w.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~dufan6ng-Dtdw8H0q.js} +17 -4
- package/build/assets/{verification-settings-CaCzojbc.js → verification-settings-DBsnSXC3.js} +1 -1
- package/build/assets/x-omAzpXkl.js +1 -0
- package/build/favicon-16x16.png +0 -0
- package/build/favicon-32x32.png +0 -0
- package/build/favicon.ico +0 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +39 -2
- package/build/locales/ca/openhands.json +39 -2
- package/build/locales/de/openhands.json +39 -2
- package/build/locales/en/openhands.json +40 -3
- package/build/locales/es/openhands.json +39 -2
- package/build/locales/fr/openhands.json +39 -2
- package/build/locales/it/openhands.json +39 -2
- package/build/locales/ja/openhands.json +39 -2
- package/build/locales/ko-KR/openhands.json +39 -2
- package/build/locales/no/openhands.json +39 -2
- package/build/locales/pt/openhands.json +39 -2
- package/build/locales/tr/openhands.json +39 -2
- package/build/locales/uk/openhands.json +39 -2
- package/build/locales/zh-CN/openhands.json +39 -2
- package/build/locales/zh-TW/openhands.json +39 -2
- package/config/defaults.json +4 -4
- package/dist/api/agent-server-adapter.cjs +3 -3
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.d.ts +46 -6
- package/dist/api/agent-server-adapter.js +187 -168
- 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 +4 -0
- package/dist/api/agent-server-compatibility.js +41 -38
- package/dist/api/agent-server-compatibility.js.map +1 -1
- package/dist/api/automation-service/automation-service.api.cjs +1 -1
- package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
- package/dist/api/automation-service/automation-service.api.d.ts +20 -0
- package/dist/api/automation-service/automation-service.api.js +136 -99
- package/dist/api/automation-service/automation-service.api.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 +1 -1
- package/dist/api/backend-registry/storage.js.map +1 -1
- package/dist/api/backend-registry/types.d.ts +2 -0
- package/dist/api/cloud/conversation-service.api.cjs +1 -1
- package/dist/api/cloud/conversation-service.api.js +22 -22
- package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
- package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
- package/dist/api/mcp-service/mcp-service.api.js +19 -19
- package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
- package/dist/api/settings-service/settings-service.api.cjs +1 -1
- package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
- package/dist/api/settings-service/settings-service.api.js +26 -12
- package/dist/api/settings-service/settings-service.api.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +2 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.d.ts +12 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +94 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +31 -90
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.d.ts +0 -7
- package/dist/components/features/automations/recommended-automations-section.d.ts +0 -6
- package/dist/components/features/backends/backend-form-modal.cjs +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
- package/dist/components/features/backends/backend-form-modal.js +568 -358
- package/dist/components/features/backends/backend-form-modal.js.map +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs.map +1 -1
- package/dist/components/features/backends/device-flow-auth.d.ts +9 -1
- package/dist/components/features/backends/device-flow-auth.js +56 -55
- package/dist/components/features/backends/device-flow-auth.js.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.js +1 -1
- package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
- package/dist/components/features/chat/chat-interface.cjs +1 -1
- package/dist/components/features/chat/chat-interface.cjs.map +1 -1
- package/dist/components/features/chat/chat-interface.js +105 -105
- package/dist/components/features/chat/chat-interface.js.map +1 -1
- package/dist/components/features/chat/chat-message.cjs +1 -1
- package/dist/components/features/chat/chat-message.cjs.map +1 -1
- package/dist/components/features/chat/chat-message.d.ts +2 -1
- package/dist/components/features/chat/chat-message.js +59 -49
- package/dist/components/features/chat/chat-message.js.map +1 -1
- package/dist/components/features/chat/pending-user-messages.cjs +1 -1
- package/dist/components/features/chat/pending-user-messages.cjs.map +1 -1
- package/dist/components/features/chat/pending-user-messages.js +4 -1
- package/dist/components/features/chat/pending-user-messages.js.map +1 -1
- package/dist/components/features/chat/typing-indicator.cjs +1 -1
- package/dist/components/features/chat/typing-indicator.cjs.map +1 -1
- package/dist/components/features/chat/typing-indicator.d.ts +8 -1
- package/dist/components/features/chat/typing-indicator.js +94 -10
- package/dist/components/features/chat/typing-indicator.js.map +1 -1
- package/dist/components/features/command-menu/command-menu-items.d.ts +5 -1
- package/dist/components/features/files-tab/segmented-toggle.cjs +1 -1
- package/dist/components/features/files-tab/segmented-toggle.cjs.map +1 -1
- package/dist/components/features/files-tab/segmented-toggle.d.ts +2 -0
- package/dist/components/features/files-tab/segmented-toggle.js +17 -14
- package/dist/components/features/files-tab/segmented-toggle.js.map +1 -1
- package/dist/components/features/manifest/manifest-form-field.d.ts +27 -0
- package/dist/components/features/manifest/manifest-prerequisites-step.d.ts +11 -0
- package/dist/components/features/manifest/manifest-review-step.d.ts +14 -0
- package/dist/components/features/manifest/manifest-setup-dialog.d.ts +14 -0
- package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.js +16 -16
- 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.d.ts +2 -2
- package/dist/components/features/mcp-page/installed-server-card.js +6 -7
- package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
- package/dist/components/features/mcp-page/installed-servers-section.cjs +1 -1
- package/dist/components/features/mcp-page/installed-servers-section.cjs.map +1 -1
- package/dist/components/features/mcp-page/installed-servers-section.d.ts +2 -2
- package/dist/components/features/mcp-page/installed-servers-section.js +2 -2
- package/dist/components/features/mcp-page/installed-servers-section.js.map +1 -1
- package/dist/components/features/mcp-page/mcp-server-health.cjs +1 -1
- package/dist/components/features/mcp-page/mcp-server-health.js +4 -4
- package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +1 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.js +2 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
- package/dist/components/features/settings/settings-input.cjs +1 -1
- package/dist/components/features/settings/settings-input.cjs.map +1 -1
- package/dist/components/features/settings/settings-input.d.ts +6 -0
- package/dist/components/features/settings/settings-input.js +13 -8
- package/dist/components/features/settings/settings-input.js.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.js +124 -123
- package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +3 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/contexts/active-backend-context.cjs +1 -1
- package/dist/contexts/active-backend-context.cjs.map +1 -1
- package/dist/contexts/active-backend-context.d.ts +3 -2
- package/dist/contexts/active-backend-context.js +55 -42
- package/dist/contexts/active-backend-context.js.map +1 -1
- package/dist/favicon-16x16.png +0 -0
- package/dist/favicon-32x32.png +0 -0
- package/dist/favicon.ico +0 -0
- package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
- package/dist/hooks/mutation/use-update-mcp-server.js +5 -5
- package/dist/hooks/query/query-keys.cjs.map +1 -1
- package/dist/hooks/query/query-keys.d.ts +4 -0
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-cloud-current-user-id.cjs +1 -1
- package/dist/hooks/query/use-cloud-current-user-id.cjs.map +1 -1
- package/dist/hooks/query/use-cloud-current-user-id.js +7 -5
- package/dist/hooks/query/use-cloud-current-user-id.js.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.js +5 -1
- package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
- package/dist/hooks/query/use-manifest-capabilities.d.ts +21 -0
- package/dist/hooks/query/use-manifest-prerequisites.d.ts +24 -0
- package/dist/hooks/use-can-manage-org-profiles.cjs +1 -1
- package/dist/hooks/use-can-manage-org-profiles.cjs.map +1 -1
- package/dist/hooks/use-can-manage-org-profiles.js +2 -1
- package/dist/hooks/use-can-manage-org-profiles.js.map +1 -1
- package/dist/hooks/use-llm-configured.cjs +1 -1
- package/dist/hooks/use-llm-configured.cjs.map +1 -1
- package/dist/hooks/use-llm-configured.js +2 -1
- package/dist/hooks/use-llm-configured.js.map +1 -1
- package/dist/hooks/use-manifest-preflight.d.ts +18 -0
- package/dist/hooks/use-tracking.cjs +1 -1
- package/dist/hooks/use-tracking.cjs.map +1 -1
- package/dist/hooks/use-tracking.d.ts +14 -0
- package/dist/hooks/use-tracking.js +28 -10
- package/dist/hooks/use-tracking.js.map +1 -1
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +38 -1
- 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 +645 -16
- package/dist/i18n/translation.js.map +1 -1
- package/dist/icons/external-link.cjs +2 -0
- package/dist/icons/external-link.cjs.map +1 -0
- package/dist/icons/external-link.js +22 -0
- package/dist/icons/external-link.js.map +1 -0
- package/dist/icons/server.cjs +2 -0
- package/dist/icons/server.cjs.map +1 -0
- package/dist/icons/server.js +17 -0
- package/dist/icons/server.js.map +1 -0
- package/dist/locales/ar/openhands.json +39 -2
- package/dist/locales/ca/openhands.json +39 -2
- package/dist/locales/de/openhands.json +39 -2
- package/dist/locales/en/openhands.json +40 -3
- package/dist/locales/es/openhands.json +39 -2
- package/dist/locales/fr/openhands.json +39 -2
- package/dist/locales/it/openhands.json +39 -2
- package/dist/locales/ja/openhands.json +39 -2
- package/dist/locales/ko-KR/openhands.json +39 -2
- package/dist/locales/no/openhands.json +39 -2
- package/dist/locales/pt/openhands.json +39 -2
- package/dist/locales/tr/openhands.json +39 -2
- package/dist/locales/uk/openhands.json +39 -2
- package/dist/locales/zh-CN/openhands.json +39 -2
- package/dist/locales/zh-TW/openhands.json +39 -2
- package/dist/manifests/automation-interface.cjs +2 -0
- package/dist/manifests/automation-interface.cjs.map +1 -0
- package/dist/manifests/automation-interface.d.ts +44 -0
- package/dist/manifests/automation-interface.js +81 -0
- package/dist/manifests/automation-interface.js.map +1 -0
- package/dist/manifests/automation-setup.cjs +2 -0
- package/dist/manifests/automation-setup.cjs.map +1 -0
- package/dist/manifests/automation-setup.d.ts +52 -0
- package/dist/manifests/automation-setup.js +8 -0
- package/dist/manifests/automation-setup.js.map +1 -0
- package/dist/manifests/interface-validation.cjs +2 -0
- package/dist/manifests/interface-validation.cjs.map +1 -0
- package/dist/manifests/interface-validation.d.ts +27 -0
- package/dist/manifests/interface-validation.js +182 -0
- package/dist/manifests/interface-validation.js.map +1 -0
- package/dist/manifests/manifest-actions.d.ts +15 -0
- package/dist/manifests/manifest-capabilities.d.ts +25 -0
- package/dist/manifests/manifest-error-map.d.ts +40 -0
- package/dist/manifests/manifest-local-validation.d.ts +56 -0
- package/dist/manifests/manifest-registry.cjs +2 -0
- package/dist/manifests/manifest-registry.cjs.map +1 -0
- package/dist/manifests/manifest-registry.d.ts +15 -0
- package/dist/manifests/manifest-registry.js +26 -0
- package/dist/manifests/manifest-registry.js.map +1 -0
- package/dist/manifests/manifest-sources.cjs +2 -0
- package/dist/manifests/manifest-sources.cjs.map +1 -0
- package/dist/manifests/manifest-sources.d.ts +15 -0
- package/dist/manifests/manifest-sources.js +8 -0
- package/dist/manifests/manifest-sources.js.map +1 -0
- package/dist/manifests/manifest-template.d.ts +18 -0
- package/dist/manifests/manifest-validation.cjs +2 -0
- package/dist/manifests/manifest-validation.cjs.map +1 -0
- package/dist/manifests/manifest-validation.d.ts +30 -0
- package/dist/manifests/manifest-validation.js +145 -0
- package/dist/manifests/manifest-validation.js.map +1 -0
- package/dist/manifests/types.cjs +2 -0
- package/dist/manifests/types.cjs.map +1 -0
- package/dist/manifests/types.d.ts +227 -0
- package/dist/manifests/types.js +6 -0
- package/dist/manifests/types.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +75 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +78 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs +17 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js +89 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs +10 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js +17 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js +15 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js +18 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js +14 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js +14 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +23 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/index.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/index.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/index.js +18 -0
- package/dist/node_modules/@openhands/extensions/automations/index.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.js +89 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +3 -3
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.cjs +17 -4
- package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.js +5 -5
- package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +9 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js +29 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.js +5 -5
- package/dist/routes/mcp.cjs +1 -1
- package/dist/routes/mcp.cjs.map +1 -1
- package/dist/routes/mcp.js +73 -82
- package/dist/routes/mcp.js.map +1 -1
- package/dist/services/telemetry.cjs +1 -1
- package/dist/services/telemetry.cjs.map +1 -1
- package/dist/services/telemetry.d.ts +8 -0
- package/dist/services/telemetry.js +163 -116
- package/dist/services/telemetry.js.map +1 -1
- package/dist/types/agent-server/core/events/conversation-state-event.d.ts +2 -19
- package/dist/types/agent-server/core/events/observation-event.d.ts +2 -18
- package/dist/types/automation.d.ts +7 -3
- package/dist/types/mcp-server.d.ts +5 -0
- package/dist/types/settings.d.ts +3 -0
- package/dist/utils/api-error-message.d.ts +6 -2
- package/dist/utils/automation-catalog.cjs +2 -0
- package/dist/utils/automation-catalog.cjs.map +1 -0
- package/dist/utils/automation-catalog.d.ts +28 -0
- package/dist/utils/automation-catalog.js +5 -0
- package/dist/utils/automation-catalog.js.map +1 -0
- package/dist/utils/automation-timeout.d.ts +3 -2
- package/dist/utils/mcp-config.cjs +1 -1
- package/dist/utils/mcp-config.cjs.map +1 -1
- package/dist/utils/mcp-config.d.ts +8 -0
- package/dist/utils/mcp-config.js +25 -20
- package/dist/utils/mcp-config.js.map +1 -1
- package/dist/utils/mcp-installed-servers.cjs +1 -1
- package/dist/utils/mcp-installed-servers.cjs.map +1 -1
- package/dist/utils/mcp-installed-servers.js +6 -3
- package/dist/utils/mcp-installed-servers.js.map +1 -1
- package/dist/utils/responder-deployment.d.ts +5 -1
- package/dist/utils/transcript-export/index.cjs +5 -5
- package/dist/utils/transcript-export/index.js +12 -12
- package/package.json +3 -3
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/check-translation-completeness.cjs +1 -0
- package/scripts/dev-safe.mjs +17 -12
- package/scripts/dev-static.mjs +17 -0
- package/scripts/dev-with-automation.mjs +12 -14
- package/scripts/ingress.mjs +22 -0
- package/scripts/proxy-utils.mjs +157 -2
- package/scripts/runtime-services-info.mjs +6 -6
- package/scripts/static-build.mjs +0 -7
- package/scripts/static-server.mjs +10 -0
- package/build/assets/active-backend-context-BlZPzZNU.js +0 -1
- package/build/assets/agent-context-settings-CTaN-Iw9.js +0 -1
- package/build/assets/agent-profiles-settings-CR4VTqv_.js +0 -1
- package/build/assets/agent-server-conversation-service.api-Btmi4q6d.js +0 -41
- package/build/assets/agent-settings-KQs-occT.js +0 -1
- package/build/assets/api-key-entry-screen-BhR24gkM.js +0 -1
- package/build/assets/app-settings-Bs4sY8WP.js +0 -1
- package/build/assets/automation-BGP_I1RR.js +0 -1
- package/build/assets/automation-detail-CwDnJbYR.js +0 -2
- package/build/assets/automation-export-Bu-r-EzL.js +0 -2
- package/build/assets/automations-list-CYw7_6FR.js +0 -1
- package/build/assets/backend-form-modal-Ce-KRHOJ.js +0 -1
- package/build/assets/browser-BUDJnBg4.js +0 -6
- package/build/assets/check-BMOG005H.js +0 -1
- package/build/assets/chevron-down-CV1zZP_K.js +0 -1
- package/build/assets/circle-check-lvN_jFN5.js +0 -1
- package/build/assets/client-source-1v-kWLNU.js +0 -1
- package/build/assets/cloud-funnel-analytics-CasMM7EO.js +0 -1
- package/build/assets/command-menu-N_BriUy8.js +0 -1
- package/build/assets/condenser-settings-Czi8cKxV.js +0 -1
- package/build/assets/conversation-C25pc2dT.js +0 -1
- package/build/assets/conversation-CObLYSJd.js +0 -90
- package/build/assets/conversation-panel-C25pc2dT.js +0 -1
- package/build/assets/conversation-state-store-DTq4hFoP.js +0 -1
- package/build/assets/extensions-hub-BKftOQ-X.js +0 -1
- package/build/assets/extensions-navigation-DF24q1H1.js +0 -1
- package/build/assets/files-tab-SAiFCnS5.js +0 -1
- package/build/assets/git-provider-icon-BREx-yUX.js +0 -1
- package/build/assets/home-EPNFgzUh.js +0 -1
- package/build/assets/home-sN90Xcxp.js +0 -1
- package/build/assets/index-home-EPNFgzUh.js +0 -1
- package/build/assets/install-server-modal-BI8yUfmr.js +0 -1
- package/build/assets/llm-not-configured-banner-DTWzISnk.js +0 -27
- package/build/assets/llm-settings-BXk5_Pac.js +0 -1
- package/build/assets/llm-settings-C1vpgWam.js +0 -1
- package/build/assets/loader-circle-6zlEYCJw.js +0 -1
- package/build/assets/manage-backends-modal-DhflyGTf.js +0 -1
- package/build/assets/manifest-8082e879.js +0 -1
- package/build/assets/mcp-CxLPda-W.js +0 -9
- package/build/assets/messages-DINDkPNK.js +0 -40
- package/build/assets/onboarding-modal-DdvE6rzw.js +0 -1
- package/build/assets/organization-service.api-CT2OQlLz.js +0 -1
- package/build/assets/plugins-management-service-DVkoM3eA.js +0 -1
- package/build/assets/plus-vIbGD459.js +0 -1
- package/build/assets/profiles-service.api-CBafmAPO.js +0 -1
- package/build/assets/providers-9UzRB9mT.js +0 -1
- package/build/assets/proxy-C79PCMjo.js +0 -1
- package/build/assets/recommended-automations-launcher-BF2mtAKw.js +0 -58
- package/build/assets/root-B5JXKp1P.css +0 -1
- package/build/assets/root-Sj7W28yE.js +0 -2
- package/build/assets/root-layout-DbhKVoc7.js +0 -3
- package/build/assets/schema-field-CV6bFnoL.js +0 -1
- package/build/assets/search-sKuYKllf.js +0 -1
- package/build/assets/secrets-service-BjK-bPN2.js +0 -1
- package/build/assets/segmented-toggle-DbbD3Tve.js +0 -1
- package/build/assets/settings-Bj5Oo45A.js +0 -1
- package/build/assets/settings-input-BjW_zyTN.js +0 -1
- package/build/assets/settings-service.api-DryhKdSr.js +0 -1
- package/build/assets/shared-conversation-CnMxy7p_.js +0 -1
- package/build/assets/telemetry-cmCL3o6Z.js +0 -2
- package/build/assets/use-activate-agent-profile-DH33MvVj.js +0 -1
- package/build/assets/use-agent-profiles-Dmd_4H8q.js +0 -1
- package/build/assets/use-cloud-current-user-id-B6DP3s47.js +0 -1
- package/build/assets/use-is-authed-BsS4XwSL.js +0 -1
- package/build/assets/use-llm-profiles-BMQoc612.js +0 -1
- package/build/assets/use-onboarding-completion-B-2BTS-y.js +0 -1
- package/build/assets/use-plugins-marketplace-PBc_XNz_.js +0 -1
- package/build/assets/use-save-agent-profile-2Mk9ZX37.js +0 -1
- package/build/assets/use-settings-DBI44RnH.js +0 -1
- package/build/assets/use-settings-nav-items-Cva28C-c.js +0 -16
- package/build/assets/use-skills-RQsCtdzN.js +0 -1
- package/build/assets/use-tracking-CN1nIMnY.js +0 -1
- package/build/assets/utils-qjs_KuS4.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js +0 -1
- package/build/assets/x-EjvKGawc.js +0 -1
- /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f1hl7voa-BrmgjeOw.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~emdr2jt4-BrmgjeOw.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode)\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":";;AAYA,IAAa,IAAuB,sBACvB,IAA6B;AAE1C,SAAS,EAAY,GAAsC;CACzD,OAAO,MAAU,WAAW,MAAU;AACxC;AAEA,SAAS,EAAgB,GAA0C;CACjE,OAAO,MAAU,KAAA,KAAa,MAAU,aAAa,MAAU;AACjE;AAEA,SAAS,EAAe,GAAkC;CACxD,IAAI,OAAO,KAAU,aAAY,GAAgB,OAAO;CACxD,IAAM,IAAI;CACV,OACE,OAAO,EAAE,MAAO,YAChB,EAAE,GAAG,SAAS,KACd,OAAO,EAAE,QAAS,YAClB,OAAO,EAAE,QAAS,YAClB,OAAO,EAAE,UAAW,YACpB,EAAY,EAAE,IAAI,KAClB,EAAgB,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"storage.js","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode) &&\n (v.connectionRevision === undefined ||\n (typeof v.connectionRevision === \"number\" &&\n Number.isSafeInteger(v.connectionRevision) &&\n v.connectionRevision >= 0))\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ export interface Backend {
|
|
|
7
7
|
apiKey: string;
|
|
8
8
|
kind: BackendKind;
|
|
9
9
|
authMode?: BackendAuthMode;
|
|
10
|
+
/** Changes whenever connection credentials change, invalidating keyed data. */
|
|
11
|
+
connectionRevision?: number;
|
|
10
12
|
}
|
|
11
13
|
export interface BackendSelection {
|
|
12
14
|
backendId: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../../_virtual/_rolldown/runtime.cjs");const e=require("../backend-registry/active-store.cjs"),t=require("
|
|
1
|
+
require("../../_virtual/_rolldown/runtime.cjs");const e=require("../backend-registry/active-store.cjs"),t=require("../client-source.cjs"),n=require("./proxy.cjs"),r=require("../conversation-metadata-store.cjs");function i(e){if(!e?.id)return e;let t=r.getStoredConversationMetadata(e.id);return t?{...e,selected_repository:e.selected_repository??t.selected_repository??null,selected_branch:e.selected_branch??t.selected_branch??null,git_provider:e.git_provider??t.git_provider??null,selected_workspace:e.selected_workspace??t.selected_workspace??null}:e}function a(){let t=e.getActiveBackend().backend;if(t.kind!==`cloud`)throw Error(`Cloud conversations call requires a cloud backend.`);return t}async function o(e=20,t){let r=a(),o=new URLSearchParams;o.set(`limit`,String(e)),t&&o.set(`page_id`,t),o.set(`sort_order`,`UPDATED_AT_DESC`);let s=await n.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/search?${o.toString()}`});return{items:(s?.items??[]).map(e=>i(e)),next_page_id:s?.next_page_id??null}}async function s(e){if(e.length===0)return[];let t=a(),r=new URLSearchParams;for(let t of e)r.append(`ids`,t);return(await n.callCloudProxy({backend:t,method:`GET`,path:`/api/v1/app-conversations?${r.toString()}`})??[]).map(i)}async function c(e){return await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/app-conversations`,body:e,headers:t.AGENT_CANVAS_CLIENT_HEADERS})}async function l(e){return n.callCloudProxy({backend:a(),method:`GET`,path:`/api/v1/app-conversations/${e}/download`,responseType:`blob`})}async function u(e){await n.callCloudProxy({backend:a(),method:`DELETE`,path:`/api/v1/app-conversations/${e}`})}async function d(e,t){return await n.callCloudProxy({backend:a(),method:`PATCH`,path:`/api/v1/app-conversations/${e}`,body:{public:t}})}async function f(e){await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/pause`})}async function p(e){await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/resume`})}async function m(e,t){let r=a(),i=new URLSearchParams;return i.append(`file_path`,t),await n.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/${e}/file?${i.toString()}`})??``}async function h(e){let t=a(),r=new URLSearchParams;return r.set(`ids`,e),(await n.callCloudProxy({backend:t,method:`GET`,path:`/api/v1/app-conversations/start-tasks?${r.toString()}`}))?.[0]??null}exports.batchGetCloudConversations=s,exports.createCloudAppConversation=c,exports.deleteCloudConversation=u,exports.downloadCloudConversation=l,exports.getCloudAppConversationStartTask=h,exports.pauseCloudSandbox=f,exports.readCloudConversationFile=m,exports.resumeCloudSandbox=p,exports.searchCloudConversations=o,exports.updateCloudConversationPublicFlag=d;
|
|
2
2
|
//# sourceMappingURL=conversation-service.api.cjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getActiveBackend as e } from "../backend-registry/active-store.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { AGENT_CANVAS_CLIENT_HEADERS as t } from "../client-source.js";
|
|
3
|
+
import { callCloudProxy as n } from "./proxy.js";
|
|
4
4
|
import { getStoredConversationMetadata as r } from "../conversation-metadata-store.js";
|
|
5
5
|
//#region src/api/cloud/conversation-service.api.ts
|
|
6
6
|
function i(e) {
|
|
@@ -19,10 +19,10 @@ function a() {
|
|
|
19
19
|
if (t.kind !== "cloud") throw Error("Cloud conversations call requires a cloud backend.");
|
|
20
20
|
return t;
|
|
21
21
|
}
|
|
22
|
-
async function o(e = 20,
|
|
22
|
+
async function o(e = 20, t) {
|
|
23
23
|
let r = a(), o = new URLSearchParams();
|
|
24
|
-
o.set("limit", String(e)),
|
|
25
|
-
let s = await
|
|
24
|
+
o.set("limit", String(e)), t && o.set("page_id", t), o.set("sort_order", "UPDATED_AT_DESC");
|
|
25
|
+
let s = await n({
|
|
26
26
|
backend: r,
|
|
27
27
|
method: "GET",
|
|
28
28
|
path: `/api/v1/app-conversations/search?${o.toString()}`
|
|
@@ -34,25 +34,25 @@ async function o(e = 20, n) {
|
|
|
34
34
|
}
|
|
35
35
|
async function s(e) {
|
|
36
36
|
if (e.length === 0) return [];
|
|
37
|
-
let
|
|
37
|
+
let t = a(), r = new URLSearchParams();
|
|
38
38
|
for (let t of e) r.append("ids", t);
|
|
39
|
-
return (await
|
|
40
|
-
backend:
|
|
39
|
+
return (await n({
|
|
40
|
+
backend: t,
|
|
41
41
|
method: "GET",
|
|
42
42
|
path: `/api/v1/app-conversations?${r.toString()}`
|
|
43
43
|
}) ?? []).map(i);
|
|
44
44
|
}
|
|
45
45
|
async function c(e) {
|
|
46
|
-
return await
|
|
46
|
+
return await n({
|
|
47
47
|
backend: a(),
|
|
48
48
|
method: "POST",
|
|
49
49
|
path: "/api/v1/app-conversations",
|
|
50
50
|
body: e,
|
|
51
|
-
headers:
|
|
51
|
+
headers: t
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
async function l(e) {
|
|
55
|
-
return
|
|
55
|
+
return n({
|
|
56
56
|
backend: a(),
|
|
57
57
|
method: "GET",
|
|
58
58
|
path: `/api/v1/app-conversations/${e}/download`,
|
|
@@ -60,46 +60,46 @@ async function l(e) {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
async function u(e) {
|
|
63
|
-
await
|
|
63
|
+
await n({
|
|
64
64
|
backend: a(),
|
|
65
65
|
method: "DELETE",
|
|
66
66
|
path: `/api/v1/app-conversations/${e}`
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
async function d(e,
|
|
70
|
-
return await
|
|
69
|
+
async function d(e, t) {
|
|
70
|
+
return await n({
|
|
71
71
|
backend: a(),
|
|
72
72
|
method: "PATCH",
|
|
73
73
|
path: `/api/v1/app-conversations/${e}`,
|
|
74
|
-
body: { public:
|
|
74
|
+
body: { public: t }
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
async function f(e) {
|
|
78
|
-
await
|
|
78
|
+
await n({
|
|
79
79
|
backend: a(),
|
|
80
80
|
method: "POST",
|
|
81
81
|
path: `/api/v1/sandboxes/${e}/pause`
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
async function p(e) {
|
|
85
|
-
await
|
|
85
|
+
await n({
|
|
86
86
|
backend: a(),
|
|
87
87
|
method: "POST",
|
|
88
88
|
path: `/api/v1/sandboxes/${e}/resume`
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
|
-
async function m(e,
|
|
91
|
+
async function m(e, t) {
|
|
92
92
|
let r = a(), i = new URLSearchParams();
|
|
93
|
-
return i.append("file_path",
|
|
93
|
+
return i.append("file_path", t), await n({
|
|
94
94
|
backend: r,
|
|
95
95
|
method: "GET",
|
|
96
96
|
path: `/api/v1/app-conversations/${e}/file?${i.toString()}`
|
|
97
97
|
}) ?? "";
|
|
98
98
|
}
|
|
99
99
|
async function h(e) {
|
|
100
|
-
let
|
|
101
|
-
return r.set("ids", e), (await
|
|
102
|
-
backend:
|
|
100
|
+
let t = a(), r = new URLSearchParams();
|
|
101
|
+
return r.set("ids", e), (await n({
|
|
102
|
+
backend: t,
|
|
103
103
|
method: "GET",
|
|
104
104
|
path: `/api/v1/app-conversations/start-tasks?${r.toString()}`
|
|
105
105
|
}))?.[0] ?? null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/mcp-client.cjs");require("../../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("../backend-registry/active-store.cjs"),n=require("../agent-server-client-options.cjs"),r=require("
|
|
1
|
+
require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/mcp-client.cjs");require("../../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("../backend-registry/active-store.cjs"),n=require("../agent-server-client-options.cjs"),r=require("./mcp-redacted-credentials.cjs"),i=require("../../utils/mcp-credential-validation.cjs"),a=require("../../utils/redact-mcp-secrets.cjs");var o=120;function s(e){return e.type===`stdio`?{transport:`stdio`,command:e.command,...e.args?.length&&{args:e.args},...e.env&&Object.keys(e.env).length>0&&{env:e.env}}:{transport:e.type===`sse`?`sse`:`http`,url:e.url,...e.headers&&Object.keys(e.headers).length>0&&{headers:e.headers},...e.auth?{auth:e.auth}:{}}}function c(e){return e.auth?.strategy===`oauth2`?o:e.timeout}async function l(e){let t=i.getCredentialValidationForServer(e),n=await r.substituteRedactedMcpCredentials(e),a=s(n),o=c(e);return{request:{server:a,...e.name?{name:e.name}:{},...o===void 0?{}:{timeout:o},...t?{tool_call:t.toolCall}:{}},substituted:n}}function u(e,t){return e.ok?e.tool_result?{...e,tool_result:{...e.tool_result,text:a.redactMcpSecrets(e.tool_result.text,...t)}}:e:{...e,error:a.redactMcpSecrets(e.error,...t)}}function d(e,t,n){let r=u(e,n);if(r.ok&&t&&r.tool_result&&r.tools.includes(t.toolCall.name)){let e=t.interpret(r.tool_result);if(e)return{ok:!1,error:e,error_kind:`credentials`}}return r}function f(){if(t.getActiveBackend().backend.kind===`local`){let{host:e,apiKey:t}=n.getAgentServerClientOptions();return{host:e,...t?{apiKey:t}:{}}}let e=t.getRegisteredBackends().find(e=>e.kind===`local`&&e.host);if(e)return{host:e.host.replace(/\/+$/,``),...e.apiKey?{apiKey:e.apiKey}:{}};throw Error(`OAuth authorization requires a reachable local backend.`)}function p(){let{host:t,apiKey:n}=f();return new e.MCPClient({host:t,...n?{apiKey:n}:{},timeout:125e3})}function m(e){return e.status===`succeeded`?{ok:!0,tools:e.tools??[],...e.tool_result!==void 0&&{tool_result:e.tool_result},...e.oauth_state!==void 0&&{oauth_state:e.oauth_state}}:{ok:!1,error:e.error||`OAuth authorization did not complete`,error_kind:e.error_kind||`unknown`}}var h=e=>new Promise(t=>{window.setTimeout(t,e)}),g=class r{static async testServer(r){if(t.getActiveBackend().backend.kind===`cloud`)return{ok:!0,tools:[]};let a=i.getCredentialValidationForServer(r),{host:o,apiKey:s}=n.getAgentServerClientOptions(),c=new e.MCPClient({host:o,...s?{apiKey:s}:{}});try{let{request:e,substituted:t}=await l(r);return d(await c.testServer(e),a,[t,r])}finally{c.close()}}static async startOAuth(e){let t=p();try{return await r.startOAuthWithClient(t,e)}finally{t.close()}}static async getOAuthStatus(e){let t=p();try{return await r.getOAuthStatusWithClient(t,e)}finally{t.close()}}static async submitOAuthCallback(e,t){let n=p();try{return await r.submitOAuthCallbackWithClient(n,e,t)}finally{n.close()}}static async authorizeOAuth(e){let t=i.getCredentialValidationForServer(e),n=n=>d(n,t,[e]),a=window.open(`about:blank`,`_blank`),s=p();try{let t=await r.startOAuthWithClient(s,e);if(!t.ok||!t.job_id||!t.authorization_url)return a?.close(),n({ok:!1,error:t.error||`Could not start OAuth authorization`,error_kind:t.error_kind||`unknown`});let i=await r.getOAuthStatusWithClient(s,t.job_id);for(let e=0;e<20;e+=1){if(i.status===`succeeded`||i.status===`failed`)return a?.close(),n(m(i));if(i.callback_ready)break;await h(250),i=await r.getOAuthStatusWithClient(s,t.job_id)}a&&(a.location.href=t.authorization_url);for(let e=0;e<o;e+=1)if(await h(1e3),i=await r.getOAuthStatusWithClient(s,t.job_id),i.status===`succeeded`||i.status===`failed`)return a?.close(),n(m(i));return{ok:!1,error:`OAuth authorization timed out`,error_kind:`timeout`}}finally{s.close()}}static async startOAuthWithClient(e,t){let{request:n}=await l(t);return e.startOAuth(n)}static async getOAuthStatusWithClient(e,t){return await e.getOAuthStatus(t)}static async submitOAuthCallbackWithClient(e,t,n){return await e.submitOAuthCallback(t,{callback_url:n})}};exports.default=g;
|
|
2
2
|
//# sourceMappingURL=mcp-service.api.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-service.api.cjs","names":[],"sources":["../../../src/api/mcp-service/mcp-service.api.ts"],"sourcesContent":["import { MCPClient } from \"@openhands/typescript-client/clients\";\nimport type { MCPTestRequest } from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport {\n getCredentialValidationForServer,\n type CredentialValidation,\n} from \"#/utils/mcp-credential-validation\";\nimport type { MCPAuthCredential } from \"#/types/mcp-auth\";\nimport type {\n ExtendedMCPTestResponse,\n MCPOAuthStartResponse,\n MCPOAuthStatusResponse,\n MCPServerConfig,\n} from \"#/types/mcp-server\";\nimport { redactMcpSecrets } from \"#/utils/redact-mcp-secrets\";\nimport { substituteRedactedMcpCredentials } from \"./mcp-redacted-credentials\";\n\nconst OAUTH_MCP_TEST_TIMEOUT_SECONDS = 120;\n\ntype MCPTestServer = {\n transport?: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n auth?: MCPAuthCredential;\n};\n\ninterface ExtendedMCPTestRequest {\n server: MCPTestServer;\n name?: string;\n timeout?: number;\n tool_call?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n}\n\nfunction toMcpServer(server: MCPServerConfig): MCPTestServer {\n if (server.type === \"stdio\") {\n return {\n transport: \"stdio\",\n command: server.command!,\n ...(server.args?.length && { args: server.args }),\n ...(server.env &&\n Object.keys(server.env).length > 0 && { env: server.env }),\n };\n }\n return {\n transport: server.type === \"sse\" ? \"sse\" : \"http\",\n url: server.url!,\n ...(server.headers &&\n Object.keys(server.headers).length > 0 && { headers: server.headers }),\n ...(server.auth ? { auth: server.auth } : {}),\n };\n}\n\nfunction getMcpTestTimeout(server: MCPServerConfig): number | undefined {\n if (server.auth?.strategy !== \"oauth2\") return server.timeout;\n return OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n}\n\nasync function buildMcpTestRequest(server: MCPServerConfig): Promise<{\n request: ExtendedMCPTestRequest;\n substituted: MCPServerConfig;\n}> {\n const validation = getCredentialValidationForServer(server);\n const substituted = await substituteRedactedMcpCredentials(server);\n const serverSpec = toMcpServer(substituted);\n const timeout = getMcpTestTimeout(server);\n return {\n request: {\n server: serverSpec,\n ...(server.name ? { name: server.name } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n ...(validation ? { tool_call: validation.toolCall } : {}),\n },\n substituted,\n };\n}\n\nfunction redactMcpTestResponse(\n result: ExtendedMCPTestResponse,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n if (!result.ok) {\n return {\n ...result,\n error: redactMcpSecrets(result.error, ...redactionSources),\n };\n }\n if (result.tool_result) {\n return {\n ...result,\n tool_result: {\n ...result.tool_result,\n text: redactMcpSecrets(result.tool_result.text, ...redactionSources),\n },\n };\n }\n return result;\n}\n\n/**\n * Display-boundary post-processing shared by the test and OAuth probes:\n * scrub secrets from error/tool-result text, then let the catalog entry's\n * credential validation turn a failed read-only tool call into a\n * `credentials` failure. The interpretation only runs when the probe tool\n * is actually advertised in `tools` — a server variant that doesn't expose\n * the tool (e.g. a hosted alternative to the stdio server the spec was\n * written for) must degrade to a connectivity-only success, not be\n * misreported as bad credentials.\n */\nfunction finalizeMcpTestResponse(\n result: ExtendedMCPTestResponse,\n validation: CredentialValidation | undefined,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n const redacted = redactMcpTestResponse(result, redactionSources);\n if (\n redacted.ok &&\n validation &&\n redacted.tool_result &&\n redacted.tools.includes(validation.toolCall.name)\n ) {\n const credentialError = validation.interpret(redacted.tool_result);\n if (credentialError) {\n return {\n ok: false,\n error: credentialError,\n error_kind: \"credentials\",\n };\n }\n }\n return redacted;\n}\n\nfunction getMcpProbeOptions(): { host: string; apiKey?: string } {\n const active = getActiveBackend().backend;\n if (active.kind === \"local\") {\n const { host, apiKey } = getAgentServerClientOptions();\n return { host, ...(apiKey ? { apiKey } : {}) };\n }\n\n const localBackend = getRegisteredBackends().find(\n (backend) => backend.kind === \"local\" && backend.host,\n );\n if (localBackend) {\n return {\n host: localBackend.host.replace(/\\/+$/, \"\"),\n ...(localBackend.apiKey ? { apiKey: localBackend.apiKey } : {}),\n };\n }\n throw new Error(\"OAuth authorization requires a reachable local backend.\");\n}\n\nfunction createMcpProbeClient(): MCPClient {\n const { host, apiKey } = getMcpProbeOptions();\n return new MCPClient({\n host,\n ...(apiKey ? { apiKey } : {}),\n timeout: OAUTH_MCP_TEST_TIMEOUT_SECONDS * 1000 + 5000,\n });\n}\n\nfunction oauthStatusToTestResponse(\n status: MCPOAuthStatusResponse,\n): ExtendedMCPTestResponse {\n if (status.status === \"succeeded\") {\n return {\n ok: true,\n tools: status.tools ?? [],\n ...(status.tool_result !== undefined && {\n tool_result: status.tool_result,\n }),\n ...(status.oauth_state !== undefined && {\n oauth_state: status.oauth_state,\n }),\n };\n }\n return {\n ok: false,\n error: status.error || \"OAuth authorization did not complete\",\n error_kind: status.error_kind || \"unknown\",\n };\n}\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, ms);\n });\n\nclass McpService {\n static async testServer(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n // The MCP connectivity-test endpoint lives on the local agent-server. It\n // spawns the configured stdio command / opens an SSE-or-SHTTP connection\n // from that process's environment. Cloud backends don't expose this\n // endpoint to the frontend — the MCP server would actually run inside the\n // cloud sandbox, which isn't reachable from the browser before the user\n // starts a conversation. Calling `getAgentServerClientOptions()` here for\n // a cloud-active session would throw `NoBackendAvailableError(\"No backend\n // is configured.\")` and block the install flow entirely. Short-circuit\n // with a synthetic success so saving proceeds; any real connection\n // failure surfaces inside the conversation runtime instead.\n if (getActiveBackend().backend.kind === \"cloud\") {\n return { ok: true, tools: [] };\n }\n const validation = getCredentialValidationForServer(server);\n const { host, apiKey } = getAgentServerClientOptions();\n const client = new MCPClient({ host, ...(apiKey ? { apiKey } : {}) });\n try {\n const { request, substituted } = await buildMcpTestRequest(server);\n const result = (await client.testServer(\n request as MCPTestRequest,\n )) as ExtendedMCPTestResponse;\n // Redact against both config forms: `server` may hold fresh plaintext\n // input, `substituted` the stored (encrypted) round-trip values.\n return finalizeMcpTestResponse(result, validation, [substituted, server]);\n } finally {\n client.close();\n }\n }\n\n static async startOAuth(\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.startOAuthWithClient(client, server);\n } finally {\n client.close();\n }\n }\n\n static async getOAuthStatus(jobId: string): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.getOAuthStatusWithClient(client, jobId);\n } finally {\n client.close();\n }\n }\n\n static async submitOAuthCallback(\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.submitOAuthCallbackWithClient(\n client,\n jobId,\n callbackUrl,\n );\n } finally {\n client.close();\n }\n }\n\n static async authorizeOAuth(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n const validation = getCredentialValidationForServer(server);\n const finalize = (result: ExtendedMCPTestResponse) =>\n finalizeMcpTestResponse(result, validation, [server]);\n const popup = window.open(\"about:blank\", \"_blank\");\n const client = createMcpProbeClient();\n try {\n const start = await McpService.startOAuthWithClient(client, server);\n if (!start.ok || !start.job_id || !start.authorization_url) {\n popup?.close();\n return finalize({\n ok: false,\n error: start.error || \"Could not start OAuth authorization\",\n error_kind: start.error_kind || \"unknown\",\n });\n }\n\n let status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n if (status.callback_ready) break;\n await sleep(250);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n }\n\n if (popup) {\n popup.location.href = start.authorization_url;\n }\n\n for (\n let attempt = 0;\n attempt < OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n attempt += 1\n ) {\n await sleep(1000);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n }\n\n return {\n ok: false,\n error: \"OAuth authorization timed out\",\n error_kind: \"timeout\",\n };\n } finally {\n client.close();\n }\n }\n\n private static async startOAuthWithClient(\n client: MCPClient,\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const { request } = await buildMcpTestRequest(server);\n return client.startOAuth(request as MCPTestRequest);\n }\n\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.getOAuthStatus(jobId);\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.submitOAuthCallback(jobId, { callback_url: callbackUrl });\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-service.api.cjs","names":[],"sources":["../../../src/api/mcp-service/mcp-service.api.ts"],"sourcesContent":["import { MCPClient } from \"@openhands/typescript-client/clients\";\nimport type { MCPTestRequest } from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport {\n getCredentialValidationForServer,\n type CredentialValidation,\n} from \"#/utils/mcp-credential-validation\";\nimport type { MCPAuthCredential } from \"#/types/mcp-auth\";\nimport type {\n ExtendedMCPTestResponse,\n MCPOAuthStartResponse,\n MCPOAuthStatusResponse,\n MCPServerConfig,\n} from \"#/types/mcp-server\";\nimport { redactMcpSecrets } from \"#/utils/redact-mcp-secrets\";\nimport { substituteRedactedMcpCredentials } from \"./mcp-redacted-credentials\";\n\nconst OAUTH_MCP_TEST_TIMEOUT_SECONDS = 120;\n\ntype MCPTestServer = {\n transport?: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n auth?: MCPAuthCredential;\n};\n\ninterface ExtendedMCPTestRequest {\n server: MCPTestServer;\n name?: string;\n timeout?: number;\n tool_call?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n}\n\nfunction toMcpServer(server: MCPServerConfig): MCPTestServer {\n if (server.type === \"stdio\") {\n return {\n transport: \"stdio\",\n command: server.command!,\n ...(server.args?.length && { args: server.args }),\n ...(server.env &&\n Object.keys(server.env).length > 0 && { env: server.env }),\n };\n }\n return {\n transport: server.type === \"sse\" ? \"sse\" : \"http\",\n url: server.url!,\n ...(server.headers &&\n Object.keys(server.headers).length > 0 && { headers: server.headers }),\n ...(server.auth ? { auth: server.auth } : {}),\n };\n}\n\nfunction getMcpTestTimeout(server: MCPServerConfig): number | undefined {\n if (server.auth?.strategy !== \"oauth2\") return server.timeout;\n return OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n}\n\nasync function buildMcpTestRequest(server: MCPServerConfig): Promise<{\n request: ExtendedMCPTestRequest;\n substituted: MCPServerConfig;\n}> {\n const validation = getCredentialValidationForServer(server);\n const substituted = await substituteRedactedMcpCredentials(server);\n const serverSpec = toMcpServer(substituted);\n const timeout = getMcpTestTimeout(server);\n return {\n request: {\n server: serverSpec,\n ...(server.name ? { name: server.name } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n ...(validation ? { tool_call: validation.toolCall } : {}),\n },\n substituted,\n };\n}\n\nfunction redactMcpTestResponse(\n result: ExtendedMCPTestResponse,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n if (!result.ok) {\n return {\n ...result,\n error: redactMcpSecrets(result.error, ...redactionSources),\n };\n }\n if (result.tool_result) {\n return {\n ...result,\n tool_result: {\n ...result.tool_result,\n text: redactMcpSecrets(result.tool_result.text, ...redactionSources),\n },\n };\n }\n return result;\n}\n\n/**\n * Display-boundary post-processing shared by the test and OAuth probes:\n * scrub secrets from error/tool-result text, then let the catalog entry's\n * credential validation turn a failed read-only tool call into a\n * `credentials` failure. The interpretation only runs when the probe tool\n * is actually advertised in `tools` — a server variant that doesn't expose\n * the tool (e.g. a hosted alternative to the stdio server the spec was\n * written for) must degrade to a connectivity-only success, not be\n * misreported as bad credentials.\n */\nfunction finalizeMcpTestResponse(\n result: ExtendedMCPTestResponse,\n validation: CredentialValidation | undefined,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n const redacted = redactMcpTestResponse(result, redactionSources);\n if (\n redacted.ok &&\n validation &&\n redacted.tool_result &&\n redacted.tools.includes(validation.toolCall.name)\n ) {\n const credentialError = validation.interpret(redacted.tool_result);\n if (credentialError) {\n return {\n ok: false,\n error: credentialError,\n error_kind: \"credentials\",\n };\n }\n }\n return redacted;\n}\n\nfunction getMcpProbeOptions(): { host: string; apiKey?: string } {\n const active = getActiveBackend().backend;\n if (active.kind === \"local\") {\n const { host, apiKey } = getAgentServerClientOptions();\n return { host, ...(apiKey ? { apiKey } : {}) };\n }\n\n const localBackend = getRegisteredBackends().find(\n (backend) => backend.kind === \"local\" && backend.host,\n );\n if (localBackend) {\n return {\n host: localBackend.host.replace(/\\/+$/, \"\"),\n ...(localBackend.apiKey ? { apiKey: localBackend.apiKey } : {}),\n };\n }\n throw new Error(\"OAuth authorization requires a reachable local backend.\");\n}\n\nfunction createMcpProbeClient(): MCPClient {\n const { host, apiKey } = getMcpProbeOptions();\n return new MCPClient({\n host,\n ...(apiKey ? { apiKey } : {}),\n timeout: OAUTH_MCP_TEST_TIMEOUT_SECONDS * 1000 + 5000,\n });\n}\n\nfunction oauthStatusToTestResponse(\n status: MCPOAuthStatusResponse,\n): ExtendedMCPTestResponse {\n if (status.status === \"succeeded\") {\n return {\n ok: true,\n tools: status.tools ?? [],\n ...(status.tool_result !== undefined && {\n tool_result: status.tool_result,\n }),\n ...(status.oauth_state !== undefined && {\n oauth_state: status.oauth_state,\n }),\n };\n }\n return {\n ok: false,\n error: status.error || \"OAuth authorization did not complete\",\n error_kind: status.error_kind || \"unknown\",\n };\n}\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, ms);\n });\n\nclass McpService {\n static async testServer(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n // The MCP connectivity-test endpoint lives on the local agent-server. It\n // spawns the configured stdio command / opens an SSE-or-SHTTP connection\n // from that process's environment. Cloud backends don't expose this\n // endpoint to the frontend — the MCP server would actually run inside the\n // cloud sandbox, which isn't reachable from the browser before the user\n // starts a conversation. Calling `getAgentServerClientOptions()` here for\n // a cloud-active session would throw `NoBackendAvailableError(\"No backend\n // is configured.\")` and block the install flow entirely. Short-circuit\n // with a synthetic success so saving proceeds; any real connection\n // failure surfaces inside the conversation runtime instead.\n if (getActiveBackend().backend.kind === \"cloud\") {\n return { ok: true, tools: [] };\n }\n const validation = getCredentialValidationForServer(server);\n const { host, apiKey } = getAgentServerClientOptions();\n const client = new MCPClient({ host, ...(apiKey ? { apiKey } : {}) });\n try {\n const { request, substituted } = await buildMcpTestRequest(server);\n const result = (await client.testServer(\n request as MCPTestRequest,\n )) as ExtendedMCPTestResponse;\n // Redact against both config forms: `server` may hold fresh plaintext\n // input, `substituted` the stored (encrypted) round-trip values.\n return finalizeMcpTestResponse(result, validation, [substituted, server]);\n } finally {\n client.close();\n }\n }\n\n static async startOAuth(\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.startOAuthWithClient(client, server);\n } finally {\n client.close();\n }\n }\n\n static async getOAuthStatus(jobId: string): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.getOAuthStatusWithClient(client, jobId);\n } finally {\n client.close();\n }\n }\n\n static async submitOAuthCallback(\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.submitOAuthCallbackWithClient(\n client,\n jobId,\n callbackUrl,\n );\n } finally {\n client.close();\n }\n }\n\n static async authorizeOAuth(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n const validation = getCredentialValidationForServer(server);\n const finalize = (result: ExtendedMCPTestResponse) =>\n finalizeMcpTestResponse(result, validation, [server]);\n const popup = window.open(\"about:blank\", \"_blank\");\n const client = createMcpProbeClient();\n try {\n const start = await McpService.startOAuthWithClient(client, server);\n if (!start.ok || !start.job_id || !start.authorization_url) {\n popup?.close();\n return finalize({\n ok: false,\n error: start.error || \"Could not start OAuth authorization\",\n error_kind: start.error_kind || \"unknown\",\n });\n }\n\n let status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n if (status.callback_ready) break;\n await sleep(250);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n }\n\n if (popup) {\n popup.location.href = start.authorization_url;\n }\n\n for (\n let attempt = 0;\n attempt < OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n attempt += 1\n ) {\n await sleep(1000);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n }\n\n return {\n ok: false,\n error: \"OAuth authorization timed out\",\n error_kind: \"timeout\",\n };\n } finally {\n client.close();\n }\n }\n\n private static async startOAuthWithClient(\n client: MCPClient,\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const { request } = await buildMcpTestRequest(server);\n return client.startOAuth(request as MCPTestRequest);\n }\n\n // typescript-client 1.36 types the OAuth probes with the generated\n // agent-server models, which describe the opaque `oauth_state` JSON blobs as\n // `unknown` rather than the recursive `MCPJsonValue` the local types use. The\n // wire shape is unchanged, so narrow back to the app's boundary type.\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.getOAuthStatus(jobId)) as MCPOAuthStatusResponse;\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.submitOAuthCallback(jobId, {\n callback_url: callbackUrl,\n })) as MCPOAuthStatusResponse;\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
|
|
@@ -2,9 +2,9 @@ import { MCPClient as e } from "../../node_modules/@openhands/typescript-client/
|
|
|
2
2
|
import "../../node_modules/@openhands/typescript-client/dist/clients.js";
|
|
3
3
|
import { getActiveBackend as t, getRegisteredBackends as n } from "../backend-registry/active-store.js";
|
|
4
4
|
import { getAgentServerClientOptions as r } from "../agent-server-client-options.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { substituteRedactedMcpCredentials as i } from "./mcp-redacted-credentials.js";
|
|
6
|
+
import { getCredentialValidationForServer as a } from "../../utils/mcp-credential-validation.js";
|
|
7
|
+
import { redactMcpSecrets as o } from "../../utils/redact-mcp-secrets.js";
|
|
8
8
|
//#region src/api/mcp-service/mcp-service.api.ts
|
|
9
9
|
var s = 120;
|
|
10
10
|
function c(e) {
|
|
@@ -24,12 +24,12 @@ function l(e) {
|
|
|
24
24
|
return e.auth?.strategy === "oauth2" ? s : e.timeout;
|
|
25
25
|
}
|
|
26
26
|
async function u(e) {
|
|
27
|
-
let t =
|
|
27
|
+
let t = a(e), n = await i(e), r = c(n), o = l(e);
|
|
28
28
|
return {
|
|
29
29
|
request: {
|
|
30
30
|
server: r,
|
|
31
31
|
...e.name ? { name: e.name } : {},
|
|
32
|
-
...
|
|
32
|
+
...o === void 0 ? {} : { timeout: o },
|
|
33
33
|
...t ? { tool_call: t.toolCall } : {}
|
|
34
34
|
},
|
|
35
35
|
substituted: n
|
|
@@ -40,11 +40,11 @@ function d(e, t) {
|
|
|
40
40
|
...e,
|
|
41
41
|
tool_result: {
|
|
42
42
|
...e.tool_result,
|
|
43
|
-
text:
|
|
43
|
+
text: o(e.tool_result.text, ...t)
|
|
44
44
|
}
|
|
45
45
|
} : e : {
|
|
46
46
|
...e,
|
|
47
|
-
error:
|
|
47
|
+
error: o(e.error, ...t)
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
function f(e, t, n) {
|
|
@@ -102,13 +102,13 @@ var g = (e) => new Promise((t) => {
|
|
|
102
102
|
ok: !0,
|
|
103
103
|
tools: []
|
|
104
104
|
};
|
|
105
|
-
let
|
|
105
|
+
let i = a(n), { host: o, apiKey: s } = r(), c = new e({
|
|
106
106
|
host: o,
|
|
107
107
|
...s ? { apiKey: s } : {}
|
|
108
108
|
});
|
|
109
109
|
try {
|
|
110
110
|
let { request: e, substituted: t } = await u(n);
|
|
111
|
-
return f(await c.testServer(e),
|
|
111
|
+
return f(await c.testServer(e), i, [t, n]);
|
|
112
112
|
} finally {
|
|
113
113
|
c.close();
|
|
114
114
|
}
|
|
@@ -138,22 +138,22 @@ var g = (e) => new Promise((t) => {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
static async authorizeOAuth(e) {
|
|
141
|
-
let t =
|
|
141
|
+
let t = a(e), r = (n) => f(n, t, [e]), i = window.open("about:blank", "_blank"), o = m();
|
|
142
142
|
try {
|
|
143
143
|
let t = await n.startOAuthWithClient(o, e);
|
|
144
|
-
if (!t.ok || !t.job_id || !t.authorization_url) return
|
|
144
|
+
if (!t.ok || !t.job_id || !t.authorization_url) return i?.close(), r({
|
|
145
145
|
ok: !1,
|
|
146
146
|
error: t.error || "Could not start OAuth authorization",
|
|
147
147
|
error_kind: t.error_kind || "unknown"
|
|
148
148
|
});
|
|
149
|
-
let
|
|
149
|
+
let a = await n.getOAuthStatusWithClient(o, t.job_id);
|
|
150
150
|
for (let e = 0; e < 20; e += 1) {
|
|
151
|
-
if (
|
|
152
|
-
if (
|
|
153
|
-
await g(250),
|
|
151
|
+
if (a.status === "succeeded" || a.status === "failed") return i?.close(), r(h(a));
|
|
152
|
+
if (a.callback_ready) break;
|
|
153
|
+
await g(250), a = await n.getOAuthStatusWithClient(o, t.job_id);
|
|
154
154
|
}
|
|
155
|
-
|
|
156
|
-
for (let e = 0; e < s; e += 1) if (await g(1e3),
|
|
155
|
+
i && (i.location.href = t.authorization_url);
|
|
156
|
+
for (let e = 0; e < s; e += 1) if (await g(1e3), a = await n.getOAuthStatusWithClient(o, t.job_id), a.status === "succeeded" || a.status === "failed") return i?.close(), r(h(a));
|
|
157
157
|
return {
|
|
158
158
|
ok: !1,
|
|
159
159
|
error: "OAuth authorization timed out",
|
|
@@ -168,10 +168,10 @@ var g = (e) => new Promise((t) => {
|
|
|
168
168
|
return e.startOAuth(n);
|
|
169
169
|
}
|
|
170
170
|
static async getOAuthStatusWithClient(e, t) {
|
|
171
|
-
return e.getOAuthStatus(t);
|
|
171
|
+
return await e.getOAuthStatus(t);
|
|
172
172
|
}
|
|
173
173
|
static async submitOAuthCallbackWithClient(e, t, n) {
|
|
174
|
-
return e.submitOAuthCallback(t, { callback_url: n });
|
|
174
|
+
return await e.submitOAuthCallback(t, { callback_url: n });
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
177
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-service.api.js","names":[],"sources":["../../../src/api/mcp-service/mcp-service.api.ts"],"sourcesContent":["import { MCPClient } from \"@openhands/typescript-client/clients\";\nimport type { MCPTestRequest } from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport {\n getCredentialValidationForServer,\n type CredentialValidation,\n} from \"#/utils/mcp-credential-validation\";\nimport type { MCPAuthCredential } from \"#/types/mcp-auth\";\nimport type {\n ExtendedMCPTestResponse,\n MCPOAuthStartResponse,\n MCPOAuthStatusResponse,\n MCPServerConfig,\n} from \"#/types/mcp-server\";\nimport { redactMcpSecrets } from \"#/utils/redact-mcp-secrets\";\nimport { substituteRedactedMcpCredentials } from \"./mcp-redacted-credentials\";\n\nconst OAUTH_MCP_TEST_TIMEOUT_SECONDS = 120;\n\ntype MCPTestServer = {\n transport?: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n auth?: MCPAuthCredential;\n};\n\ninterface ExtendedMCPTestRequest {\n server: MCPTestServer;\n name?: string;\n timeout?: number;\n tool_call?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n}\n\nfunction toMcpServer(server: MCPServerConfig): MCPTestServer {\n if (server.type === \"stdio\") {\n return {\n transport: \"stdio\",\n command: server.command!,\n ...(server.args?.length && { args: server.args }),\n ...(server.env &&\n Object.keys(server.env).length > 0 && { env: server.env }),\n };\n }\n return {\n transport: server.type === \"sse\" ? \"sse\" : \"http\",\n url: server.url!,\n ...(server.headers &&\n Object.keys(server.headers).length > 0 && { headers: server.headers }),\n ...(server.auth ? { auth: server.auth } : {}),\n };\n}\n\nfunction getMcpTestTimeout(server: MCPServerConfig): number | undefined {\n if (server.auth?.strategy !== \"oauth2\") return server.timeout;\n return OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n}\n\nasync function buildMcpTestRequest(server: MCPServerConfig): Promise<{\n request: ExtendedMCPTestRequest;\n substituted: MCPServerConfig;\n}> {\n const validation = getCredentialValidationForServer(server);\n const substituted = await substituteRedactedMcpCredentials(server);\n const serverSpec = toMcpServer(substituted);\n const timeout = getMcpTestTimeout(server);\n return {\n request: {\n server: serverSpec,\n ...(server.name ? { name: server.name } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n ...(validation ? { tool_call: validation.toolCall } : {}),\n },\n substituted,\n };\n}\n\nfunction redactMcpTestResponse(\n result: ExtendedMCPTestResponse,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n if (!result.ok) {\n return {\n ...result,\n error: redactMcpSecrets(result.error, ...redactionSources),\n };\n }\n if (result.tool_result) {\n return {\n ...result,\n tool_result: {\n ...result.tool_result,\n text: redactMcpSecrets(result.tool_result.text, ...redactionSources),\n },\n };\n }\n return result;\n}\n\n/**\n * Display-boundary post-processing shared by the test and OAuth probes:\n * scrub secrets from error/tool-result text, then let the catalog entry's\n * credential validation turn a failed read-only tool call into a\n * `credentials` failure. The interpretation only runs when the probe tool\n * is actually advertised in `tools` — a server variant that doesn't expose\n * the tool (e.g. a hosted alternative to the stdio server the spec was\n * written for) must degrade to a connectivity-only success, not be\n * misreported as bad credentials.\n */\nfunction finalizeMcpTestResponse(\n result: ExtendedMCPTestResponse,\n validation: CredentialValidation | undefined,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n const redacted = redactMcpTestResponse(result, redactionSources);\n if (\n redacted.ok &&\n validation &&\n redacted.tool_result &&\n redacted.tools.includes(validation.toolCall.name)\n ) {\n const credentialError = validation.interpret(redacted.tool_result);\n if (credentialError) {\n return {\n ok: false,\n error: credentialError,\n error_kind: \"credentials\",\n };\n }\n }\n return redacted;\n}\n\nfunction getMcpProbeOptions(): { host: string; apiKey?: string } {\n const active = getActiveBackend().backend;\n if (active.kind === \"local\") {\n const { host, apiKey } = getAgentServerClientOptions();\n return { host, ...(apiKey ? { apiKey } : {}) };\n }\n\n const localBackend = getRegisteredBackends().find(\n (backend) => backend.kind === \"local\" && backend.host,\n );\n if (localBackend) {\n return {\n host: localBackend.host.replace(/\\/+$/, \"\"),\n ...(localBackend.apiKey ? { apiKey: localBackend.apiKey } : {}),\n };\n }\n throw new Error(\"OAuth authorization requires a reachable local backend.\");\n}\n\nfunction createMcpProbeClient(): MCPClient {\n const { host, apiKey } = getMcpProbeOptions();\n return new MCPClient({\n host,\n ...(apiKey ? { apiKey } : {}),\n timeout: OAUTH_MCP_TEST_TIMEOUT_SECONDS * 1000 + 5000,\n });\n}\n\nfunction oauthStatusToTestResponse(\n status: MCPOAuthStatusResponse,\n): ExtendedMCPTestResponse {\n if (status.status === \"succeeded\") {\n return {\n ok: true,\n tools: status.tools ?? [],\n ...(status.tool_result !== undefined && {\n tool_result: status.tool_result,\n }),\n ...(status.oauth_state !== undefined && {\n oauth_state: status.oauth_state,\n }),\n };\n }\n return {\n ok: false,\n error: status.error || \"OAuth authorization did not complete\",\n error_kind: status.error_kind || \"unknown\",\n };\n}\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, ms);\n });\n\nclass McpService {\n static async testServer(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n // The MCP connectivity-test endpoint lives on the local agent-server. It\n // spawns the configured stdio command / opens an SSE-or-SHTTP connection\n // from that process's environment. Cloud backends don't expose this\n // endpoint to the frontend — the MCP server would actually run inside the\n // cloud sandbox, which isn't reachable from the browser before the user\n // starts a conversation. Calling `getAgentServerClientOptions()` here for\n // a cloud-active session would throw `NoBackendAvailableError(\"No backend\n // is configured.\")` and block the install flow entirely. Short-circuit\n // with a synthetic success so saving proceeds; any real connection\n // failure surfaces inside the conversation runtime instead.\n if (getActiveBackend().backend.kind === \"cloud\") {\n return { ok: true, tools: [] };\n }\n const validation = getCredentialValidationForServer(server);\n const { host, apiKey } = getAgentServerClientOptions();\n const client = new MCPClient({ host, ...(apiKey ? { apiKey } : {}) });\n try {\n const { request, substituted } = await buildMcpTestRequest(server);\n const result = (await client.testServer(\n request as MCPTestRequest,\n )) as ExtendedMCPTestResponse;\n // Redact against both config forms: `server` may hold fresh plaintext\n // input, `substituted` the stored (encrypted) round-trip values.\n return finalizeMcpTestResponse(result, validation, [substituted, server]);\n } finally {\n client.close();\n }\n }\n\n static async startOAuth(\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.startOAuthWithClient(client, server);\n } finally {\n client.close();\n }\n }\n\n static async getOAuthStatus(jobId: string): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.getOAuthStatusWithClient(client, jobId);\n } finally {\n client.close();\n }\n }\n\n static async submitOAuthCallback(\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.submitOAuthCallbackWithClient(\n client,\n jobId,\n callbackUrl,\n );\n } finally {\n client.close();\n }\n }\n\n static async authorizeOAuth(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n const validation = getCredentialValidationForServer(server);\n const finalize = (result: ExtendedMCPTestResponse) =>\n finalizeMcpTestResponse(result, validation, [server]);\n const popup = window.open(\"about:blank\", \"_blank\");\n const client = createMcpProbeClient();\n try {\n const start = await McpService.startOAuthWithClient(client, server);\n if (!start.ok || !start.job_id || !start.authorization_url) {\n popup?.close();\n return finalize({\n ok: false,\n error: start.error || \"Could not start OAuth authorization\",\n error_kind: start.error_kind || \"unknown\",\n });\n }\n\n let status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n if (status.callback_ready) break;\n await sleep(250);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n }\n\n if (popup) {\n popup.location.href = start.authorization_url;\n }\n\n for (\n let attempt = 0;\n attempt < OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n attempt += 1\n ) {\n await sleep(1000);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n }\n\n return {\n ok: false,\n error: \"OAuth authorization timed out\",\n error_kind: \"timeout\",\n };\n } finally {\n client.close();\n }\n }\n\n private static async startOAuthWithClient(\n client: MCPClient,\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const { request } = await buildMcpTestRequest(server);\n return client.startOAuth(request as MCPTestRequest);\n }\n\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.getOAuthStatus(jobId);\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.submitOAuthCallback(jobId, { callback_url: callbackUrl });\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-service.api.js","names":[],"sources":["../../../src/api/mcp-service/mcp-service.api.ts"],"sourcesContent":["import { MCPClient } from \"@openhands/typescript-client/clients\";\nimport type { MCPTestRequest } from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport {\n getCredentialValidationForServer,\n type CredentialValidation,\n} from \"#/utils/mcp-credential-validation\";\nimport type { MCPAuthCredential } from \"#/types/mcp-auth\";\nimport type {\n ExtendedMCPTestResponse,\n MCPOAuthStartResponse,\n MCPOAuthStatusResponse,\n MCPServerConfig,\n} from \"#/types/mcp-server\";\nimport { redactMcpSecrets } from \"#/utils/redact-mcp-secrets\";\nimport { substituteRedactedMcpCredentials } from \"./mcp-redacted-credentials\";\n\nconst OAUTH_MCP_TEST_TIMEOUT_SECONDS = 120;\n\ntype MCPTestServer = {\n transport?: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n auth?: MCPAuthCredential;\n};\n\ninterface ExtendedMCPTestRequest {\n server: MCPTestServer;\n name?: string;\n timeout?: number;\n tool_call?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n}\n\nfunction toMcpServer(server: MCPServerConfig): MCPTestServer {\n if (server.type === \"stdio\") {\n return {\n transport: \"stdio\",\n command: server.command!,\n ...(server.args?.length && { args: server.args }),\n ...(server.env &&\n Object.keys(server.env).length > 0 && { env: server.env }),\n };\n }\n return {\n transport: server.type === \"sse\" ? \"sse\" : \"http\",\n url: server.url!,\n ...(server.headers &&\n Object.keys(server.headers).length > 0 && { headers: server.headers }),\n ...(server.auth ? { auth: server.auth } : {}),\n };\n}\n\nfunction getMcpTestTimeout(server: MCPServerConfig): number | undefined {\n if (server.auth?.strategy !== \"oauth2\") return server.timeout;\n return OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n}\n\nasync function buildMcpTestRequest(server: MCPServerConfig): Promise<{\n request: ExtendedMCPTestRequest;\n substituted: MCPServerConfig;\n}> {\n const validation = getCredentialValidationForServer(server);\n const substituted = await substituteRedactedMcpCredentials(server);\n const serverSpec = toMcpServer(substituted);\n const timeout = getMcpTestTimeout(server);\n return {\n request: {\n server: serverSpec,\n ...(server.name ? { name: server.name } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n ...(validation ? { tool_call: validation.toolCall } : {}),\n },\n substituted,\n };\n}\n\nfunction redactMcpTestResponse(\n result: ExtendedMCPTestResponse,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n if (!result.ok) {\n return {\n ...result,\n error: redactMcpSecrets(result.error, ...redactionSources),\n };\n }\n if (result.tool_result) {\n return {\n ...result,\n tool_result: {\n ...result.tool_result,\n text: redactMcpSecrets(result.tool_result.text, ...redactionSources),\n },\n };\n }\n return result;\n}\n\n/**\n * Display-boundary post-processing shared by the test and OAuth probes:\n * scrub secrets from error/tool-result text, then let the catalog entry's\n * credential validation turn a failed read-only tool call into a\n * `credentials` failure. The interpretation only runs when the probe tool\n * is actually advertised in `tools` — a server variant that doesn't expose\n * the tool (e.g. a hosted alternative to the stdio server the spec was\n * written for) must degrade to a connectivity-only success, not be\n * misreported as bad credentials.\n */\nfunction finalizeMcpTestResponse(\n result: ExtendedMCPTestResponse,\n validation: CredentialValidation | undefined,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n const redacted = redactMcpTestResponse(result, redactionSources);\n if (\n redacted.ok &&\n validation &&\n redacted.tool_result &&\n redacted.tools.includes(validation.toolCall.name)\n ) {\n const credentialError = validation.interpret(redacted.tool_result);\n if (credentialError) {\n return {\n ok: false,\n error: credentialError,\n error_kind: \"credentials\",\n };\n }\n }\n return redacted;\n}\n\nfunction getMcpProbeOptions(): { host: string; apiKey?: string } {\n const active = getActiveBackend().backend;\n if (active.kind === \"local\") {\n const { host, apiKey } = getAgentServerClientOptions();\n return { host, ...(apiKey ? { apiKey } : {}) };\n }\n\n const localBackend = getRegisteredBackends().find(\n (backend) => backend.kind === \"local\" && backend.host,\n );\n if (localBackend) {\n return {\n host: localBackend.host.replace(/\\/+$/, \"\"),\n ...(localBackend.apiKey ? { apiKey: localBackend.apiKey } : {}),\n };\n }\n throw new Error(\"OAuth authorization requires a reachable local backend.\");\n}\n\nfunction createMcpProbeClient(): MCPClient {\n const { host, apiKey } = getMcpProbeOptions();\n return new MCPClient({\n host,\n ...(apiKey ? { apiKey } : {}),\n timeout: OAUTH_MCP_TEST_TIMEOUT_SECONDS * 1000 + 5000,\n });\n}\n\nfunction oauthStatusToTestResponse(\n status: MCPOAuthStatusResponse,\n): ExtendedMCPTestResponse {\n if (status.status === \"succeeded\") {\n return {\n ok: true,\n tools: status.tools ?? [],\n ...(status.tool_result !== undefined && {\n tool_result: status.tool_result,\n }),\n ...(status.oauth_state !== undefined && {\n oauth_state: status.oauth_state,\n }),\n };\n }\n return {\n ok: false,\n error: status.error || \"OAuth authorization did not complete\",\n error_kind: status.error_kind || \"unknown\",\n };\n}\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, ms);\n });\n\nclass McpService {\n static async testServer(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n // The MCP connectivity-test endpoint lives on the local agent-server. It\n // spawns the configured stdio command / opens an SSE-or-SHTTP connection\n // from that process's environment. Cloud backends don't expose this\n // endpoint to the frontend — the MCP server would actually run inside the\n // cloud sandbox, which isn't reachable from the browser before the user\n // starts a conversation. Calling `getAgentServerClientOptions()` here for\n // a cloud-active session would throw `NoBackendAvailableError(\"No backend\n // is configured.\")` and block the install flow entirely. Short-circuit\n // with a synthetic success so saving proceeds; any real connection\n // failure surfaces inside the conversation runtime instead.\n if (getActiveBackend().backend.kind === \"cloud\") {\n return { ok: true, tools: [] };\n }\n const validation = getCredentialValidationForServer(server);\n const { host, apiKey } = getAgentServerClientOptions();\n const client = new MCPClient({ host, ...(apiKey ? { apiKey } : {}) });\n try {\n const { request, substituted } = await buildMcpTestRequest(server);\n const result = (await client.testServer(\n request as MCPTestRequest,\n )) as ExtendedMCPTestResponse;\n // Redact against both config forms: `server` may hold fresh plaintext\n // input, `substituted` the stored (encrypted) round-trip values.\n return finalizeMcpTestResponse(result, validation, [substituted, server]);\n } finally {\n client.close();\n }\n }\n\n static async startOAuth(\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.startOAuthWithClient(client, server);\n } finally {\n client.close();\n }\n }\n\n static async getOAuthStatus(jobId: string): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.getOAuthStatusWithClient(client, jobId);\n } finally {\n client.close();\n }\n }\n\n static async submitOAuthCallback(\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.submitOAuthCallbackWithClient(\n client,\n jobId,\n callbackUrl,\n );\n } finally {\n client.close();\n }\n }\n\n static async authorizeOAuth(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n const validation = getCredentialValidationForServer(server);\n const finalize = (result: ExtendedMCPTestResponse) =>\n finalizeMcpTestResponse(result, validation, [server]);\n const popup = window.open(\"about:blank\", \"_blank\");\n const client = createMcpProbeClient();\n try {\n const start = await McpService.startOAuthWithClient(client, server);\n if (!start.ok || !start.job_id || !start.authorization_url) {\n popup?.close();\n return finalize({\n ok: false,\n error: start.error || \"Could not start OAuth authorization\",\n error_kind: start.error_kind || \"unknown\",\n });\n }\n\n let status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n if (status.callback_ready) break;\n await sleep(250);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n }\n\n if (popup) {\n popup.location.href = start.authorization_url;\n }\n\n for (\n let attempt = 0;\n attempt < OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n attempt += 1\n ) {\n await sleep(1000);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n }\n\n return {\n ok: false,\n error: \"OAuth authorization timed out\",\n error_kind: \"timeout\",\n };\n } finally {\n client.close();\n }\n }\n\n private static async startOAuthWithClient(\n client: MCPClient,\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const { request } = await buildMcpTestRequest(server);\n return client.startOAuth(request as MCPTestRequest);\n }\n\n // typescript-client 1.36 types the OAuth probes with the generated\n // agent-server models, which describe the opaque `oauth_state` JSON blobs as\n // `unknown` rather than the recursive `MCPJsonValue` the local types use. The\n // wire shape is unchanged, so narrow back to the app's boundary type.\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.getOAuthStatus(jobId)) as MCPOAuthStatusResponse;\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.submitOAuthCallback(jobId, {\n callback_url: callbackUrl,\n })) as MCPOAuthStatusResponse;\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs");require("../../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("../backend-registry/active-store.cjs"),n=require("../agent-server-client-options.cjs"),r=require("../../services/settings.cjs"),i=require("../../utils/mcp-config.cjs"),a=require("../cloud/settings-service.api.cjs");var o=[`language`,`user_consents_to_analytics`,`enable_sound_notifications`,`git_user_name`,`git_user_email`,`title_llm_profile`,`disabled_skills`],s=new Set(o),c=e=>s.has(e),l=e=>{let t={},n={};for(let[r,i]of Object.entries(e))c(r)?t[r]=i:n[r]=i;return{extracted:t,rest:n}},u=e=>JSON.parse(JSON.stringify(e)),d=(e,t)=>({...e??{},...t??{}});async function f(e,t=3,n=500){for(let r=0;r<t;r+=1)try{return await e()}catch(e){if(r>=t-1)throw e;let i=n*2**r;await new Promise(e=>{setTimeout(e,i)})}throw Error(`Retry attempts exhausted`)}var p={redacted:null,encrypted:null,timestamp:0},m=300*1e3,h=()=>Date.now()-p.timestamp<m,g=()=>{p={redacted:null,encrypted:null,timestamp:0}},_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),v=(e,t)=>`Basic ${btoa(`${e}:${t}`)}`,y=e=>{switch(e.strategy){case`none`:return{};case`api_key`:{if(typeof e.value!=`string`||!e.value)return null;let t=typeof e.header_name==`string`&&e.header_name?e.header_name:`Authorization`,n=t===`Authorization`?`Bearer ${e.value}`:e.value;return{[t]:n}}case`bearer`:return typeof e.value!=`string`||!e.value?null:{Authorization:`Bearer ${e.value}`};case`basic`:return typeof e.username!=`string`||typeof e.password!=`string`?null:{Authorization:v(e.username,e.password)};case`header`:return i.stringRecord(e.headers)??{};case`oauth2`:{let t=_(e.state)?e.state.tokens:void 0;return!_(t)||typeof t.access_token!=`string`?null:{Authorization:`Bearer ${t.access_token}`}}default:return null}},b=e=>{if(!_(e))return e;let t=_(e.mcpServers),n=t?e.mcpServers:e,r=Object.fromEntries(Object.entries(n).map(([e,t])=>{if(!_(t)||!_(t.auth))return[e,t];let n=y(t.auth);if(n===null)return[e,t];let r={...t},a={...i.stringRecord(t.headers)??{},...n};return delete r.auth,Object.keys(a).length>0?r.headers=a:delete r.headers,[e,r]}));return t?{...e,mcpServers:r}:r},x=e=>{let t=i.getSdkMcpServerMap(e);return t?Object.values(t).some(e=>i.hasRedactedMcpSecretLeaf(_(e)?e.auth:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.headers:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.env:void 0)):!1},
|
|
1
|
+
require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs");require("../../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("../backend-registry/active-store.cjs"),n=require("../agent-server-client-options.cjs"),r=require("../../services/settings.cjs"),i=require("../../utils/mcp-config.cjs"),a=require("../cloud/settings-service.api.cjs");var o=[`language`,`user_consents_to_analytics`,`enable_sound_notifications`,`git_user_name`,`git_user_email`,`title_llm_profile`,`disabled_skills`],s=new Set(o),c=e=>s.has(e),l=e=>{let t={},n={};for(let[r,i]of Object.entries(e))c(r)?t[r]=i:n[r]=i;return{extracted:t,rest:n}},u=e=>JSON.parse(JSON.stringify(e)),d=(e,t)=>({...e??{},...t??{}});async function f(e,t=3,n=500){for(let r=0;r<t;r+=1)try{return await e()}catch(e){if(r>=t-1)throw e;let i=n*2**r;await new Promise(e=>{setTimeout(e,i)})}throw Error(`Retry attempts exhausted`)}var p={redacted:null,encrypted:null,timestamp:0},m=300*1e3,h=()=>Date.now()-p.timestamp<m,g=()=>{p={redacted:null,encrypted:null,timestamp:0}},_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),v=(e,t)=>`Basic ${btoa(`${e}:${t}`)}`,y=e=>{switch(e.strategy){case`none`:return{};case`api_key`:{if(typeof e.value!=`string`||!e.value)return null;let t=typeof e.header_name==`string`&&e.header_name?e.header_name:`Authorization`,n=t===`Authorization`?`Bearer ${e.value}`:e.value;return{[t]:n}}case`bearer`:return typeof e.value!=`string`||!e.value?null:{Authorization:`Bearer ${e.value}`};case`basic`:return typeof e.username!=`string`||typeof e.password!=`string`?null:{Authorization:v(e.username,e.password)};case`header`:return i.stringRecord(e.headers)??{};case`oauth2`:{let t=_(e.state)?e.state.tokens:void 0;return!_(t)||typeof t.access_token!=`string`?null:{Authorization:`Bearer ${t.access_token}`}}default:return null}},b=e=>{if(!_(e))return e;let t=_(e.mcpServers),n=t?e.mcpServers:e,r=Object.fromEntries(Object.entries(n).map(([e,t])=>{if(!_(t)||!_(t.auth))return[e,t];let n=y(t.auth);if(n===null)return[e,t];let r={...t},a={...i.stringRecord(t.headers)??{},...n};return delete r.auth,Object.keys(a).length>0?r.headers=a:delete r.headers,[e,r]}));return t?{...e,mcpServers:r}:r},x=e=>{if(!_(e))return e;let t=_(e.mcpServers),n=t?e.mcpServers:e,r=Object.fromEntries(Object.entries(n).map(([e,t])=>_(t)?[e,{...t,enabled:t.enabled!==!1}]:[e,t]));return t?{...e,mcpServers:r}:r},S=e=>{let t=i.getSdkMcpServerMap(e);return t?Object.values(t).some(e=>i.hasRedactedMcpSecretLeaf(_(e)?e.auth:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.headers:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.env:void 0)):!1},C=(e,t)=>{let n=i.getSdkMcpServerMap(e),r=i.getSdkMcpServerMap(t);return!n||!r?!1:Object.keys(n).some(e=>!(e in r))},w=e=>{let t={agent_settings:e.agent_settings??{},conversation_settings:e.conversation_settings??{},llm_api_key_set:e.llm_api_key_is_set},n=e.misc_settings?.app_preferences;if(n)for(let e of o){let r=n[e];r!==void 0&&(t[e]=r)}return t},T=e=>{let t=d(r.DEFAULT_SETTINGS.agent_settings??{},e.agent_settings??{}),n=d(r.DEFAULT_SETTINGS.conversation_settings??{},e.conversation_settings??{}),i={...u(r.DEFAULT_SETTINGS),...e,provider_tokens_set:{...r.DEFAULT_SETTINGS.provider_tokens_set??{},...e.provider_tokens_set??{}},agent_settings:t,conversation_settings:n},a=t.llm,o=t.condenser;return typeof t.agent==`string`&&(i.agent=t.agent),typeof a?.model==`string`&&a.model.length>0&&(i.llm_model=a.model),typeof a?.base_url==`string`&&(i.llm_base_url=a.base_url),typeof o?.enabled==`boolean`&&(i.enable_default_condenser=o.enabled),typeof o?.max_size==`number`&&(i.condenser_max_size=o.max_size),typeof n.confirmation_mode==`boolean`&&(i.confirmation_mode=n.confirmation_mode),(typeof n.security_analyzer==`string`||n.security_analyzer===null)&&(i.security_analyzer=n.security_analyzer),typeof n.max_iterations==`number`&&(i.max_iterations=n.max_iterations),i.search_api_key_set=!!i.search_api_key,i},E=class r{static async fetchSettingsFromApi(t){return f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).getSettings({exposeSecrets:t}))}static async getSettings(){if(t.getActiveBackend().backend.kind===`cloud`)try{return T(await f(()=>a.fetchCloudSettings()))}catch(e){return console.warn(`Failed to fetch cloud settings, using defaults:`,e),T({})}if(h()&&p.redacted)return T(w(p.redacted));try{let e=await this.fetchSettingsFromApi();return p.redacted=e,p.timestamp=Date.now(),T(w(e))}catch(e){return console.warn(`Failed to fetch settings from API, using defaults:`,e),T({})}}static async getSettingsForConversation(){if(h()&&p.encrypted)return{agentSettings:p.encrypted.agent_settings,conversationSettings:p.encrypted.conversation_settings,secretsEncrypted:!0};let e=await this.fetchSettingsFromApi(`encrypted`);return p.encrypted=e,p.timestamp||=Date.now(),{agentSettings:e.agent_settings,conversationSettings:e.conversation_settings,secretsEncrypted:!0}}static async getSettingsSchema(){return t.getActiveBackend().backend.kind===`cloud`?await a.fetchCloudSettingsSchema():await new e.SettingsClient(n.getAgentServerClientOptions()).getAgentSchema()}static async getConversationSettingsSchema(){return t.getActiveBackend().backend.kind===`cloud`?await a.fetchCloudConversationSettingsSchema():await new e.SettingsClient(n.getAgentServerClientOptions()).getConversationSchema()}static async saveSettings(i){let{extracted:o,rest:s}=l(i),c=Object.keys(o).length>0,u={},d=s.agent_settings_diff;d&&Object.keys(d).length>0&&(u.agent_settings_diff=d);let p=s.conversation_settings_diff;p&&Object.keys(p).length>0&&(u.conversation_settings_diff=p),c&&(u.misc_settings_diff={app_preferences:o});let m=t.getActiveBackend().backend.kind===`cloud`,h=u.agent_settings_diff,_=!!h&&`mcp_config`in h&&h.mcp_config!==null,v;if(_)try{v=m?(await a.fetchCloudSettings())?.agent_settings?.mcp_config:(await r.fetchSettingsFromApi())?.agent_settings?.mcp_config}catch{}let y=m&&_&&S(v)&&!C(v,h?.mcp_config),w=_&&!y;if(m){if(!(u.agent_settings_diff||u.conversation_settings_diff||c))return!0;w&&await f(()=>a.saveCloudSettings({agent_settings_diff:{mcp_config:null}}));let e={};if(u.agent_settings_diff&&(e.agent_settings_diff={...u.agent_settings_diff},`mcp_config`in e.agent_settings_diff)){let t=b(e.agent_settings_diff.mcp_config);e.agent_settings_diff.mcp_config=y?x(t):t}u.conversation_settings_diff&&(e.conversation_settings_diff=u.conversation_settings_diff),c&&(e.app_preferences=o);try{await f(()=>a.saveCloudSettings(e))}catch(e){if(w&&v)try{await a.saveCloudSettings({agent_settings_diff:{mcp_config:v}})}catch{}throw e}}else{if(!(u.agent_settings_diff||u.conversation_settings_diff||u.misc_settings_diff))return!0;w&&await f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings({agent_settings_diff:{mcp_config:null}}));try{await f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings(u))}catch(t){if(w&&v)try{await new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings({agent_settings_diff:{mcp_config:v}})}catch{}throw t}}return g(),!0}static invalidateCache(){g()}};exports.default=E;
|
|
2
2
|
//# sourceMappingURL=settings-service.api.cjs.map
|