@openhands/agent-canvas 1.7.2 → 1.8.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-B7lYw4uD.js} +1 -1
- package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-WUD4tfSq.js} +1 -1
- package/build/assets/active-backend-context-mY7Gff5c.js +2 -0
- package/build/assets/{agent-context-settings-CTaN-Iw9.js → agent-context-settings-BTUmWEzL.js} +1 -1
- package/build/assets/{agent-profiles-settings-CR4VTqv_.js → agent-profiles-settings-Ilqid_R5.js} +1 -1
- package/build/assets/agent-server-conversation-service.api-C_7YnjzP.js +41 -0
- package/build/assets/{agent-settings-BIOsUglV.js → agent-settings-BGTyoT6X.js} +2 -2
- package/build/assets/agent-settings-CxfT4ksO.js +1 -0
- package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-eRyIwDyU.js} +1 -1
- package/build/assets/api-key-entry-screen-JOx3SH1-.js +1 -0
- package/build/assets/app-settings-D53QZy5p.js +1 -0
- package/build/assets/automation-detail-nEflClmc.js +2 -0
- package/build/assets/{automation-export-Bu-r-EzL.js → automation-export-BO_kfqC8.js} +1 -1
- package/build/assets/{automations-list-CYw7_6FR.js → automations-list-BYncC7gv.js} +1 -1
- package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-C02hGa8t.js} +1 -1
- package/build/assets/backend-form-modal-CKrBF80P.js +1 -0
- package/build/assets/{backend-synced-settings-badge-BNpEylNP.js → backend-synced-settings-badge-CQ9xtNWm.js} +1 -1
- package/build/assets/{badge-DwgrwohM.js → badge-CzXbf7tR.js} +1 -1
- package/build/assets/{base-modal-CSHhJTSr.js → base-modal-DkVyzFMt.js} +1 -1
- package/build/assets/{brand-button-CQO8oqVo.js → brand-button-BUlDL-mz.js} +1 -1
- package/build/assets/{browser-BUDJnBg4.js → browser-3QjrEr1D.js} +1 -1
- package/build/assets/{browser-tab-CEApjoEV.js → browser-tab-BijpUbdt.js} +1 -1
- package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-BKsVjhtA.js} +1 -1
- package/build/assets/check-CrxQfJZ2.js +1 -0
- package/build/assets/chevron-down-D_LsyTA7.js +1 -0
- package/build/assets/circle-check-DZn9HkLE.js +1 -0
- package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-DdjUiOo1.js} +1 -1
- package/build/assets/cloud-funnel-analytics-NlmDoeo2.js +1 -0
- package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Dl9UtvD6.js} +1 -1
- package/build/assets/{command-menu-N_BriUy8.js → command-menu-CvLPs7dg.js} +1 -1
- package/build/assets/{condenser-settings-Czi8cKxV.js → condenser-settings-C4Y9CzQV.js} +1 -1
- package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-CRBJSllP.js} +1 -1
- package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-FGaafXGh.js} +1 -1
- package/build/assets/conversation-D_ORtpKC.js +1 -0
- package/build/assets/conversation-Dpc5nmGi.js +90 -0
- package/build/assets/conversation-panel-D_ORtpKC.js +1 -0
- package/build/assets/conversation-state-store-CGRQemtx.js +1 -0
- package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-CDjvNgpG.js} +1 -1
- package/build/assets/{copy-B8Y5ufoR.js → copy-Drwu97Gx.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-NbN1clVr.js} +1 -1
- package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-CDm_WrVu.js} +1 -1
- package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-CqA2BTCL.js} +1 -1
- package/build/assets/{entry.client-DETaouwO.js → entry.client-BO2KQj0y.js} +2 -2
- package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-DSqPZnsD.js} +1 -1
- package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-mGl2pqqx.js} +1 -1
- package/build/assets/extensions-hub-Br3Lgynp.js +1 -0
- package/build/assets/extensions-navigation-BQmstKDZ.js +1 -0
- package/build/assets/{external-link-Cnnd6ikC.js → external-link-D9B2QMPf.js} +1 -1
- package/build/assets/files-tab-4c9HFSLo.js +1 -0
- package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-CtVAktAy.js} +1 -1
- package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-DICE64sz.js} +1 -1
- package/build/assets/git-provider-icon-0PqmIS_S.js +1 -0
- package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-KMsA9c4a.js} +1 -1
- package/build/assets/home-D9JsyEmE.js +1 -0
- package/build/assets/{home-sN90Xcxp.js → home-TFhnmZLx.js} +1 -1
- package/build/assets/index-home-D9JsyEmE.js +1 -0
- package/build/assets/install-server-modal-BgGRnqA0.js +1 -0
- package/build/assets/{launch-Ccnhte5b.js → launch-DjkKw55l.js} +1 -1
- package/build/assets/{list-todo-_BXQzOiB.js → list-todo-BpAf7aOT.js} +1 -1
- package/build/assets/{llm-not-configured-banner-DTWzISnk.js → llm-not-configured-banner-Y4W9-sar.js} +4 -4
- package/build/assets/llm-settings-D8zNkIlP.js +1 -0
- package/build/assets/llm-settings-nPwv7hKu.js +1 -0
- package/build/assets/{llm-subscription-service-W5BprsNA.js → llm-subscription-service-COTgZc1C.js} +1 -1
- package/build/assets/loader-circle-CGD6-Vak.js +1 -0
- package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DRFyh6Iy.js} +1 -1
- package/build/assets/manage-backends-modal-DiRWE3tJ.js +1 -0
- package/build/assets/manifest-1cf33a7b.js +1 -0
- package/build/assets/markdown-renderer-U40HF0Ak.js +8 -0
- package/build/assets/mcp-xDMaHzOw.js +9 -0
- package/build/assets/{messages-DINDkPNK.js → messages-CdNfZPgd.js} +2 -2
- package/build/assets/{modal-body-DQhiw-AR.js → modal-body-C3bGicn4.js} +1 -1
- package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-DFFO6BMU.js} +1 -1
- package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-vxkAIRyZ.js} +1 -1
- package/build/assets/{onboarding-BegDrOKn.js → onboarding-DWuFieEA.js} +1 -1
- package/build/assets/onboarding-modal-C8m72Dpb.js +1 -0
- package/build/assets/organization-service.api-CQ73CB-S.js +1 -0
- package/build/assets/{pencil-8_lvWDoZ.js → pencil-DzW2GB2M.js} +1 -1
- package/build/assets/{planner-tab-w6HT0N_A.js → planner-tab-YG0bGxDY.js} +1 -1
- package/build/assets/plugins-management-service-ijhH8OSh.js +1 -0
- package/build/assets/plus-CTGLo3aa.js +1 -0
- package/build/assets/profiles-service.api-C32pPm70.js +1 -0
- package/build/assets/providers-DuSn9s2i.js +1 -0
- package/build/assets/proxy-BiyDhMBd.js +1 -0
- package/build/assets/{puzzle-DXWdfaa7.js → puzzle-DlqT0yvr.js} +1 -1
- package/build/assets/{recommended-automations-launcher-BF2mtAKw.js → recommended-automations-launcher-Dru1yN46.js} +2 -2
- package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-Br5254f4.js} +1 -1
- package/build/assets/root-DOLLQteU.js +2 -0
- package/build/assets/root-layout-xmylWoew.js +3 -0
- package/build/assets/schema-field-htfNouTG.js +1 -0
- package/build/assets/{sdk-section-page-BW-i45yr.js → sdk-section-page-D0K1dBQY.js} +1 -1
- package/build/assets/search-BrpWXWUi.js +1 -0
- package/build/assets/secrets-service-Dbv5Zb8G.js +1 -0
- package/build/assets/{secrets-settings-D7U1ErCH.js → secrets-settings-Da4SSaX9.js} +1 -1
- package/build/assets/{segmented-toggle-DbbD3Tve.js → segmented-toggle-CZKOdIly.js} +1 -1
- package/build/assets/settings-F4a09IxY.js +1 -0
- package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-jOiv5Yrk.js} +1 -1
- package/build/assets/{settings-index-COAdxm2Q.js → settings-index-CyJBf5NA.js} +1 -1
- package/build/assets/{settings-input-BjW_zyTN.js → settings-input-BEaTCem1.js} +1 -1
- package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-VqMzkYYt.js} +1 -1
- package/build/assets/{settings-modal-CFnbQ8_4.js → settings-modal-C-S1NpbC.js} +1 -1
- package/build/assets/settings-service.api-CTJRrvMu.js +1 -0
- package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-B405oU_v.js} +1 -1
- package/build/assets/{shared-conversation-CnMxy7p_.js → shared-conversation-BvWtTwES.js} +1 -1
- package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-BGMuyC86.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-U78hQRJ1.js → sidebar-mobile-menu-toggle-xiKoUfGa.js} +1 -1
- package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-DA4_ct9G.js} +1 -1
- package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-FRJ3rADB.js} +1 -1
- package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-BMdhr_sd.js} +1 -1
- package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-CGUkgcVH.js} +1 -1
- package/build/assets/{skills-plugins-BPhaNpfx.js → skills-plugins-C5eJnyft.js} +1 -1
- package/build/assets/{skills-settings-CcwMtnnJ.js → skills-settings-pUxMr6WZ.js} +1 -1
- package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-B3kIdVyH.js} +1 -1
- package/build/assets/{task-list-tab-BmaTwjaS.js → task-list-tab-B3k4W1cK.js} +1 -1
- package/build/assets/{terminal-BRcoba5B.js → terminal-CBI_41Zc.js} +1 -1
- package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-DYRr9CAR.js} +1 -1
- package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-gZPlx23R.js} +1 -1
- package/build/assets/{typography-C6fuRTTT.js → typography-B1UxuuEC.js} +1 -1
- package/build/assets/{use-acp-credential-form-B0_pZ_uS.js → use-acp-credential-form-CjSvKWFH.js} +1 -1
- package/build/assets/use-activate-agent-profile-DCRf47e-.js +1 -0
- package/build/assets/use-agent-profiles-DmT9zxAN.js +1 -0
- package/build/assets/{use-can-manage-org-profiles-CrG1km7R.js → use-can-manage-org-profiles-vBiP7rHF.js} +1 -1
- package/build/assets/use-cloud-current-user-id-BMq9gw93.js +1 -0
- package/build/assets/use-config-C959QcRC.js +1 -0
- package/build/assets/{use-create-conversation-Dsa4nzU9.js → use-create-conversation-CakhLF0X.js} +1 -1
- package/build/assets/{use-create-secret-BnxuAjDt.js → use-create-secret-RT4QtSS9.js} +1 -1
- package/build/assets/use-llm-profiles-CdaxVpyY.js +1 -0
- package/build/assets/use-onboarding-completion-CJU4MNAY.js +1 -0
- package/build/assets/use-plugins-marketplace-D-93nqtJ.js +1 -0
- package/build/assets/{use-save-agent-profile-2Mk9ZX37.js → use-save-agent-profile-DGJ3-u0M.js} +1 -1
- package/build/assets/{use-save-settings-BRh9p_fv.js → use-save-settings--C6LZXfI.js} +1 -1
- package/build/assets/use-settings-DIAo5KFk.js +1 -0
- package/build/assets/use-settings-nav-items-DPK5sxvR.js +16 -0
- package/build/assets/use-skills-D_mLhYNa.js +1 -0
- package/build/assets/use-tracking-COqZLobY.js +1 -0
- package/build/assets/{use-user-conversation-GnGhs_Ob.js → use-user-conversation-DhcAEyJX.js} +1 -1
- package/build/assets/{useMutation-DyQXZFEF.js → useMutation-DHLpZ6J0.js} +1 -1
- package/build/assets/utils-DsWhWn2F.js +1 -0
- 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~g4xrpilz-CYPMCkX1.js} +1 -1
- package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-atebg0iG.js} +1 -1
- package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-G9DMrR7m.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-DEhW1h3I.js} +1 -1
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js → vendor~root-layout~index-home~home~conversation-panel~conversation-Acmf1sKj.js} +1 -1
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-CmzCY1BT.js} +1 -1
- package/build/assets/{vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js → vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-C7Yh77RT.js} +1 -1
- 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~bi2r7bko-VFnwct3q.js} +1 -1
- package/build/assets/{verification-settings-CaCzojbc.js → verification-settings-Vr5cN4md.js} +1 -1
- package/build/assets/x-Dx_JbpHA.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 +2 -0
- package/build/locales/ca/openhands.json +2 -0
- package/build/locales/de/openhands.json +2 -0
- package/build/locales/en/openhands.json +2 -0
- package/build/locales/es/openhands.json +2 -0
- package/build/locales/fr/openhands.json +2 -0
- package/build/locales/it/openhands.json +2 -0
- package/build/locales/ja/openhands.json +2 -0
- package/build/locales/ko-KR/openhands.json +2 -0
- package/build/locales/no/openhands.json +2 -0
- package/build/locales/pt/openhands.json +2 -0
- package/build/locales/tr/openhands.json +2 -0
- package/build/locales/uk/openhands.json +2 -0
- package/build/locales/zh-CN/openhands.json +2 -0
- package/build/locales/zh-TW/openhands.json +2 -0
- package/config/defaults.json +4 -4
- package/dist/api/agent-server-adapter.cjs +1 -1
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.js +7 -7
- package/dist/api/agent-server-adapter.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.js +95 -95
- 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/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/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/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/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-tracking.cjs +1 -1
- package/dist/hooks/use-tracking.js +9 -9
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +2 -0
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +1 -1
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +34 -0
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +2 -0
- package/dist/locales/ca/openhands.json +2 -0
- package/dist/locales/de/openhands.json +2 -0
- package/dist/locales/en/openhands.json +2 -0
- package/dist/locales/es/openhands.json +2 -0
- package/dist/locales/fr/openhands.json +2 -0
- package/dist/locales/it/openhands.json +2 -0
- package/dist/locales/ja/openhands.json +2 -0
- package/dist/locales/ko-KR/openhands.json +2 -0
- package/dist/locales/no/openhands.json +2 -0
- package/dist/locales/pt/openhands.json +2 -0
- package/dist/locales/tr/openhands.json +2 -0
- package/dist/locales/uk/openhands.json +2 -0
- package/dist/locales/zh-CN/openhands.json +2 -0
- package/dist/locales/zh-TW/openhands.json +2 -0
- 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/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +2 -2
- 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/mcp-server.d.ts +5 -0
- package/dist/types/settings.d.ts +3 -0
- 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/package.json +2 -2
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/dev-safe.mjs +2 -2
- package/build/assets/active-backend-context-BlZPzZNU.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-detail-CwDnJbYR.js +0 -2
- package/build/assets/backend-form-modal-Ce-KRHOJ.js +0 -1
- 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/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/index-home-EPNFgzUh.js +0 -1
- package/build/assets/install-server-modal-BI8yUfmr.js +0 -1
- 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/markdown-renderer-CvOO0YIr.js +0 -8
- package/build/assets/mcp-CxLPda-W.js +0 -9
- 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/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/settings-Bj5Oo45A.js +0 -1
- package/build/assets/settings-service.api-DryhKdSr.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-config-Csy8EAP9.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-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/x-EjvKGawc.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-config.cjs","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-config.cjs","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\n/**\n * Only an explicit ``false`` is carried. Every mutation round-trips the whole\n * server map through these converters, so preserving the flag here is what\n * stops adding or deleting one server from silently re-enabling another.\n */\nfunction disabledField(server: { enabled?: boolean }) {\n return server.enabled === false ? { enabled: false as const } : {};\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n ...disabledField(server),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n ...disabledField(server),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n // The SDK omits ``enabled`` while it holds its default (true), so only an\n // explicit ``false`` marks a server as switched off.\n const disabled = serverConfig.enabled === false;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n if (disabled) stdioServer.enabled = false;\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n *\n * ``enabled`` is only emitted when a server is switched off — the SDK defaults\n * it to true. Omitting it is what *clears* a previously persisted\n * ``enabled: false``, and that only works because ``saveSettings`` pre-clears\n * ``mcp_config`` to null before every write (see\n * ``settings-service.api.ts``), turning the backend's RFC 7386 merge into a\n * full replace. If that pre-clear is ever removed, re-enabling a server\n * becomes a silent no-op.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n Object.assign(server, disabledField(entry));\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
|
|
@@ -26,6 +26,14 @@ export declare function parseMcpConfig(value: unknown): MCPConfig;
|
|
|
26
26
|
* persisted ahead of it, and shift the suffix on every save as the count
|
|
27
27
|
* of other server types changes. With per-base collision suffixing,
|
|
28
28
|
* unrelated entries keep their human-meaningful names stable across edits.
|
|
29
|
+
*
|
|
30
|
+
* ``enabled`` is only emitted when a server is switched off — the SDK defaults
|
|
31
|
+
* it to true. Omitting it is what *clears* a previously persisted
|
|
32
|
+
* ``enabled: false``, and that only works because ``saveSettings`` pre-clears
|
|
33
|
+
* ``mcp_config`` to null before every write (see
|
|
34
|
+
* ``settings-service.api.ts``), turning the backend's RFC 7386 merge into a
|
|
35
|
+
* full replace. If that pre-clear is ever removed, re-enabling a server
|
|
36
|
+
* becomes a silent no-op.
|
|
29
37
|
*/
|
|
30
38
|
export declare function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null;
|
|
31
39
|
export {};
|
package/dist/utils/mcp-config.js
CHANGED
|
@@ -54,7 +54,7 @@ function l(e) {
|
|
|
54
54
|
} : void 0;
|
|
55
55
|
}
|
|
56
56
|
case "oauth2": {
|
|
57
|
-
let t =
|
|
57
|
+
let t = _(e.authentication), n = c(e.state);
|
|
58
58
|
return {
|
|
59
59
|
strategy: "oauth2",
|
|
60
60
|
...t && { authentication: t },
|
|
@@ -72,52 +72,57 @@ function d(e) {
|
|
|
72
72
|
return e.auth && !s(e.auth) && (t.auth = e.auth), e.headers && Object.keys(e.headers).length > 0 && (t.headers = e.headers), t;
|
|
73
73
|
}
|
|
74
74
|
function f(e) {
|
|
75
|
+
return e.enabled === !1 ? { enabled: !1 } : {};
|
|
76
|
+
}
|
|
77
|
+
function p(e) {
|
|
75
78
|
return {
|
|
76
79
|
...e.name && { name: e.name },
|
|
77
80
|
url: e.url,
|
|
78
81
|
...e.headers && { headers: e.headers },
|
|
79
|
-
...e.auth && { auth: e.auth }
|
|
82
|
+
...e.auth && { auth: e.auth },
|
|
83
|
+
...f(e)
|
|
80
84
|
};
|
|
81
85
|
}
|
|
82
|
-
function p(e) {
|
|
83
|
-
return f(e);
|
|
84
|
-
}
|
|
85
86
|
function m(e) {
|
|
87
|
+
return p(e);
|
|
88
|
+
}
|
|
89
|
+
function h(e) {
|
|
86
90
|
return {
|
|
87
|
-
...
|
|
91
|
+
...p(e),
|
|
88
92
|
...e.timeout !== void 0 && { timeout: e.timeout }
|
|
89
93
|
};
|
|
90
94
|
}
|
|
91
|
-
function
|
|
95
|
+
function g(e) {
|
|
92
96
|
return {
|
|
93
97
|
name: e.name,
|
|
94
98
|
command: e.command,
|
|
95
99
|
...e.args && { args: e.args },
|
|
96
|
-
...e.env && { env: e.env }
|
|
100
|
+
...e.env && { env: e.env },
|
|
101
|
+
...f(e)
|
|
97
102
|
};
|
|
98
103
|
}
|
|
99
|
-
function
|
|
104
|
+
function _(e) {
|
|
100
105
|
if (!e || typeof e != "object") return;
|
|
101
106
|
let t = e;
|
|
102
107
|
if (t.type !== "oauth") return;
|
|
103
108
|
let n = { type: "oauth" };
|
|
104
109
|
return (t.client_auth_method === "none" || t.client_auth_method === "client_secret_post" || t.client_auth_method === "client_secret_basic" || t.client_auth_method === "private_key_jwt") && (n.client_auth_method = t.client_auth_method), (typeof t.scopes == "string" || Array.isArray(t.scopes) && t.scopes.every((e) => typeof e == "string")) && (n.scopes = t.scopes), typeof t.client_name == "string" && (n.client_name = t.client_name), typeof t.client_metadata_url == "string" && (n.client_metadata_url = t.client_metadata_url), typeof t.client_id == "string" && (n.client_id = t.client_id), typeof t.client_secret == "string" && (n.client_secret = t.client_secret), t.additional_client_metadata && typeof t.additional_client_metadata == "object" && !Array.isArray(t.additional_client_metadata) && (n.additional_client_metadata = t.additional_client_metadata), n;
|
|
105
110
|
}
|
|
106
|
-
function
|
|
111
|
+
function v(e) {
|
|
107
112
|
let n = a(e);
|
|
108
113
|
if (!n) return { ...t };
|
|
109
114
|
let s = [], c = [], l = [];
|
|
110
115
|
for (let [e, t] of Object.entries(n)) {
|
|
111
116
|
if (!i(t)) continue;
|
|
112
|
-
let n = t.url;
|
|
117
|
+
let n = t.url, a = t.enabled === !1;
|
|
113
118
|
if (n) {
|
|
114
|
-
let i = t.transport,
|
|
119
|
+
let i = t.transport, c = u(t), d = o(t.headers);
|
|
115
120
|
if (i === "sse") {
|
|
116
121
|
let t = r(e, "sse"), i = { url: n };
|
|
117
|
-
t && (i.name = t),
|
|
122
|
+
t && (i.name = t), c && (i.auth = c), d && (i.headers = d), a && (i.enabled = !1), s.push(i);
|
|
118
123
|
} else {
|
|
119
124
|
let i = r(e, "shttp"), o = { url: n };
|
|
120
|
-
i && (o.name = i), t.timeout != null && (o.timeout = t.timeout),
|
|
125
|
+
i && (o.name = i), t.timeout != null && (o.timeout = t.timeout), c && (o.auth = c), d && (o.headers = d), a && (o.enabled = !1), l.push(o);
|
|
121
126
|
}
|
|
122
127
|
} else {
|
|
123
128
|
if (typeof t.command != "string") continue;
|
|
@@ -125,7 +130,7 @@ function _(e) {
|
|
|
125
130
|
name: e,
|
|
126
131
|
command: t.command
|
|
127
132
|
};
|
|
128
|
-
t.args && (n.args = t.args), t.env && (n.env = t.env), c.push(n);
|
|
133
|
+
t.args && (n.args = t.args), t.env && (n.env = t.env), a && (n.enabled = !1), c.push(n);
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
return {
|
|
@@ -134,7 +139,7 @@ function _(e) {
|
|
|
134
139
|
shttp_servers: l
|
|
135
140
|
};
|
|
136
141
|
}
|
|
137
|
-
function
|
|
142
|
+
function y(t) {
|
|
138
143
|
let n = {}, r = (t) => {
|
|
139
144
|
let r = e(t);
|
|
140
145
|
if (!(r in n)) return r;
|
|
@@ -144,19 +149,19 @@ function v(t) {
|
|
|
144
149
|
};
|
|
145
150
|
for (let e of t.sse_servers) {
|
|
146
151
|
let t = {}, i;
|
|
147
|
-
typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e))), t.transport = "sse", n[r(i || "sse")] = t;
|
|
152
|
+
typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e), f(e))), t.transport = "sse", n[r(i || "sse")] = t;
|
|
148
153
|
}
|
|
149
154
|
for (let e of t.shttp_servers) {
|
|
150
155
|
let t = { transport: "http" }, i;
|
|
151
|
-
typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e)), e.timeout != null && (t.timeout = e.timeout)), n[r(i || "shttp")] = t;
|
|
156
|
+
typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e), f(e)), e.timeout != null && (t.timeout = e.timeout)), n[r(i || "shttp")] = t;
|
|
152
157
|
}
|
|
153
158
|
for (let e of t.stdio_servers) {
|
|
154
159
|
let t = { command: e.command };
|
|
155
|
-
e.args && (t.args = e.args), e.env && (t.env = e.env), n[r(e.name || "stdio")] = t;
|
|
160
|
+
e.args && (t.args = e.args), e.env && (t.env = e.env), Object.assign(t, f(e)), n[r(e.name || "stdio")] = t;
|
|
156
161
|
}
|
|
157
162
|
return Object.keys(n).length > 0 ? n : null;
|
|
158
163
|
}
|
|
159
164
|
//#endregion
|
|
160
|
-
export { n as REDACTED_MCP_SECRET_VALUE, a as getSdkMcpServerMap, s as hasRedactedMcpSecretLeaf,
|
|
165
|
+
export { n as REDACTED_MCP_SECRET_VALUE, a as getSdkMcpServerMap, s as hasRedactedMcpSecretLeaf, v as parseMcpConfig, o as stringRecord, h as toMcpShttpServer, m as toMcpSseServer, g as toMcpStdioServer, y as toSdkMcpConfig };
|
|
161
166
|
|
|
162
167
|
//# sourceMappingURL=mcp-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-config.js","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-config.js","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\n/**\n * Only an explicit ``false`` is carried. Every mutation round-trips the whole\n * server map through these converters, so preserving the flag here is what\n * stops adding or deleting one server from silently re-enabling another.\n */\nfunction disabledField(server: { enabled?: boolean }) {\n return server.enabled === false ? { enabled: false as const } : {};\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n ...disabledField(server),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n ...disabledField(server),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n // The SDK omits ``enabled`` while it holds its default (true), so only an\n // explicit ``false`` marks a server as switched off.\n const disabled = serverConfig.enabled === false;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n if (disabled) stdioServer.enabled = false;\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n *\n * ``enabled`` is only emitted when a server is switched off — the SDK defaults\n * it to true. Omitting it is what *clears* a previously persisted\n * ``enabled: false``, and that only works because ``saveSettings`` pre-clears\n * ``mcp_config`` to null before every write (see\n * ``settings-service.api.ts``), turning the backend's RFC 7386 merge into a\n * full replace. If that pre-clear is ever removed, re-enabling a server\n * becomes a silent no-op.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n Object.assign(server, disabledField(entry));\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../_virtual/_rolldown/runtime.cjs");function e(e){return[...e.sse_servers.map((e,t)=>({id:`sse-${t}`,type:`sse`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,auth:typeof e==`object`?e.auth:void 0})),...e.stdio_servers.map((e,t)=>({id:`stdio-${t}`,type:`stdio`,name:e.name,command:e.command,args:e.args,env:e.env})),...e.shttp_servers.map((e,t)=>({id:`shttp-${t}`,type:`shttp`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,timeout:typeof e==`object`?e.timeout:void 0,auth:typeof e==`object`?e.auth:void 0}))]}exports.flattenMcpConfig=e;
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");function e(e){return[...e.sse_servers.map((e,t)=>({id:`sse-${t}`,type:`sse`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,auth:typeof e==`object`?e.auth:void 0,enabled:typeof e==`object`?e.enabled:void 0})),...e.stdio_servers.map((e,t)=>({id:`stdio-${t}`,type:`stdio`,name:e.name,command:e.command,args:e.args,env:e.env,enabled:e.enabled})),...e.shttp_servers.map((e,t)=>({id:`shttp-${t}`,type:`shttp`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,timeout:typeof e==`object`?e.timeout:void 0,auth:typeof e==`object`?e.auth:void 0,enabled:typeof e==`object`?e.enabled:void 0}))]}exports.flattenMcpConfig=e;
|
|
2
2
|
//# sourceMappingURL=mcp-installed-servers.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-installed-servers.cjs","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ];\n}\n"],"mappings":"6CAGA,SAAgB,EAAiB,EAAsC,CACrE,MAAO,CACL,GAAG,EAAO,YAAY,KAAK,EAAQ,KAAW,CAC5C,GAAI,OAAO,IACX,KAAM,MACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,
|
|
1
|
+
{"version":3,"file":"mcp-installed-servers.cjs","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n enabled: server.enabled,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ];\n}\n"],"mappings":"6CAGA,SAAgB,EAAiB,EAAsC,CACrE,MAAO,CACL,GAAG,EAAO,YAAY,KAAK,EAAQ,KAAW,CAC5C,GAAI,OAAO,IACX,KAAM,MACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,EACzD,EAAE,EACF,GAAG,EAAO,cAAc,KAAK,EAAQ,KAAW,CAC9C,GAAI,SAAS,IACb,KAAM,QACN,KAAM,EAAO,KACb,QAAS,EAAO,QAChB,KAAM,EAAO,KACb,IAAK,EAAO,IACZ,QAAS,EAAO,OAClB,EAAE,EACF,GAAG,EAAO,cAAc,KAAK,EAAQ,KAAW,CAC9C,GAAI,SAAS,IACb,KAAM,QACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,EACzD,EAAE,CACJ,CACF"}
|
|
@@ -7,7 +7,8 @@ function e(e) {
|
|
|
7
7
|
name: typeof e == "object" ? e.name : void 0,
|
|
8
8
|
url: typeof e == "string" ? e : e.url,
|
|
9
9
|
headers: typeof e == "object" ? e.headers : void 0,
|
|
10
|
-
auth: typeof e == "object" ? e.auth : void 0
|
|
10
|
+
auth: typeof e == "object" ? e.auth : void 0,
|
|
11
|
+
enabled: typeof e == "object" ? e.enabled : void 0
|
|
11
12
|
})),
|
|
12
13
|
...e.stdio_servers.map((e, t) => ({
|
|
13
14
|
id: `stdio-${t}`,
|
|
@@ -15,7 +16,8 @@ function e(e) {
|
|
|
15
16
|
name: e.name,
|
|
16
17
|
command: e.command,
|
|
17
18
|
args: e.args,
|
|
18
|
-
env: e.env
|
|
19
|
+
env: e.env,
|
|
20
|
+
enabled: e.enabled
|
|
19
21
|
})),
|
|
20
22
|
...e.shttp_servers.map((e, t) => ({
|
|
21
23
|
id: `shttp-${t}`,
|
|
@@ -24,7 +26,8 @@ function e(e) {
|
|
|
24
26
|
url: typeof e == "string" ? e : e.url,
|
|
25
27
|
headers: typeof e == "object" ? e.headers : void 0,
|
|
26
28
|
timeout: typeof e == "object" ? e.timeout : void 0,
|
|
27
|
-
auth: typeof e == "object" ? e.auth : void 0
|
|
29
|
+
auth: typeof e == "object" ? e.auth : void 0,
|
|
30
|
+
enabled: typeof e == "object" ? e.enabled : void 0
|
|
28
31
|
}))
|
|
29
32
|
];
|
|
30
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-installed-servers.js","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ];\n}\n"],"mappings":";AAGA,SAAgB,EAAiB,GAAsC;CACrE,OAAO;EACL,GAAG,EAAO,YAAY,KAAK,GAAQ,OAAW;GAC5C,IAAI,OAAO;GACX,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;
|
|
1
|
+
{"version":3,"file":"mcp-installed-servers.js","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n enabled: server.enabled,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ];\n}\n"],"mappings":";AAGA,SAAgB,EAAiB,GAAsC;CACrE,OAAO;EACL,GAAG,EAAO,YAAY,KAAK,GAAQ,OAAW;GAC5C,IAAI,OAAO;GACX,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;EACzD,EAAE;EACF,GAAG,EAAO,cAAc,KAAK,GAAQ,OAAW;GAC9C,IAAI,SAAS;GACb,MAAM;GACN,MAAM,EAAO;GACb,SAAS,EAAO;GAChB,MAAM,EAAO;GACb,KAAK,EAAO;GACZ,SAAS,EAAO;EAClB,EAAE;EACF,GAAG,EAAO,cAAc,KAAK,GAAQ,OAAW;GAC9C,IAAI,SAAS;GACb,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;EACzD,EAAE;CACJ;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openhands/agent-canvas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@microlink/react-json-view": "1.31.20",
|
|
25
25
|
"@monaco-editor/react": "4.7.0",
|
|
26
26
|
"@openhands/extensions": "0.11.0",
|
|
27
|
-
"@openhands/typescript-client": "1.
|
|
27
|
+
"@openhands/typescript-client": "1.36.1",
|
|
28
28
|
"@react-router/node": "7.17.0",
|
|
29
29
|
"@react-router/serve": "7.17.0",
|
|
30
30
|
"@tailwindcss/vite": "4.2.4",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* Usage:
|
|
21
21
|
* node scripts/check-sdk-version-sync.mjs
|
|
22
|
-
* EXPECTED_SDK_VERSION=1.
|
|
22
|
+
* EXPECTED_SDK_VERSION=1.39.1 node scripts/check-sdk-version-sync.mjs
|
|
23
23
|
* node scripts/check-sdk-version-sync.mjs --check-pypi
|
|
24
24
|
*
|
|
25
25
|
* Environment variables:
|
|
@@ -78,7 +78,7 @@ Triggering from other repos:
|
|
|
78
78
|
-H "Authorization: token \$GITHUB_TOKEN" \\
|
|
79
79
|
-H "Accept: application/vnd.github.v3+json" \\
|
|
80
80
|
https://api.github.com/repos/OpenHands/OpenHands/dispatches \\
|
|
81
|
-
-d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.
|
|
81
|
+
-d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.39.1"}}'
|
|
82
82
|
`);
|
|
83
83
|
process.exit(0);
|
|
84
84
|
}
|
|
@@ -260,9 +260,9 @@ async function fetchPyPIDependencies(packageName, version) {
|
|
|
260
260
|
* Parse PyPI requires_dist array and extract SDK package versions
|
|
261
261
|
*
|
|
262
262
|
* PyPI returns dependencies in PEP 508 format like:
|
|
263
|
-
* "openhands-sdk>=1.
|
|
264
|
-
* "openhands-tools==1.
|
|
265
|
-
* "openhands-workspace (>=1.
|
|
263
|
+
* "openhands-sdk>=1.39.1,<2.0.0"
|
|
264
|
+
* "openhands-tools==1.39.1"
|
|
265
|
+
* "openhands-workspace (>=1.39.1)"
|
|
266
266
|
*/
|
|
267
267
|
function parseSdkVersionsFromRequiresDist(requiresDist) {
|
|
268
268
|
const versions = {};
|
|
@@ -276,7 +276,7 @@ function parseSdkVersionsFromRequiresDist(requiresDist) {
|
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
// Extract the version number - look for patterns like:
|
|
279
|
-
// ">=1.
|
|
279
|
+
// ">=1.39.1", "==1.39.1", "(>=1.39.1)", "~=1.39.1"
|
|
280
280
|
// After the package name and before any comma or closing paren
|
|
281
281
|
const versionPattern = /[><=~!]+\s*([0-9]+(?:\.[0-9]+)*)/;
|
|
282
282
|
const match = dep.match(versionPattern);
|
package/scripts/dev-safe.mjs
CHANGED
|
@@ -48,7 +48,7 @@ const LOCAL_AGENT_SERVER_SUBDIRS = [
|
|
|
48
48
|
"openhands-workspace",
|
|
49
49
|
];
|
|
50
50
|
const DEFAULT_AGENT_SERVER_VERSION = SHARED_DEFAULTS.versions.agentServer;
|
|
51
|
-
// Temporary transitive-dep pin: openhands-sdk 1.
|
|
51
|
+
// Temporary transitive-dep pin: openhands-sdk 1.39.1 leaves agent-client-protocol
|
|
52
52
|
// unbounded (>=0.10.1), but acp 0.11.0 reordered the ACP prompt() args and breaks
|
|
53
53
|
// the SDK's ACP client. Hold acp <0.11 until a fixed SDK ships. See config/defaults.json.
|
|
54
54
|
const AGENT_CLIENT_PROTOCOL_CONSTRAINT =
|
|
@@ -399,7 +399,7 @@ export function validateFrontendDependencies(
|
|
|
399
399
|
* edits are picked up without a manual reinstall. The agent-server itself
|
|
400
400
|
* is rebuilt from local source on each invocation (--reinstall).
|
|
401
401
|
* - OH_AGENT_SERVER_GIT_REF: Git commit SHA or branch name
|
|
402
|
-
* - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.
|
|
402
|
+
* - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.39.1")
|
|
403
403
|
*
|
|
404
404
|
* If none are set, defaults to the released version specified by
|
|
405
405
|
* DEFAULT_AGENT_SERVER_VERSION. Set OH_AGENT_SERVER_GIT_REF to use a
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{St as t,yt as n}from"./vendor-styling-Bcgpimp9.js";import{r}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f9xdmd0z-DLMP7bZx.js";import{D as i,F as a,I as o,M as s,O as ee,P as te,T as ne,d as re,k as ie,w as c,y as ae}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js";import{R as oe,t as se,z as l}from"./utils-qjs_KuS4.js";var u=e(t(),1),ce=`__AGENT_CANVAS_BASE_PATH__`;function le(e){let t=e?.trim();return!t||t===`/`?``:(t.startsWith(`/`)?t:`/${t}`).replace(/\/+$/,``)}function ue(){let e=le(void 0);if(e)return e;if(typeof window<`u`){let e=window[ce];if(typeof e==`string`)return le(e)}return``}function de(e){let t=ue();return t?`${t}${e.startsWith(`/`)?e:`/${e}`}`:e.startsWith(`/`)?e:`/${e}`}var d=`openhands`,fe=[{label:`English`,value:`en`},{label:`日本語`,value:`ja`},{label:`简体中文`,value:`zh-CN`},{label:`繁體中文`,value:`zh-TW`},{label:`한국어`,value:`ko-KR`},{label:`Norsk`,value:`no`},{label:`Arabic`,value:`ar`},{label:`Deutsch`,value:`de`},{label:`Français`,value:`fr`},{label:`Italiano`,value:`it`},{label:`Português`,value:`pt`},{label:`Español`,value:`es`},{label:`Català`,value:`ca`},{label:`Türkçe`,value:`tr`},{label:`Українська`,value:`uk`}],f=new WeakMap,pe=e=>{if(!f.has(e)){let t=e.use(ee).use(i).use(r).init({fallbackLng:`en`,debug:!1,supportedLngs:fe.map(e=>e.value),nonExplicitSupportedLngs:!1,ns:[d],defaultNS:d,fallbackNS:d,backend:{loadPath:de(`/locales/{{lng}}/{{ns}}.json`)},interpolation:{escapeValue:!1}});f.set(e,t)}return e},me=()=>pe(s()),he=null,p=null,m=()=>(he||=me(),he),ge=()=>p??m(),_e=e=>(p=e??m(),p),ve=async(e=m())=>(await f.get(e),e),ye=e=>e?typeof e==`object`&&!Array.isArray(e)?{ns:d,...e}:e:{ns:d},h=new Proxy({},{get:(e,t)=>{let n=ge();if(t===`t`)return(e,t)=>n.t(e,ye(t));if(t===`exists`)return(e,t)=>n.exists(e,ye(t));let r=Reflect.get(n,t,n);return typeof r==`function`?r.bind(n):r},set:(e,t,n)=>{let r=ge();return Reflect.set(r,t,n,r)}}),be=e=>typeof e.response?.data==`object`&&e.response?.data!==null&&`error`in e.response.data&&typeof e.response?.data?.error==`string`,xe=e=>typeof e.response?.data==`object`&&e.response?.data!==null&&`message`in e.response.data&&typeof e.response?.data?.message==`string`,Se=`Disconnected (check URL or network). Check that the backend URL is correct and the backend server is reachable. If the backend is on another origin, check that it allows this frontend origin.`,Ce=`Disconnected (request timed out). Check that the backend URL is correct and reachable.`,we=4;function Te(e){return typeof e==`object`&&!!e}function Ee(e){let t=[],n=new Set,r=e,i=0;for(;r!=null&&i<we&&!n.has(r);){if(n.add(r),r instanceof Error)r.message&&t.push(r.message),r=r.cause;else if(typeof r==`string`){r&&t.push(r);break}else if(Te(r)){let e=r.message;typeof e==`string`&&e&&t.push(e),r=r.cause}else break;i+=1}return t}function g(e){if(!e)return!1;let t=e.toLowerCase();return t.includes(`disconnected (check cors or network)`)||t.includes(`disconnected (check url or network)`)||t.includes(`blocked by cors`)||t.includes(`failed to fetch`)||t.includes(`network error`)||t.includes(`load failed`)||t.includes(`networkerror when attempting to fetch resource`)||t.includes(`cors`)&&t.includes(`blocked`)}function De(e){return Ee(e).some(g)}function _(e){if(!e)return!1;let t=e.toLowerCase();return t.includes(`request timeout`)||t.includes(`timeout after`)||t.includes(`backend request timed out`)}function v(e){let t=Ee(e);return t.some(g)?Se:t.some(_)?Ce:t[0]??null}function Oe(e){return typeof e==`object`&&!!e&&`isAxiosError`in e&&e.isAxiosError===!0}var y=e=>{let t=null,n=!1;return Oe(e)?(n=!0,t=be(e)&&e.response?.data.error?e.response?.data.error:xe(e)&&e.response?.data.message?e.response?.data.message:e.message):t=e instanceof Error?e.message:typeof e==`string`?e:null,v(n?t??e:e)??t??``},b=(e,t=5e3,n=1e4)=>{if(!e)return t;let r=e.length/(1e3/60)*1e3*1.5;return Math.min(Math.max(r,t),n)},x=n(),ke={background:`var(--oh-color-tertiary)`,border:`1px solid var(--oh-border-input)`,color:`#fff`,borderRadius:`var(--oh-radius)`,maxWidth:`400px`,wordBreak:`break-word`,overflowWrap:`anywhere`,whiteSpace:`pre-wrap`},S={position:`top-right`,style:ke},Ae={...ke,color:`var(--oh-muted)`};function je({message:e}){let t=u.useRef(null),[n,r]=u.useState(!1);return u.useLayoutEffect(()=>{let e=t.current;if(!e)return;let n=()=>{let t=Number.parseFloat(getComputedStyle(e).lineHeight);if(!Number.isFinite(t)||t<=0){r(!1);return}r(e.getBoundingClientRect().height>t*1.5)};n();let i=new ResizeObserver(n);return i.observe(e),()=>i.disconnect()},[e]),(0,x.jsxs)(`div`,{className:se(`flex min-w-0 gap-2`,n?`items-start`:`items-center`),children:[(0,x.jsx)(ne,{"aria-hidden":!0,className:`h-4 w-4 shrink-0`,strokeWidth:2,style:{color:oe}}),(0,x.jsx)(`span`,{ref:t,className:`min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]`,children:e})]})}var Me={...S,icon:null,style:Ae},Ne=e=>{let t=e||h.t(l.STATUS$ERROR);g(t)?t=h.t(l.ERROR$CORS_OR_NETWORK):_(t)&&(t=h.t(l.ERROR$BACKEND_REQUEST_TIMEOUT));let n=b(t,4e3);c((0,x.jsx)(je,{message:t}),{...Me,duration:n})},Pe=e=>{let t=b(e,5e3);c.success((0,x.jsx)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:e}),{...S,duration:t})},Fe=(e,t,n)=>{let r=b(`${e} ${t}`,5e3);c.success((0,x.jsxs)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:[e,` `,(0,x.jsx)(`a`,{className:`underline hover:no-underline`,href:n,children:t})]}),{...S,duration:r})},Ie=e=>{let t=b(e,6e3);c((0,x.jsx)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:e}),{...S,icon:`⚠️`,duration:t})},Le=`openhands-backend-health`,Re=500;function ze(e){if(typeof e!=`object`||!e)return!1;let t=e;return Number.isInteger(t.consecutiveFailures)&&t.consecutiveFailures>=0&&t.consecutiveFailures<=5&&(t.lastError===null||typeof t.lastError==`string`)&&(t.lastFailureAt===null||typeof t.lastFailureAt==`number`)&&typeof t.disabled==`boolean`}function Be(){if(typeof window>`u`)return{};try{let e=window.localStorage.getItem(Le);if(!e)return{};let t=JSON.parse(e);if(typeof t!=`object`||!t)return{};let n={};for(let[e,r]of Object.entries(t))typeof e==`string`&&e.length>0&&ze(r)&&(n[e]=r);return n}catch{return{}}}function Ve(e){if(!(typeof window>`u`))try{if(Object.keys(e).length===0){window.localStorage.removeItem(Le);return}window.localStorage.setItem(Le,JSON.stringify(e))}catch{}}function He(e){let t=v(e)??`Unknown error`;return t.length>Re?`${t.slice(0,Re)}…`:t}var C=Be(),Ue=new Set;function We(){Ue.forEach(e=>e())}function w(e){C=e,Ve(e),We()}function Ge(){return C}function Ke(e){return C[e]??null}function qe(e){return Ue.add(e),()=>{Ue.delete(e)}}function Je(e,t){let n=C[e],r=Math.min((n?.consecutiveFailures??0)+1,5),i=n?.disabled===!0||r>=5,a={consecutiveFailures:r,lastError:He(t),lastFailureAt:Date.now(),disabled:i};w({...C,[e]:a})}function Ye(e){if(!(e in C))return;let{[e]:t,...n}=C;w(n)}function Xe(e){if(!(e in C))return;let{[e]:t,...n}=C;w(n)}function Ze(e){if(!(e in C))return;let{[e]:t,...n}=C;w(n)}var Qe=`workspace/project`,$e=`__AGENT_CANVAS_LOCK_TO_CLOUD__`,T=`all-hands.dev`,E=`openhands.dev`,et=`app.${T}`,tt=E,nt=`app.${E}`;function rt(e){return e?.trim()||null}function it(e){if(!e)return null;let t=e.trim().replace(/\/$/,``);return t?/^https?:\/\//i.test(t)?t:typeof window<`u`?`${window.location.protocol}//${t}`:`http://${t}`:null}function D(e){if(!e)return null;let t=e.trim().replace(/\/+$/,``);return t?/^https?:\/\//i.test(t)?t:`https://${t}`:null}function at(e){let t=e.toLowerCase();return t===et||t===nt?tt:t===T?E:t.endsWith(`.${T}`)?`${t.slice(0,-13)}${E}`:t}function ot(e){let t=D(e);if(!t)return null;try{let e=new URL(t),n=e.port?`:${e.port}`:``;return`${e.protocol}//${at(e.hostname)}${n}`}catch{return t.toLowerCase()}}function st(){let e=O();return!e||typeof window>`u`||!dt(window.location.origin,e)?null:window.location.origin}function ct(){return it(void 0)}function lt(){let e=rt(void 0);if(e)return e;if(typeof window<`u`){let e=window.__AGENT_CANVAS_SESSION_API_KEY__;if(typeof e==`string`)return rt(e)}return null}function ut(){return{baseUrl:k()??``,sessionApiKey:A()??``}}function O(){let e=D(void 0);if(e)return e;if(typeof window<`u`){let e=window[$e];if(typeof e==`string`)return D(e)}return null}function dt(e,t){let n=ot(e),r=ot(t);return!n||!r?!1:n===r}function ft(){return st()?`cookie`:`api-key`}function k(){return ct()||(typeof window<`u`?window.location.origin:null)}function A(){return lt()}function j(){return Qe}function pt(e){return`${j().replace(/\/+$/,``)}/${e.replace(/-/g,``)}`}function mt(){let e=A();return e?{"X-Session-API-Key":e}:{}}function M(){return typeof window<`u`&&window.__AGENT_CANVAS_AUTH_REQUIRED__===!0}function ht(){return M()?!A():!1}var gt=`default-local`,_t=`Local`,vt=`locked-cloud`,yt=`OpenHands Cloud`;function bt(){if(!O())return null;let e=st();return e?{id:vt,name:yt,host:e,apiKey:``,kind:`cloud`,authMode:`cookie`}:null}function N(){if(O())return null;let e=k(),t=A();return!e||!t?null:{id:gt,name:_t,host:e,apiKey:t,kind:`local`}}var xt=`openhands-backends`,P=`openhands-active-backend`;function St(e){return e===`local`||e===`cloud`}function Ct(e){return e===void 0||e===`api-key`||e===`cookie`}function wt(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.id==`string`&&t.id.length>0&&typeof t.name==`string`&&typeof t.host==`string`&&typeof t.apiKey==`string`&&St(t.kind)&&Ct(t.authMode)}function Tt(e){try{let{hostname:t}=new URL(e);return t===`localhost`||t===`127.0.0.1`||t===`::1`||t===`[::1]`}catch{return!1}}function Et(e,t){return e.id!==`default-local`||e.kind!==`local`?!1:e.host===t.host||Tt(e.host)&&Tt(t.host)}function Dt(e){let t=N();if(!t)return e;let n=!1,r=e.map(e=>!Et(e,t)||e.apiKey===t.apiKey?e:(n=!0,{...e,apiKey:t.apiKey}));return n?(F(r),r):e}function F(e){if(!(typeof window>`u`))try{window.localStorage.setItem(xt,JSON.stringify(e))}catch{}}function Ot(){if(typeof window>`u`)return[];try{let e=bt();if(e)return F([e]),Nt()?.backendId!==e.id&&I({backendId:e.id}),[e];let t=window.localStorage.getItem(xt);if(t===null){let e=N();return e?(F([e]),[e]):[]}let n=JSON.parse(t);if(!Array.isArray(n))return[];let r=n.filter(wt);if(r.length===0){let e=N();return e?(F([e]),[e]):[]}return Dt(r)}catch{return[]}}function kt(e){if(!e)return null;try{let t=JSON.parse(e);if(typeof t!=`object`||!t||typeof t.backendId!=`string`)return null;let n=t.orgId;return{backendId:t.backendId,orgId:typeof n==`string`&&n.length>0?n:null}}catch{return null}}function At(e,t){try{return e?.getItem(t)??null}catch{return null}}function jt(e,t,n){try{e?.setItem(t,n)}catch{}}function Mt(e,t){try{e?.removeItem(t)}catch{}}function Nt(){return typeof window>`u`?null:kt(At(window.sessionStorage,P))||kt(At(window.localStorage,P))}function I(e){if(typeof window>`u`)return;if(!e){Mt(window.sessionStorage,P),Mt(window.localStorage,P);return}let t=JSON.stringify({backendId:e.backendId,orgId:e.orgId??null});jt(window.sessionStorage,P,t),jt(window.localStorage,P,t)}var Pt=`no-backend`,Ft={id:Pt,name:`No Backend Available`,host:``,apiKey:``,kind:`local`};function L(e){return e.id===Pt}function It(e){return e.find(e=>e.kind===`local`&&Ke(e.id)?.disabled!==!0)||(e.find(e=>e.kind===`local`)??e[0]??Ft)}function R(e,t){let n=null,r=null;if(t){let i=e.find(e=>e.id===t.backendId);i&&(n=i,r=t.orgId??null)}return n||(n=It(e),r=null),{backends:e,selection:t,active:{backend:n,orgId:r}}}var z=R(Ot(),Nt()),B=new Set;function Lt(){B.forEach(e=>e())}function V(){return z.active}function H(){let e=z.active.backend;return e.kind===`local`&&!L(e)?e:null}function U(){return z.backends}function W(){return z.selection}function Rt(){return z}function zt(e){I(e),z=R(z.backends,e),Lt()}function G(e){F(e);let t=z.selection;t&&!e.some(e=>e.id===t.backendId)&&(t=null,I(null)),z=R(e,t),Lt()}function Bt(e){return B.add(e),()=>{B.delete(e)}}var Vt=(e,t)=>{(e?.response?.status===401||e?.status===401)&&t.invalidateQueries({queryKey:[`user`,`authenticated`]})},Ht=e=>{if(!(e instanceof ie)||e.response?.status!==401&&e.status!==401)return!1;let t=V().backend;if(t.kind!==`cloud`)return!1;let n=e.config?.url;return!n||n.startsWith(t.host.replace(/\/+$/,``))},K=new Set,Ut=()=>{let e=new te({queryCache:new a({onSuccess:(e,t)=>{let n=t.meta?.backendId??t.options.meta?.backendId;typeof n==`string`&&Ye(n)},onError:(t,n)=>{if(n.queryKey[0]===`user`&&n.queryKey[1]===`authenticated`||Vt(t,e),!(n.meta?.disableToast??n.options.meta?.disableToast)&&!Ht(t)){let e=y(t);K.has(e||``)||(Ne(e||h.t(l.ERROR$GENERIC)),K.add(e||``),setTimeout(()=>{K.delete(e||``)},3e3))}}}),mutationCache:new o({onError:(t,n,r,i)=>{Vt(t,e),!(i?.meta?.disableToast??i?.options.meta?.disableToast)&&!Ht(t)&&Ne(y(t)||h.t(l.ERROR$GENERIC))}})});return e},Wt=null,Gt=null,Kt=()=>(Wt||=Ut(),Wt),qt=()=>Gt??Kt(),Jt=e=>(Gt=e??Kt(),Gt),Yt=new Proxy({},{get:(e,t)=>{let n=qt(),r=Reflect.get(n,t,n);return typeof r==`function`?r.bind(n):r},set:(e,t,n)=>{let r=qt();return Reflect.set(r,t,n,r)}});function Xt(e){if(e&&!e.startsWith(`/`))try{let t=new URL(e),n=t.hostname,r=window.location.hostname??window.location.host?.split(`:`)[0];return r&&(n===`localhost`||n===`127.0.0.1`)&&r!==`localhost`&&r!==`127.0.0.1`?`${r}:${t.port}`:t.host}catch{return window.location.host}return window.location.host}function Zt(e){if(e&&!e.startsWith(`/`))try{return(new URL(e).pathname.split(`/api/conversations`)[0]||``).replace(/\/$/,``)}catch{return``}return``}function Qt(e){let t=Xt(e),n=Zt(e),r=window.location.protocol===`https:`,i=$t(e)===`https:`;return`${r||i?`https:`:`http:`}//${t}${n}`}function $t(e){if(!e||e.startsWith(`/`))return null;try{return new URL(e).protocol}catch{return null}}function en(e){let t=Xt(e),n=Zt(e),r=window.location.protocol===`https:`,i=$t(e)===`https:`;return`${r||i?`wss:`:`ws:`}//${t}${n}/sockets/bash-events`}function tn(e,t){if(!e)return null;let n=Xt(t),r=Zt(t),i=window.location.protocol===`https:`,a=$t(t)===`https:`;return`${i||a?`wss:`:`ws:`}//${n}${r}/sockets/events/${e}`}var nn=class extends Error{constructor(){super(`No backend is configured.`),this.name=`NoBackendAvailableError`}};function rn(e){return e.replace(/\/+$/,``)}function an(e,t){return e.host?rn(e.host):e.conversationUrl?rn(Qt(e.conversationUrl)):rn(t?.host??``)}function q(e={}){let t=H();if(!t&&!e.host&&!e.conversationUrl)throw new nn;let n=e.sessionApiKey??e.apiKey??t?.apiKey??void 0;return{host:an(e,t),...n?{apiKey:n}:{},workingDir:e.workingDir??j(),...e.timeout===void 0?{}:{timeout:e.timeout}}}function on(e){let{host:t,apiKey:n,timeout:r}=q(e);return{baseUrl:t,...n?{apiKey:n}:{},timeout:r??6e4}}var sn={_comment:`Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.`,versions:{agentServer:`1.38.0`,agentCanvas:`1.7.2`,automation:`1.4.1`},compatibility:{minimumAgentServer:`1.28.0`},constraints:{_comment:`Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).`,agentClientProtocol:`agent-client-protocol<0.11`},images:{agentServer:`ghcr.io/openhands/agent-server`,agentCanvas:`ghcr.io/openhands/agent-canvas`},ports:{agentServer:18e3,automation:18001,proxy:8e3},paths:{stateSubdir:`agent-canvas`,conversations:`agent-canvas/conversations`,bashEvents:`agent-canvas/bash_events`,automationDb:`automation/automations.db`,canvasBasePath:`/canvas`},packages:{agentServer:`openhands-agent-server`,automation:`openhands-automation`,tools:`openhands-tools`,workspace:`openhands-workspace`},telemetry:{posthogApiKey:`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,posthogHost:`https://us.i.posthog.com`}},cn=5e3,ln=`unknown`,J=sn.compatibility.minimumAgentServer,un=`AGENT_SERVER_UNSUPPORTED_VERSION`,dn=`AGENT_SERVER_UNKNOWN_VERSION`,Y=null,fn=e=>Array.isArray(e?.usable_tools)?e.usable_tools:null,X=class extends Error{details;noBackendConfigured;constructor(e,t){let n=t?.noBackendConfigured??!1;super(n?`No agent server backend is configured yet. Add a backend to get started.`:`Could not connect to the configured agent server. Make sure it is running and reachable, then reload the page.`),this.name=`AgentServerUnavailableError`,this.details=e??null,this.noBackendConfigured=n}},pn=e=>e instanceof X||typeof e==`object`&&!!e&&`name`in e&&e.name===`AgentServerUnavailableError`,mn=class extends X{code=un;actualVersion;requiredVersion=J;constructor(e){let t=`Agent Canvas requires agent-server ${J} or newer; this backend is running ${e}. Please upgrade the agent-server backend.`;super(t),this.name=`AgentServerUnsupportedVersionError`,this.message=t,this.actualVersion=e}},hn=class extends X{code=dn;actualVersion;requiredVersion=J;constructor(e){let t=`Could not determine this backend's agent-server version.${e?` It reported "${e}".`:``} Agent Canvas requires agent-server ${J} or newer, but this backend did not return a valid version from /server_info. Restart or rebuild the agent-server backend, then try again.`;super(t),this.name=`AgentServerUnknownVersionError`,this.message=t,this.actualVersion=e}},gn=e=>M()&&Q(e,401);function Z(){Y=null}function _n(e){let t=fn(Y);return Array.isArray(t)?t.includes(e):!0}function vn(e){return e instanceof Error&&e.name===`HttpError`&&`status`in e&&typeof e.status==`number`}function Q(e,t){return vn(e)&&e.status===t}function yn(e){return typeof e==`string`&&e.trim()||null}function bn(e){return yn(e.sdk_version)}function xn(e){return yn(e.version)??bn(e)}function Sn(e){let t=xn(e);return!t||t.toLowerCase()===ln?null:t}function Cn(e){let t=Sn(e);return!t||!En(t)?null:t}function wn(e){return!Y||e&&H()?.host!==e?null:Cn(Y)}function Tn(e,t){let n=En(e),r=En(t);if(!n||!r)return null;for(let e of[`major`,`minor`,`patch`]){if(n[e]>r[e])return 1;if(n[e]<r[e])return-1}return n.prerelease&&!r.prerelease?-1:!n.prerelease&&r.prerelease?1:n.prerelease&&r.prerelease?n.prerelease.localeCompare(r.prerelease):0}function En(e){let[t]=e.trim().replace(/^v/,``).split(`+`),[n,r]=t.split(`-`,2),i=n.split(`.`);if(i.length!==3)return null;let[a,o,s]=i.map(e=>Number(e));return[a,o,s].every(e=>Number.isInteger(e)&&e>=0)?{major:a,minor:o,patch:s,prerelease:r}:null}function Dn(e){let t=Sn(e);if(!t)throw Z(),new hn(xn(e));let n=Tn(t,J);if(n===null)throw Z(),new hn(t);if(n<0)throw Z(),new mn(t)}async function On(){let e=H();if(!e){if(Z(),L(V().backend))throw new X(`No backend configured`,{noBackendConfigured:!0});return null}let t=q({host:e.host,sessionApiKey:e.apiKey||null,timeout:cn}),n;try{n=await new ae(t).getServerInfo()}catch(e){throw Z(),Q(e,401)?e:new X(e instanceof Error?e.message:null)}if(Dn(n),M())try{await new re(t).getSettings()}catch(e){if(Q(e,401))throw e;console.warn(`[agent-server] getSettings() probe failed (non-401):`,e)}return Y=n,n}var kn={WEB_CLIENT_CONFIG:[`web-client-config`],MAIN_APP_COOKIE_AUTH:[`main-app-cookie-auth`]},An={all:[`settings`],byScope:e=>[`settings`,e],personal:()=>[`settings`,`personal`]},jn={all:[`llm-profiles`]},Mn={all:[`agent-profiles`]},Nn={retry:!1},Pn={all:[`llm-subscription`],openaiStatus:[`llm-subscription`,`openai`,`status`],openaiModels:[`llm-subscription`,`openai`,`models`]},Fn={all:[`local-workspaces`]},In={marketplace:[`plugins-marketplace`],installed:[`plugins-installed`],local:[`plugins-local`]},Ln={latestVersion:[`agent-canvas-latest-version`]},Rn={staleTime:1e3*60*5,gcTime:1e3*60*15},$=u.createContext(null);function zn(){return typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID():`backend-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Bn({children:e}){let t=u.useSyncExternalStore(Bt,Rt,Rt),n=u.useCallback(()=>{Z(),Yt.invalidateQueries({queryKey:kn.WEB_CLIENT_CONFIG})},[]),r=u.useCallback((e,t)=>{let r=W()?.backendId??null,i=W()?.orgId??null,a=t??null;e===r&&a===i||(zt({backendId:e,orgId:a}),n())},[n]),i=u.useCallback(e=>{let t={...e,id:zn()};return G([...U(),t]),zt({backendId:t.id}),n(),t},[n]),a=u.useCallback((e,t)=>{let r=U().find(t=>t.id===e),i=W()?.backendId??null;G(U().map(n=>n.id===e?{...n,...t}:n));let a=t.host!==void 0&&r!==void 0&&t.host!==r.host,o=t.apiKey!==void 0&&r!==void 0&&t.apiKey!==r.apiKey;(a||o)&&(Xe(e),i===e&&n())},[n]),o=u.useCallback(e=>{G(U().filter(t=>t.id!==e)),Ze(e),n()},[n]),s=u.useMemo(()=>({backends:t.backends,active:t.active,setActive:r,addBackend:i,updateBackend:a,removeBackend:o}),[t,r,i,a,o]);return(0,x.jsx)($.Provider,{value:s,children:e})}function Vn(){let e=u.useContext($);if(!e)throw Error(`useActiveBackendContext must be used inside <ActiveBackendProvider>`);return e}function Hn(){let e=u.useContext($);return e?e.active:{backend:N()??Ft,orgId:null}}export{Je as $,Qt as A,_t as B,Q as C,q as D,nn as E,Jt as F,mt as G,pt as H,V as I,O as J,j as K,H as L,Kt as M,qt as N,on as O,Yt as P,Ge as Q,U as R,vn as S,sn as T,k as U,Qe as V,ut as W,ht as X,M as Y,dt as Z,wn as _,_e as _t,Nn as a,Fe as at,_n as b,jn as c,v as ct,In as d,g as dt,Ye as et,kn as f,fe as ft,Tn as g,h as gt,Z as h,ge as ht,Mn as i,Pe as it,tn as j,en as k,Pn as l,_ as lt,Dn as m,m as mt,Hn as n,S as nt,Ln as o,Ie as ot,An as p,d as pt,ft as q,Vn as r,Ne as rt,Rn as s,y as st,Bn as t,qe as tt,Fn as u,De as ut,Cn as v,ve as vt,On as w,pn as x,gn as y,de as yt,L as z};
|