@openhands/agent-canvas 1.7.2 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.windows.md +2 -2
- package/build/assets/{Trans-DP5rcauH.js → Trans-Bwpzk1wT.js} +1 -1
- package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-C921BlYB.js} +1 -1
- package/build/assets/active-backend-context-BiwzkzDy.js +2 -0
- package/build/assets/agent-context-settings-DXNT_dcw.js +1 -0
- package/build/assets/agent-profiles-settings-BymJf3EP.js +1 -0
- package/build/assets/agent-server-conversation-service.api-CYSWw-2g.js +41 -0
- package/build/assets/agent-settings-BjgQQe-_.js +1 -0
- package/build/assets/{agent-settings-BIOsUglV.js → agent-settings-WzqXk6B4.js} +2 -2
- package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-DR8EVyZM.js} +1 -1
- package/build/assets/api-error-message-e16L1kwH.js +1 -0
- package/build/assets/api-key-entry-screen-DI0I04O3.js +1 -0
- package/build/assets/app-settings-DGistSFV.js +1 -0
- package/build/assets/automation-C_eCrGyP.js +1 -0
- package/build/assets/automation-detail-DY6x2FW1.js +2 -0
- package/build/assets/automation-export-C09f-Lua.js +2 -0
- package/build/assets/automation-setup-route-CqKp0717.js +1 -0
- package/build/assets/automations-list-CqWJ7qXW.js +1 -0
- package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-D4ngzpSh.js} +1 -1
- package/build/assets/backend-form-modal-B8D5hBzK.js +1 -0
- package/build/assets/{backend-synced-settings-badge-BNpEylNP.js → backend-synced-settings-badge-BnzI8Ysj.js} +1 -1
- package/build/assets/{badge-DwgrwohM.js → badge-1Mf1iPcX.js} +1 -1
- package/build/assets/{base-modal-CSHhJTSr.js → base-modal-BBuy0WQQ.js} +1 -1
- package/build/assets/{brand-button-CQO8oqVo.js → brand-button-DGN6Y9o6.js} +1 -1
- package/build/assets/browser-D_ekTlTS.js +6 -0
- package/build/assets/{browser-tab-CEApjoEV.js → browser-tab-D4a4Ou_w.js} +1 -1
- package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-CgbcjD97.js} +1 -1
- package/build/assets/check-CPLXgluF.js +1 -0
- package/build/assets/chevron-down-CP4QHvyc.js +1 -0
- package/build/assets/circle-check-Dpy2_xSI.js +1 -0
- package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-yTAS-nX3.js} +1 -1
- package/build/assets/cloud-funnel-analytics-CEOl5Gxr.js +1 -0
- package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Bd2yySnF.js} +1 -1
- package/build/assets/command-menu-Bj6X4ckE.js +1 -0
- package/build/assets/condenser-settings-EAXQNR2E.js +1 -0
- package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-NCUPr2-O.js} +1 -1
- package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-CrCrYuPF.js} +1 -1
- package/build/assets/conversation-BzyIcSwr.js +1 -0
- package/build/assets/conversation-CUJ0Vo8g.js +90 -0
- package/build/assets/conversation-panel-BzyIcSwr.js +1 -0
- package/build/assets/conversation-state-store-F62HvuI1.js +1 -0
- package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-BCZ7rUMH.js} +1 -1
- package/build/assets/{copy-B8Y5ufoR.js → copy-DCmZtz6n.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-D_Lp6-Fl.js} +1 -1
- package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-DLmolX8Q.js} +1 -1
- package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-BB8rzqXL.js} +1 -1
- package/build/assets/{entry.client-DETaouwO.js → entry.client-BbIYOsIg.js} +2 -2
- package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-C08-srev.js} +1 -1
- package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-BepBBX66.js} +1 -1
- package/build/assets/extensions-hub-R3KNv-5V.js +1 -0
- package/build/assets/extensions-navigation-CfWFmI1I.js +1 -0
- package/build/assets/{external-link-Cnnd6ikC.js → external-link-BdBSg8rk.js} +1 -1
- package/build/assets/files-tab-DEq8MbHu.js +1 -0
- package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-DAfsCJTe.js} +1 -1
- package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-CxfPJpzC.js} +1 -1
- package/build/assets/git-provider-icon-BZqqUPlm.js +1 -0
- package/build/assets/git-repo-dropdown-9WKINV6J.js +1 -0
- package/build/assets/git-repo-dropdown-DEpOwUez.js +1 -0
- package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-CX9oIoVT.js} +1 -1
- package/build/assets/home-CY0JaxiY.js +1 -0
- package/build/assets/home-CaNWlVvB.js +1 -0
- package/build/assets/home-store-Ch1ErdBc.js +1 -0
- package/build/assets/index-home-CaNWlVvB.js +1 -0
- package/build/assets/info-CmWQXtRQ.js +1 -0
- package/build/assets/install-server-modal-BWrudmZU.js +1 -0
- package/build/assets/{launch-Ccnhte5b.js → launch-B1POpHuP.js} +1 -1
- package/build/assets/{list-todo-_BXQzOiB.js → list-todo-DtiL3lTp.js} +1 -1
- package/build/assets/llm-not-configured-banner-3tMsM4K6.js +27 -0
- package/build/assets/llm-settings-CXo8iPNW.js +1 -0
- package/build/assets/llm-settings-D0W8mJDk.js +1 -0
- package/build/assets/{llm-subscription-service-W5BprsNA.js → llm-subscription-service-DBJbfd8Z.js} +1 -1
- package/build/assets/loader-circle-B4QDBARx.js +1 -0
- package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DfZ_bhV7.js} +1 -1
- package/build/assets/manage-backends-modal-CwyWsiag.js +1 -0
- package/build/assets/manifest-39f4789d.js +1 -0
- package/build/assets/{markdown-renderer-CvOO0YIr.js → markdown-renderer-DgiLLhW6.js} +6 -6
- package/build/assets/mcp-DXG9LWrI.js +9 -0
- package/build/assets/mcp-marketplace-utils-DFmhKc5s.js +1 -0
- package/build/assets/messages-kBjKaAeA.js +40 -0
- package/build/assets/{modal-body-DQhiw-AR.js → modal-body-CMsDpalT.js} +1 -1
- package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-B6PDrxXo.js} +1 -1
- package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-DyxBZaAb.js} +1 -1
- package/build/assets/{onboarding-BegDrOKn.js → onboarding-47hh2IHA.js} +1 -1
- package/build/assets/onboarding-modal-9BuvvROo.js +1 -0
- package/build/assets/organization-service.api-UDy63-oC.js +1 -0
- package/build/assets/{pencil-8_lvWDoZ.js → pencil-BjgtZmWp.js} +1 -1
- package/build/assets/{planner-tab-w6HT0N_A.js → planner-tab-BWk8885v.js} +1 -1
- package/build/assets/plugins-management-service-CjkgF2dd.js +1 -0
- package/build/assets/plus-DrKuuvMe.js +1 -0
- package/build/assets/profiles-service.api-CukSFLzz.js +1 -0
- package/build/assets/providers-CqUWC85T.js +1 -0
- package/build/assets/proxy-BBUG3sd2.js +1 -0
- package/build/assets/{puzzle-DXWdfaa7.js → puzzle-BoNc6zZ8.js} +1 -1
- package/build/assets/recommended-automations-launcher-ejxy1P27.js +1 -0
- package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-BrM5ZAZD.js} +1 -1
- package/build/assets/root-5S-M8SYa.js +2 -0
- package/build/assets/root-DZ39lS5f.css +1 -0
- package/build/assets/root-layout-BPqoa0gv.js +3 -0
- package/build/assets/schema-field-nImDoY6-.js +1 -0
- package/build/assets/{sdk-section-page-BW-i45yr.js → sdk-section-page-BxMrtUNV.js} +1 -1
- package/build/assets/search-Dc2qR4O2.js +1 -0
- package/build/assets/secrets-service-Dhjh3HhH.js +1 -0
- package/build/assets/{secrets-settings-D7U1ErCH.js → secrets-settings-CPdxceT_.js} +1 -1
- package/build/assets/segmented-toggle-Do6oyepX.js +1 -0
- package/build/assets/settings-BRbnfKEm.js +1 -0
- package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-DYCULKpp.js} +1 -1
- package/build/assets/{settings-index-COAdxm2Q.js → settings-index-C9o2NBO0.js} +1 -1
- package/build/assets/settings-input-B-q2gkVy.js +1 -0
- package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-WpQi0q1L.js} +1 -1
- package/build/assets/{settings-modal-CFnbQ8_4.js → settings-modal-CEK0AIx6.js} +1 -1
- package/build/assets/settings-service.api-CZiPD8__.js +1 -0
- package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-LqKdGxHL.js} +1 -1
- package/build/assets/shared-conversation-Bu-dQlgp.js +1 -0
- package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-oHBGQmLh.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-U78hQRJ1.js → sidebar-mobile-menu-toggle-ND-hgygu.js} +1 -1
- package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-CrujNA09.js} +1 -1
- package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-Bui-WNEr.js} +1 -1
- package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-CZBI7OqH.js} +1 -1
- package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-BOov_phZ.js} +1 -1
- package/build/assets/{skills-plugins-BPhaNpfx.js → skills-plugins-D0PiHWAD.js} +1 -1
- package/build/assets/{skills-settings-CcwMtnnJ.js → skills-settings-B43KArIz.js} +2 -2
- package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-C7grwnOX.js} +1 -1
- package/build/assets/{task-list-tab-BmaTwjaS.js → task-list-tab-R3ac6m7O.js} +1 -1
- package/build/assets/{terminal-BRcoba5B.js → terminal-yqkNdEAx.js} +1 -1
- package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-BeSrbgCg.js} +1 -1
- package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-wW5TWcdN.js} +1 -1
- package/build/assets/{typography-C6fuRTTT.js → typography-iYhzLlHO.js} +1 -1
- package/build/assets/{use-acp-credential-form-B0_pZ_uS.js → use-acp-credential-form-DUxbxmbq.js} +1 -1
- package/build/assets/use-activate-agent-profile-CDHA52tC.js +1 -0
- package/build/assets/use-agent-profiles-TsOdIyw5.js +1 -0
- package/build/assets/{use-can-manage-org-profiles-CrG1km7R.js → use-can-manage-org-profiles-Bt1M71u5.js} +1 -1
- package/build/assets/use-cloud-current-user-id-DWt7HCgf.js +1 -0
- package/build/assets/{use-config-Csy8EAP9.js → use-config-CxlEdf_v.js} +1 -1
- package/build/assets/{use-create-conversation-Dsa4nzU9.js → use-create-conversation-nOJ6Um5h.js} +1 -1
- package/build/assets/{use-create-secret-BnxuAjDt.js → use-create-secret-Dj5ang9x.js} +1 -1
- package/build/assets/use-is-authed-BT7Iud4U.js +1 -0
- package/build/assets/{use-is-creating-conversation-CIAcnd8M.js → use-is-creating-conversation-CAggrM75.js} +1 -1
- package/build/assets/use-llm-profiles-2Wc2db8u.js +1 -0
- package/build/assets/use-onboarding-completion-gxQlcEy2.js +1 -0
- package/build/assets/use-plugins-marketplace-CVO7sXYR.js +1 -0
- package/build/assets/use-save-agent-profile-D0wC5ExW.js +1 -0
- package/build/assets/{use-save-settings-BRh9p_fv.js → use-save-settings-L3aMaDeS.js} +1 -1
- package/build/assets/use-settings-8nt3DGxW.js +1 -0
- package/build/assets/use-settings-nav-items-DHAAD-zk.js +16 -0
- package/build/assets/use-skills-CE6miQ3r.js +1 -0
- package/build/assets/use-tracking-BGboadaZ.js +68 -0
- package/build/assets/{use-user-conversation-GnGhs_Ob.js → use-user-conversation-BIIpGUgM.js} +1 -1
- package/build/assets/useInfiniteQuery-BLRVmVPU.js +1 -0
- package/build/assets/{useMutation-DyQXZFEF.js → useMutation-CaSHLnX0.js} +1 -1
- package/build/assets/{useQueries-B3T1a7qt.js → useQueries--d_WWAzc.js} +1 -1
- package/build/assets/{useQuery-B38jBavx.js → useQuery-DiPh8LRJ.js} +1 -1
- package/build/assets/utils-BgGG1znF.js +1 -0
- package/build/assets/{vendor~browser-CIoZCqGs.js → vendor~browser-IVYgIgG1.js} +1 -1
- package/build/assets/{vendor~entry.client-Di4qO77Y.js → vendor~entry.client-BcYIVQvB.js} +1 -1
- package/build/assets/{vendor~entry.client-BfviqoVc.js → vendor~entry.client-CXM9oiAk.js} +1 -1
- package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0bpqexo-CbTboogo.js} +2 -2
- package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f9xdmd0z-DLMP7bZx.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~d4by102p-C2f0ZhS-.js} +1 -1
- package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-C7RmQJwN.js} +1 -1
- package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-Bqp1ZqJM.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-BCn8lzeG.js} +1 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~automation-setup-route-B_L-gcOG.js +1 -0
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-sjx0x5ac.js +1 -0
- package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~automation-setup-route~onboarding-modal-D7IDevqN.js +1 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~bi2r7bko-Bw4AuHN1.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~dfc8ddxy-tTyxnjXT.js} +1 -1
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hakxo2tj-ClV0p9g3.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gy8zbn65-CGt6bWRT.js} +1 -1
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~eywn6ulz-BKxxr74w.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~dufan6ng-Dtdw8H0q.js} +17 -4
- package/build/assets/{verification-settings-CaCzojbc.js → verification-settings-DBsnSXC3.js} +1 -1
- package/build/assets/x-omAzpXkl.js +1 -0
- package/build/favicon-16x16.png +0 -0
- package/build/favicon-32x32.png +0 -0
- package/build/favicon.ico +0 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +39 -2
- package/build/locales/ca/openhands.json +39 -2
- package/build/locales/de/openhands.json +39 -2
- package/build/locales/en/openhands.json +40 -3
- package/build/locales/es/openhands.json +39 -2
- package/build/locales/fr/openhands.json +39 -2
- package/build/locales/it/openhands.json +39 -2
- package/build/locales/ja/openhands.json +39 -2
- package/build/locales/ko-KR/openhands.json +39 -2
- package/build/locales/no/openhands.json +39 -2
- package/build/locales/pt/openhands.json +39 -2
- package/build/locales/tr/openhands.json +39 -2
- package/build/locales/uk/openhands.json +39 -2
- package/build/locales/zh-CN/openhands.json +39 -2
- package/build/locales/zh-TW/openhands.json +39 -2
- package/config/defaults.json +4 -4
- package/dist/api/agent-server-adapter.cjs +3 -3
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.d.ts +46 -6
- package/dist/api/agent-server-adapter.js +187 -168
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/agent-server-compatibility.cjs +1 -1
- package/dist/api/agent-server-compatibility.cjs.map +1 -1
- package/dist/api/agent-server-compatibility.d.ts +4 -0
- package/dist/api/agent-server-compatibility.js +41 -38
- package/dist/api/agent-server-compatibility.js.map +1 -1
- package/dist/api/automation-service/automation-service.api.cjs +1 -1
- package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
- package/dist/api/automation-service/automation-service.api.d.ts +20 -0
- package/dist/api/automation-service/automation-service.api.js +136 -99
- package/dist/api/automation-service/automation-service.api.js.map +1 -1
- package/dist/api/backend-registry/storage.cjs +1 -1
- package/dist/api/backend-registry/storage.cjs.map +1 -1
- package/dist/api/backend-registry/storage.js +1 -1
- package/dist/api/backend-registry/storage.js.map +1 -1
- package/dist/api/backend-registry/types.d.ts +2 -0
- package/dist/api/cloud/conversation-service.api.cjs +1 -1
- package/dist/api/cloud/conversation-service.api.js +22 -22
- package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
- package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
- package/dist/api/mcp-service/mcp-service.api.js +19 -19
- package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
- package/dist/api/settings-service/settings-service.api.cjs +1 -1
- package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
- package/dist/api/settings-service/settings-service.api.js +26 -12
- package/dist/api/settings-service/settings-service.api.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +2 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.d.ts +12 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +94 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +31 -90
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.d.ts +0 -7
- package/dist/components/features/automations/recommended-automations-section.d.ts +0 -6
- package/dist/components/features/backends/backend-form-modal.cjs +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
- package/dist/components/features/backends/backend-form-modal.js +568 -358
- package/dist/components/features/backends/backend-form-modal.js.map +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs.map +1 -1
- package/dist/components/features/backends/device-flow-auth.d.ts +9 -1
- package/dist/components/features/backends/device-flow-auth.js +56 -55
- package/dist/components/features/backends/device-flow-auth.js.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.js +1 -1
- package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
- package/dist/components/features/chat/chat-interface.cjs +1 -1
- package/dist/components/features/chat/chat-interface.cjs.map +1 -1
- package/dist/components/features/chat/chat-interface.js +105 -105
- package/dist/components/features/chat/chat-interface.js.map +1 -1
- package/dist/components/features/chat/chat-message.cjs +1 -1
- package/dist/components/features/chat/chat-message.cjs.map +1 -1
- package/dist/components/features/chat/chat-message.d.ts +2 -1
- package/dist/components/features/chat/chat-message.js +59 -49
- package/dist/components/features/chat/chat-message.js.map +1 -1
- package/dist/components/features/chat/pending-user-messages.cjs +1 -1
- package/dist/components/features/chat/pending-user-messages.cjs.map +1 -1
- package/dist/components/features/chat/pending-user-messages.js +4 -1
- package/dist/components/features/chat/pending-user-messages.js.map +1 -1
- package/dist/components/features/chat/typing-indicator.cjs +1 -1
- package/dist/components/features/chat/typing-indicator.cjs.map +1 -1
- package/dist/components/features/chat/typing-indicator.d.ts +8 -1
- package/dist/components/features/chat/typing-indicator.js +94 -10
- package/dist/components/features/chat/typing-indicator.js.map +1 -1
- package/dist/components/features/command-menu/command-menu-items.d.ts +5 -1
- package/dist/components/features/files-tab/segmented-toggle.cjs +1 -1
- package/dist/components/features/files-tab/segmented-toggle.cjs.map +1 -1
- package/dist/components/features/files-tab/segmented-toggle.d.ts +2 -0
- package/dist/components/features/files-tab/segmented-toggle.js +17 -14
- package/dist/components/features/files-tab/segmented-toggle.js.map +1 -1
- package/dist/components/features/manifest/manifest-form-field.d.ts +27 -0
- package/dist/components/features/manifest/manifest-prerequisites-step.d.ts +11 -0
- package/dist/components/features/manifest/manifest-review-step.d.ts +14 -0
- package/dist/components/features/manifest/manifest-setup-dialog.d.ts +14 -0
- package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.js +16 -16
- package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
- package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
- package/dist/components/features/mcp-page/installed-server-card.d.ts +2 -2
- package/dist/components/features/mcp-page/installed-server-card.js +6 -7
- package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
- package/dist/components/features/mcp-page/installed-servers-section.cjs +1 -1
- package/dist/components/features/mcp-page/installed-servers-section.cjs.map +1 -1
- package/dist/components/features/mcp-page/installed-servers-section.d.ts +2 -2
- package/dist/components/features/mcp-page/installed-servers-section.js +2 -2
- package/dist/components/features/mcp-page/installed-servers-section.js.map +1 -1
- package/dist/components/features/mcp-page/mcp-server-health.cjs +1 -1
- package/dist/components/features/mcp-page/mcp-server-health.js +4 -4
- package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +1 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.js +2 -1
- package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
- package/dist/components/features/settings/settings-input.cjs +1 -1
- package/dist/components/features/settings/settings-input.cjs.map +1 -1
- package/dist/components/features/settings/settings-input.d.ts +6 -0
- package/dist/components/features/settings/settings-input.js +13 -8
- package/dist/components/features/settings/settings-input.js.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.js +124 -123
- package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +3 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/contexts/active-backend-context.cjs +1 -1
- package/dist/contexts/active-backend-context.cjs.map +1 -1
- package/dist/contexts/active-backend-context.d.ts +3 -2
- package/dist/contexts/active-backend-context.js +55 -42
- package/dist/contexts/active-backend-context.js.map +1 -1
- package/dist/favicon-16x16.png +0 -0
- package/dist/favicon-32x32.png +0 -0
- package/dist/favicon.ico +0 -0
- package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
- package/dist/hooks/mutation/use-update-mcp-server.js +5 -5
- package/dist/hooks/query/query-keys.cjs.map +1 -1
- package/dist/hooks/query/query-keys.d.ts +4 -0
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-cloud-current-user-id.cjs +1 -1
- package/dist/hooks/query/use-cloud-current-user-id.cjs.map +1 -1
- package/dist/hooks/query/use-cloud-current-user-id.js +7 -5
- package/dist/hooks/query/use-cloud-current-user-id.js.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.js +5 -1
- package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
- package/dist/hooks/query/use-manifest-capabilities.d.ts +21 -0
- package/dist/hooks/query/use-manifest-prerequisites.d.ts +24 -0
- package/dist/hooks/use-can-manage-org-profiles.cjs +1 -1
- package/dist/hooks/use-can-manage-org-profiles.cjs.map +1 -1
- package/dist/hooks/use-can-manage-org-profiles.js +2 -1
- package/dist/hooks/use-can-manage-org-profiles.js.map +1 -1
- package/dist/hooks/use-llm-configured.cjs +1 -1
- package/dist/hooks/use-llm-configured.cjs.map +1 -1
- package/dist/hooks/use-llm-configured.js +2 -1
- package/dist/hooks/use-llm-configured.js.map +1 -1
- package/dist/hooks/use-manifest-preflight.d.ts +18 -0
- package/dist/hooks/use-tracking.cjs +1 -1
- package/dist/hooks/use-tracking.cjs.map +1 -1
- package/dist/hooks/use-tracking.d.ts +14 -0
- package/dist/hooks/use-tracking.js +28 -10
- package/dist/hooks/use-tracking.js.map +1 -1
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +38 -1
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +2 -2
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +645 -16
- package/dist/i18n/translation.js.map +1 -1
- package/dist/icons/external-link.cjs +2 -0
- package/dist/icons/external-link.cjs.map +1 -0
- package/dist/icons/external-link.js +22 -0
- package/dist/icons/external-link.js.map +1 -0
- package/dist/icons/server.cjs +2 -0
- package/dist/icons/server.cjs.map +1 -0
- package/dist/icons/server.js +17 -0
- package/dist/icons/server.js.map +1 -0
- package/dist/locales/ar/openhands.json +39 -2
- package/dist/locales/ca/openhands.json +39 -2
- package/dist/locales/de/openhands.json +39 -2
- package/dist/locales/en/openhands.json +40 -3
- package/dist/locales/es/openhands.json +39 -2
- package/dist/locales/fr/openhands.json +39 -2
- package/dist/locales/it/openhands.json +39 -2
- package/dist/locales/ja/openhands.json +39 -2
- package/dist/locales/ko-KR/openhands.json +39 -2
- package/dist/locales/no/openhands.json +39 -2
- package/dist/locales/pt/openhands.json +39 -2
- package/dist/locales/tr/openhands.json +39 -2
- package/dist/locales/uk/openhands.json +39 -2
- package/dist/locales/zh-CN/openhands.json +39 -2
- package/dist/locales/zh-TW/openhands.json +39 -2
- package/dist/manifests/automation-interface.cjs +2 -0
- package/dist/manifests/automation-interface.cjs.map +1 -0
- package/dist/manifests/automation-interface.d.ts +44 -0
- package/dist/manifests/automation-interface.js +81 -0
- package/dist/manifests/automation-interface.js.map +1 -0
- package/dist/manifests/automation-setup.cjs +2 -0
- package/dist/manifests/automation-setup.cjs.map +1 -0
- package/dist/manifests/automation-setup.d.ts +52 -0
- package/dist/manifests/automation-setup.js +8 -0
- package/dist/manifests/automation-setup.js.map +1 -0
- package/dist/manifests/interface-validation.cjs +2 -0
- package/dist/manifests/interface-validation.cjs.map +1 -0
- package/dist/manifests/interface-validation.d.ts +27 -0
- package/dist/manifests/interface-validation.js +182 -0
- package/dist/manifests/interface-validation.js.map +1 -0
- package/dist/manifests/manifest-actions.d.ts +15 -0
- package/dist/manifests/manifest-capabilities.d.ts +25 -0
- package/dist/manifests/manifest-error-map.d.ts +40 -0
- package/dist/manifests/manifest-local-validation.d.ts +56 -0
- package/dist/manifests/manifest-registry.cjs +2 -0
- package/dist/manifests/manifest-registry.cjs.map +1 -0
- package/dist/manifests/manifest-registry.d.ts +15 -0
- package/dist/manifests/manifest-registry.js +26 -0
- package/dist/manifests/manifest-registry.js.map +1 -0
- package/dist/manifests/manifest-sources.cjs +2 -0
- package/dist/manifests/manifest-sources.cjs.map +1 -0
- package/dist/manifests/manifest-sources.d.ts +15 -0
- package/dist/manifests/manifest-sources.js +8 -0
- package/dist/manifests/manifest-sources.js.map +1 -0
- package/dist/manifests/manifest-template.d.ts +18 -0
- package/dist/manifests/manifest-validation.cjs +2 -0
- package/dist/manifests/manifest-validation.cjs.map +1 -0
- package/dist/manifests/manifest-validation.d.ts +30 -0
- package/dist/manifests/manifest-validation.js +145 -0
- package/dist/manifests/manifest-validation.js.map +1 -0
- package/dist/manifests/types.cjs +2 -0
- package/dist/manifests/types.cjs.map +1 -0
- package/dist/manifests/types.d.ts +227 -0
- package/dist/manifests/types.js +6 -0
- package/dist/manifests/types.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +75 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +78 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs +17 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js +89 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs +10 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js +17 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js +15 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js +18 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js +14 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js +14 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +23 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/index.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/index.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/index.js +18 -0
- package/dist/node_modules/@openhands/extensions/automations/index.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.js +89 -0
- package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +3 -3
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.cjs +17 -4
- package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.js +5 -5
- package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +9 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js +29 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.js +5 -5
- package/dist/routes/mcp.cjs +1 -1
- package/dist/routes/mcp.cjs.map +1 -1
- package/dist/routes/mcp.js +73 -82
- package/dist/routes/mcp.js.map +1 -1
- package/dist/services/telemetry.cjs +1 -1
- package/dist/services/telemetry.cjs.map +1 -1
- package/dist/services/telemetry.d.ts +8 -0
- package/dist/services/telemetry.js +163 -116
- package/dist/services/telemetry.js.map +1 -1
- package/dist/types/agent-server/core/events/conversation-state-event.d.ts +2 -19
- package/dist/types/agent-server/core/events/observation-event.d.ts +2 -18
- package/dist/types/automation.d.ts +7 -3
- package/dist/types/mcp-server.d.ts +5 -0
- package/dist/types/settings.d.ts +3 -0
- package/dist/utils/api-error-message.d.ts +6 -2
- package/dist/utils/automation-catalog.cjs +2 -0
- package/dist/utils/automation-catalog.cjs.map +1 -0
- package/dist/utils/automation-catalog.d.ts +28 -0
- package/dist/utils/automation-catalog.js +5 -0
- package/dist/utils/automation-catalog.js.map +1 -0
- package/dist/utils/automation-timeout.d.ts +3 -2
- package/dist/utils/mcp-config.cjs +1 -1
- package/dist/utils/mcp-config.cjs.map +1 -1
- package/dist/utils/mcp-config.d.ts +8 -0
- package/dist/utils/mcp-config.js +25 -20
- package/dist/utils/mcp-config.js.map +1 -1
- package/dist/utils/mcp-installed-servers.cjs +1 -1
- package/dist/utils/mcp-installed-servers.cjs.map +1 -1
- package/dist/utils/mcp-installed-servers.js +6 -3
- package/dist/utils/mcp-installed-servers.js.map +1 -1
- package/dist/utils/responder-deployment.d.ts +5 -1
- package/dist/utils/transcript-export/index.cjs +5 -5
- package/dist/utils/transcript-export/index.js +12 -12
- package/package.json +3 -3
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/check-translation-completeness.cjs +1 -0
- package/scripts/dev-safe.mjs +17 -12
- package/scripts/dev-static.mjs +17 -0
- package/scripts/dev-with-automation.mjs +12 -14
- package/scripts/ingress.mjs +22 -0
- package/scripts/proxy-utils.mjs +157 -2
- package/scripts/runtime-services-info.mjs +6 -6
- package/scripts/static-build.mjs +0 -7
- package/scripts/static-server.mjs +10 -0
- package/build/assets/active-backend-context-BlZPzZNU.js +0 -1
- package/build/assets/agent-context-settings-CTaN-Iw9.js +0 -1
- package/build/assets/agent-profiles-settings-CR4VTqv_.js +0 -1
- package/build/assets/agent-server-conversation-service.api-Btmi4q6d.js +0 -41
- package/build/assets/agent-settings-KQs-occT.js +0 -1
- package/build/assets/api-key-entry-screen-BhR24gkM.js +0 -1
- package/build/assets/app-settings-Bs4sY8WP.js +0 -1
- package/build/assets/automation-BGP_I1RR.js +0 -1
- package/build/assets/automation-detail-CwDnJbYR.js +0 -2
- package/build/assets/automation-export-Bu-r-EzL.js +0 -2
- package/build/assets/automations-list-CYw7_6FR.js +0 -1
- package/build/assets/backend-form-modal-Ce-KRHOJ.js +0 -1
- package/build/assets/browser-BUDJnBg4.js +0 -6
- package/build/assets/check-BMOG005H.js +0 -1
- package/build/assets/chevron-down-CV1zZP_K.js +0 -1
- package/build/assets/circle-check-lvN_jFN5.js +0 -1
- package/build/assets/client-source-1v-kWLNU.js +0 -1
- package/build/assets/cloud-funnel-analytics-CasMM7EO.js +0 -1
- package/build/assets/command-menu-N_BriUy8.js +0 -1
- package/build/assets/condenser-settings-Czi8cKxV.js +0 -1
- package/build/assets/conversation-C25pc2dT.js +0 -1
- package/build/assets/conversation-CObLYSJd.js +0 -90
- package/build/assets/conversation-panel-C25pc2dT.js +0 -1
- package/build/assets/conversation-state-store-DTq4hFoP.js +0 -1
- package/build/assets/extensions-hub-BKftOQ-X.js +0 -1
- package/build/assets/extensions-navigation-DF24q1H1.js +0 -1
- package/build/assets/files-tab-SAiFCnS5.js +0 -1
- package/build/assets/git-provider-icon-BREx-yUX.js +0 -1
- package/build/assets/home-EPNFgzUh.js +0 -1
- package/build/assets/home-sN90Xcxp.js +0 -1
- package/build/assets/index-home-EPNFgzUh.js +0 -1
- package/build/assets/install-server-modal-BI8yUfmr.js +0 -1
- package/build/assets/llm-not-configured-banner-DTWzISnk.js +0 -27
- package/build/assets/llm-settings-BXk5_Pac.js +0 -1
- package/build/assets/llm-settings-C1vpgWam.js +0 -1
- package/build/assets/loader-circle-6zlEYCJw.js +0 -1
- package/build/assets/manage-backends-modal-DhflyGTf.js +0 -1
- package/build/assets/manifest-8082e879.js +0 -1
- package/build/assets/mcp-CxLPda-W.js +0 -9
- package/build/assets/messages-DINDkPNK.js +0 -40
- package/build/assets/onboarding-modal-DdvE6rzw.js +0 -1
- package/build/assets/organization-service.api-CT2OQlLz.js +0 -1
- package/build/assets/plugins-management-service-DVkoM3eA.js +0 -1
- package/build/assets/plus-vIbGD459.js +0 -1
- package/build/assets/profiles-service.api-CBafmAPO.js +0 -1
- package/build/assets/providers-9UzRB9mT.js +0 -1
- package/build/assets/proxy-C79PCMjo.js +0 -1
- package/build/assets/recommended-automations-launcher-BF2mtAKw.js +0 -58
- package/build/assets/root-B5JXKp1P.css +0 -1
- package/build/assets/root-Sj7W28yE.js +0 -2
- package/build/assets/root-layout-DbhKVoc7.js +0 -3
- package/build/assets/schema-field-CV6bFnoL.js +0 -1
- package/build/assets/search-sKuYKllf.js +0 -1
- package/build/assets/secrets-service-BjK-bPN2.js +0 -1
- package/build/assets/segmented-toggle-DbbD3Tve.js +0 -1
- package/build/assets/settings-Bj5Oo45A.js +0 -1
- package/build/assets/settings-input-BjW_zyTN.js +0 -1
- package/build/assets/settings-service.api-DryhKdSr.js +0 -1
- package/build/assets/shared-conversation-CnMxy7p_.js +0 -1
- package/build/assets/telemetry-cmCL3o6Z.js +0 -2
- package/build/assets/use-activate-agent-profile-DH33MvVj.js +0 -1
- package/build/assets/use-agent-profiles-Dmd_4H8q.js +0 -1
- package/build/assets/use-cloud-current-user-id-B6DP3s47.js +0 -1
- package/build/assets/use-is-authed-BsS4XwSL.js +0 -1
- package/build/assets/use-llm-profiles-BMQoc612.js +0 -1
- package/build/assets/use-onboarding-completion-B-2BTS-y.js +0 -1
- package/build/assets/use-plugins-marketplace-PBc_XNz_.js +0 -1
- package/build/assets/use-save-agent-profile-2Mk9ZX37.js +0 -1
- package/build/assets/use-settings-DBI44RnH.js +0 -1
- package/build/assets/use-settings-nav-items-Cva28C-c.js +0 -16
- package/build/assets/use-skills-RQsCtdzN.js +0 -1
- package/build/assets/use-tracking-CN1nIMnY.js +0 -1
- package/build/assets/utils-qjs_KuS4.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js +0 -1
- package/build/assets/x-EjvKGawc.js +0 -1
- /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f1hl7voa-BrmgjeOw.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~emdr2jt4-BrmgjeOw.js} +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
//#region src/manifests/interface-validation.ts
|
|
2
|
+
var e = /<[A-Za-z/!]/, t = /^[a-z0-9]+(-[a-z0-9]+)*$/, n = "https://docs.openhands.dev/", r = /^[a-z][a-z-]*$/, i = /^\.[a-z][a-z.]*json$/, a = /^[a-z0-9][a-z0-9.-]*$/, o = /^\/[A-Za-z0-9/{}_-]*$/, s = /^[^{}]*\{id\}[^{}]*$/, c = [
|
|
3
|
+
"github",
|
|
4
|
+
"gitlab",
|
|
5
|
+
"bitbucket"
|
|
6
|
+
], l = {
|
|
7
|
+
name: {
|
|
8
|
+
type: "text",
|
|
9
|
+
required: !0
|
|
10
|
+
},
|
|
11
|
+
prompt: {
|
|
12
|
+
type: "textarea",
|
|
13
|
+
required: !1
|
|
14
|
+
},
|
|
15
|
+
model: {
|
|
16
|
+
type: "llm-profile",
|
|
17
|
+
required: !1
|
|
18
|
+
},
|
|
19
|
+
timeout: {
|
|
20
|
+
type: "number",
|
|
21
|
+
required: !1
|
|
22
|
+
},
|
|
23
|
+
schedule: {
|
|
24
|
+
type: "schedule",
|
|
25
|
+
required: !1
|
|
26
|
+
}
|
|
27
|
+
}, u = Object.keys(l), d = [
|
|
28
|
+
"list",
|
|
29
|
+
"health",
|
|
30
|
+
"capabilities",
|
|
31
|
+
"validate",
|
|
32
|
+
"createPrompt",
|
|
33
|
+
"createPlugin"
|
|
34
|
+
], f = [
|
|
35
|
+
"detail",
|
|
36
|
+
"dispatch",
|
|
37
|
+
"runs",
|
|
38
|
+
"tarball"
|
|
39
|
+
];
|
|
40
|
+
function p(e) {
|
|
41
|
+
return typeof e == "object" && !!e && !Array.isArray(e);
|
|
42
|
+
}
|
|
43
|
+
var m = class {
|
|
44
|
+
errors = [];
|
|
45
|
+
fail(e, t) {
|
|
46
|
+
return this.errors.push(`${e}: ${t}`), !1;
|
|
47
|
+
}
|
|
48
|
+
copy(t, n) {
|
|
49
|
+
return typeof t != "string" || t.length === 0 ? this.fail(n, "must be a non-empty string") : e.test(t) ? this.fail(n, "must not contain markup") : !0;
|
|
50
|
+
}
|
|
51
|
+
closed(e, t, n) {
|
|
52
|
+
Object.keys(e).filter((e) => !t.includes(e)).forEach((e) => this.fail(`${n}.${e}`, "is not allowed"));
|
|
53
|
+
}
|
|
54
|
+
record(e, t) {
|
|
55
|
+
return p(e) ? !0 : (this.fail(t, "must be an object"), !1);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
function h(e, t, n) {
|
|
59
|
+
e.record(t, "routes") && (e.closed(t, [
|
|
60
|
+
"list",
|
|
61
|
+
"setup",
|
|
62
|
+
"detail"
|
|
63
|
+
], "routes"), [
|
|
64
|
+
"list",
|
|
65
|
+
"setup",
|
|
66
|
+
"detail"
|
|
67
|
+
].forEach((r) => {
|
|
68
|
+
t[r] !== n[r] && e.fail(`routes.${r}`, `must be "${n[r]}"`);
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
function g(e, t) {
|
|
72
|
+
if (e.record(t, "navigation") && (e.closed(t, ["sidebar", "commandMenu"], "navigation"), e.record(t.sidebar, "navigation.sidebar") && (e.closed(t.sidebar, ["label"], "navigation.sidebar"), e.copy(t.sidebar.label, "navigation.sidebar.label")), e.record(t.commandMenu, "navigation.commandMenu"))) {
|
|
73
|
+
let n = t.commandMenu;
|
|
74
|
+
e.closed(n, [
|
|
75
|
+
"title",
|
|
76
|
+
"description",
|
|
77
|
+
"keywords"
|
|
78
|
+
], "navigation.commandMenu"), e.copy(n.title, "navigation.commandMenu.title"), e.copy(n.description, "navigation.commandMenu.description"), e.copy(n.keywords, "navigation.commandMenu.keywords");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function _(e, t) {
|
|
82
|
+
e.record(t, "pages") && (e.closed(t, [
|
|
83
|
+
"list",
|
|
84
|
+
"detail",
|
|
85
|
+
"edit"
|
|
86
|
+
], "pages"), e.record(t.list, "pages.list") && (e.closed(t.list, ["title", "subtitle"], "pages.list"), e.copy(t.list.title, "pages.list.title"), e.copy(t.list.subtitle, "pages.list.subtitle")), e.record(t.detail, "pages.detail") && (e.closed(t.detail, ["backLabel"], "pages.detail"), e.copy(t.detail.backLabel, "pages.detail.backLabel")), e.record(t.edit, "pages.edit") && (e.closed(t.edit, ["title"], "pages.edit"), e.copy(t.edit.title, "pages.edit.title")));
|
|
87
|
+
}
|
|
88
|
+
function v(e, t, n, r) {
|
|
89
|
+
if (!e.record(n, r)) return;
|
|
90
|
+
e.closed(n, [
|
|
91
|
+
"type",
|
|
92
|
+
"label",
|
|
93
|
+
"help",
|
|
94
|
+
"required",
|
|
95
|
+
"constraints"
|
|
96
|
+
], r);
|
|
97
|
+
let { type: i, label: a, help: o, required: s, constraints: c } = n;
|
|
98
|
+
if (i !== t.type && e.fail(`${r}.type`, `must be "${t.type}", the control this host renders`), e.copy(a, `${r}.label`), o !== void 0 && e.copy(o, `${r}.help`), s !== t.required && e.fail(`${r}.required`, `must be ${t.required}, what this host enforces`), c !== void 0) {
|
|
99
|
+
if (t.type !== "number") e.fail(`${r}.constraints`, "is only allowed on a number attribute");
|
|
100
|
+
else if (e.record(c, `${r}.constraints`)) {
|
|
101
|
+
e.closed(c, ["min", "max"], `${r}.constraints`);
|
|
102
|
+
let { min: t, max: n } = c;
|
|
103
|
+
t !== void 0 && t !== 1 && e.fail(`${r}.constraints.min`, "must be the 1 this host enforces"), n !== void 0 && (!Number.isInteger(n) || n < 1) && e.fail(`${r}.constraints.max`, "must be a positive integer");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function y(e, t) {
|
|
108
|
+
if (!e.record(t, "attributes")) return;
|
|
109
|
+
let n = Object.keys(t);
|
|
110
|
+
n.length === 0 && e.fail("attributes", "must declare at least one attribute"), n.forEach((n) => {
|
|
111
|
+
if (!u.includes(n)) {
|
|
112
|
+
e.fail(`attributes.${n}`, "is not a settable attribute");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
v(e, l[n], t[n], `attributes.${n}`);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function b(e, t) {
|
|
119
|
+
if (!e.record(t, "importExport")) return;
|
|
120
|
+
e.closed(t, [
|
|
121
|
+
"fileKind",
|
|
122
|
+
"fileVersion",
|
|
123
|
+
"filenameSuffix",
|
|
124
|
+
"importDefaults"
|
|
125
|
+
], "importExport");
|
|
126
|
+
let { fileKind: n, fileVersion: o, filenameSuffix: s, importDefaults: l } = t;
|
|
127
|
+
(typeof n != "string" || !r.test(n)) && e.fail("importExport.fileKind", "must be a lowercase slug"), o !== 1 && e.fail("importExport.fileVersion", "must be 1"), (typeof s != "string" || !i.test(s)) && e.fail("importExport.filenameSuffix", "must be a .json suffix"), e.record(l, "importExport.importDefaults") && (e.closed(l, ["repoProvider", "placeholderEventSource"], "importExport.importDefaults"), (typeof l.repoProvider != "string" || !c.includes(l.repoProvider)) && e.fail("importExport.importDefaults.repoProvider", "is not a supported provider"), (typeof l.placeholderEventSource != "string" || !a.test(l.placeholderEventSource)) && e.fail("importExport.importDefaults.placeholderEventSource", "must be a lowercase event source"));
|
|
128
|
+
}
|
|
129
|
+
function x(e, t) {
|
|
130
|
+
if (!e.record(t, "endpoints")) return;
|
|
131
|
+
let n = [...d, ...f];
|
|
132
|
+
e.closed(t, n, "endpoints");
|
|
133
|
+
let r = (n) => {
|
|
134
|
+
let r = t[n];
|
|
135
|
+
return typeof r != "string" || !o.test(r) || r.includes("//") ? (e.fail(`endpoints.${n}`, "must be a rooted service-relative path"), null) : r;
|
|
136
|
+
};
|
|
137
|
+
d.forEach((t) => {
|
|
138
|
+
let n = r(t);
|
|
139
|
+
n !== null && /[{}]/.test(n) && e.fail(`endpoints.${t}`, "must not carry a substitution");
|
|
140
|
+
}), f.forEach((t) => {
|
|
141
|
+
let n = r(t);
|
|
142
|
+
n !== null && !s.test(n) && e.fail(`endpoints.${t}`, "must carry exactly one {id}");
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function S(e, n, r) {
|
|
146
|
+
if (!Array.isArray(n) || n.length === 0) return e.fail(r, "must be a non-empty array"), [];
|
|
147
|
+
let i = n.filter((n) => typeof n == "string" && t.test(n) ? !0 : (e.fail(r, "must contain only lowercase slugs"), !1));
|
|
148
|
+
return new Set(i).size !== i.length && e.fail(r, "must not repeat an id"), i;
|
|
149
|
+
}
|
|
150
|
+
var C = [
|
|
151
|
+
"version",
|
|
152
|
+
"routes",
|
|
153
|
+
"navigation",
|
|
154
|
+
"pages",
|
|
155
|
+
"docsUrl",
|
|
156
|
+
"attributes",
|
|
157
|
+
"importExport",
|
|
158
|
+
"endpoints",
|
|
159
|
+
"featuredAutomationIds",
|
|
160
|
+
"responderIntegrationIds"
|
|
161
|
+
];
|
|
162
|
+
function w(e, t) {
|
|
163
|
+
if (!p(e)) return {
|
|
164
|
+
valid: !1,
|
|
165
|
+
errors: ["interface: must be an object"]
|
|
166
|
+
};
|
|
167
|
+
if (e.version !== "1.0") return {
|
|
168
|
+
valid: !1,
|
|
169
|
+
errors: ["interface.version: must be \"1.0\""]
|
|
170
|
+
};
|
|
171
|
+
let r = new m();
|
|
172
|
+
return r.closed(e, C, "interface"), h(r, e.routes, t.mountedRoutes), g(r, e.navigation), _(r, e.pages), (typeof e.docsUrl != "string" || !e.docsUrl.startsWith(n)) && r.fail("docsUrl", `must start with ${n}`), y(r, e.attributes), b(r, e.importExport), x(r, e.endpoints), S(r, e.featuredAutomationIds, "featuredAutomationIds").forEach((e) => {
|
|
173
|
+
t.catalogIds.has(e) || r.fail("featuredAutomationIds", `${e} is not a catalog entry`);
|
|
174
|
+
}), S(r, e.responderIntegrationIds, "responderIntegrationIds"), {
|
|
175
|
+
valid: r.errors.length === 0,
|
|
176
|
+
errors: r.errors
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
export { w as validateInterfaceManifest };
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=interface-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface-validation.js","names":[],"sources":["../../src/manifests/interface-validation.ts"],"sourcesContent":["/**\n * Admission policy for the extension-published Automation interface manifest.\n *\n * Like a setup entry, the interface manifest is data authored in a different\n * repository that instructs this host to render copy, build links, and address\n * requests, so the host decides what it is *permitted* to state. Admission is\n * all-or-nothing: one bad field rejects the whole manifest, and the host falls\n * back to its own defaults rather than rendering a partially-trusted mix.\n */\n\nimport type {\n AutomationAttributeName,\n InterfaceAttributeType,\n InterfaceRoutes,\n} from \"./types\";\nimport { INTERFACE_VERSION } from \"./types\";\n\n/** Copy must never be able to inject markup into the host. */\nconst MARKUP_PATTERN = /<[A-Za-z/!]/;\nconst SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n/** The one URL the manifest may state, pinned to the product documentation. */\nconst DOCS_URL_PREFIX = \"https://docs.openhands.dev/\";\nconst FILE_KIND_PATTERN = /^[a-z][a-z-]*$/;\nconst FILENAME_SUFFIX_PATTERN = /^\\.[a-z][a-z.]*json$/;\nconst EVENT_SOURCE_PATTERN = /^[a-z0-9][a-z0-9.-]*$/;\n/** Service-relative only: rooted, no traversal, no query, no fragment. */\nconst ENDPOINT_PATTERN = /^\\/[A-Za-z0-9/{}_-]*$/;\n/** Exactly one `{id}` substitution and no other braces. */\nconst ID_ENDPOINT_PATTERN = /^[^{}]*\\{id\\}[^{}]*$/;\n\nconst GIT_PROVIDERS = [\"github\", \"gitlab\", \"bitbucket\"] as const;\n/**\n * The attribute semantics this host's edit dialog implements: the control it\n * renders per property and the requiredness it enforces. Admission pins a\n * declared attribute to exactly these, so an admitted manifest can never\n * promise a control, a requiredness, or (below) a minimum the form would\n * silently ignore.\n */\nconst HOST_ATTRIBUTES: Record<\n AutomationAttributeName,\n { type: InterfaceAttributeType; required: boolean }\n> = {\n name: { type: \"text\", required: true },\n prompt: { type: \"textarea\", required: false },\n model: { type: \"llm-profile\", required: false },\n timeout: { type: \"number\", required: false },\n schedule: { type: \"schedule\", required: false },\n};\nconst ATTRIBUTE_NAMES = Object.keys(HOST_ATTRIBUTES);\nconst PLAIN_ENDPOINT_NAMES = [\n \"list\",\n \"health\",\n \"capabilities\",\n \"validate\",\n \"createPrompt\",\n \"createPlugin\",\n] as const;\nconst ID_ENDPOINT_NAMES = [\"detail\", \"dispatch\", \"runs\", \"tarball\"] as const;\n\nexport interface InterfaceValidationContext {\n /** Ids of the published automation catalog, for the featured-list check. */\n catalogIds: ReadonlySet<string>;\n /** The routes this host has registrations for. A manifest must match them. */\n mountedRoutes: InterfaceRoutes;\n}\n\nexport interface InterfaceValidationResult {\n valid: boolean;\n errors: string[];\n}\n\ntype Rec = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Rec {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nclass InterfaceChecker {\n readonly errors: string[] = [];\n\n fail(path: string, reason: string): false {\n this.errors.push(`${path}: ${reason}`);\n return false;\n }\n\n /** Literal user-visible copy. Carries no markup. */\n copy(value: unknown, path: string): boolean {\n if (typeof value !== \"string\" || value.length === 0) {\n return this.fail(path, \"must be a non-empty string\");\n }\n if (MARKUP_PATTERN.test(value)) {\n return this.fail(path, \"must not contain markup\");\n }\n return true;\n }\n\n /** A closed object: every present key must be an expected one. */\n closed(container: Rec, allowed: readonly string[], path: string): void {\n Object.keys(container)\n .filter((key) => !allowed.includes(key))\n .forEach((key) => this.fail(`${path}.${key}`, \"is not allowed\"));\n }\n\n record(value: unknown, path: string): value is Rec {\n if (isRecord(value)) return true;\n this.fail(path, \"must be an object\");\n return false;\n }\n}\n\nfunction checkRoutes(\n check: InterfaceChecker,\n routes: unknown,\n mounted: InterfaceRoutes,\n): void {\n if (!check.record(routes, \"routes\")) return;\n check.closed(routes, [\"list\", \"setup\", \"detail\"], \"routes\");\n\n // The host serves what it has registrations for, so a declared route must be\n // exactly the mounted shape — the manifest owns link construction, not the\n // router table.\n ([\"list\", \"setup\", \"detail\"] as const).forEach((name) => {\n if (routes[name] !== mounted[name]) {\n check.fail(`routes.${name}`, `must be \"${mounted[name]}\"`);\n }\n });\n}\n\nfunction checkNavigation(check: InterfaceChecker, navigation: unknown): void {\n if (!check.record(navigation, \"navigation\")) return;\n check.closed(navigation, [\"sidebar\", \"commandMenu\"], \"navigation\");\n\n if (check.record(navigation.sidebar, \"navigation.sidebar\")) {\n check.closed(navigation.sidebar, [\"label\"], \"navigation.sidebar\");\n check.copy(navigation.sidebar.label, \"navigation.sidebar.label\");\n }\n if (check.record(navigation.commandMenu, \"navigation.commandMenu\")) {\n const menu = navigation.commandMenu;\n check.closed(\n menu,\n [\"title\", \"description\", \"keywords\"],\n \"navigation.commandMenu\",\n );\n check.copy(menu.title, \"navigation.commandMenu.title\");\n check.copy(menu.description, \"navigation.commandMenu.description\");\n check.copy(menu.keywords, \"navigation.commandMenu.keywords\");\n }\n}\n\nfunction checkPages(check: InterfaceChecker, pages: unknown): void {\n if (!check.record(pages, \"pages\")) return;\n check.closed(pages, [\"list\", \"detail\", \"edit\"], \"pages\");\n\n if (check.record(pages.list, \"pages.list\")) {\n check.closed(pages.list, [\"title\", \"subtitle\"], \"pages.list\");\n check.copy(pages.list.title, \"pages.list.title\");\n check.copy(pages.list.subtitle, \"pages.list.subtitle\");\n }\n if (check.record(pages.detail, \"pages.detail\")) {\n check.closed(pages.detail, [\"backLabel\"], \"pages.detail\");\n check.copy(pages.detail.backLabel, \"pages.detail.backLabel\");\n }\n if (check.record(pages.edit, \"pages.edit\")) {\n check.closed(pages.edit, [\"title\"], \"pages.edit\");\n check.copy(pages.edit.title, \"pages.edit.title\");\n }\n}\n\nfunction checkAttribute(\n check: InterfaceChecker,\n host: { type: InterfaceAttributeType; required: boolean },\n attribute: unknown,\n path: string,\n): void {\n if (!check.record(attribute, path)) return;\n check.closed(\n attribute,\n [\"type\", \"label\", \"help\", \"required\", \"constraints\"],\n path,\n );\n\n const { type, label, help, required, constraints } = attribute;\n if (type !== host.type) {\n check.fail(\n `${path}.type`,\n `must be \"${host.type}\", the control this host renders`,\n );\n }\n check.copy(label, `${path}.label`);\n if (help !== undefined) check.copy(help, `${path}.help`);\n if (required !== host.required) {\n check.fail(\n `${path}.required`,\n `must be ${host.required}, what this host enforces`,\n );\n }\n\n if (constraints !== undefined) {\n if (host.type !== \"number\") {\n check.fail(\n `${path}.constraints`,\n \"is only allowed on a number attribute\",\n );\n } else if (check.record(constraints, `${path}.constraints`)) {\n check.closed(constraints, [\"min\", \"max\"], `${path}.constraints`);\n const { min, max } = constraints;\n // The form validates a positive integer, i.e. an effective minimum of 1;\n // any other declared minimum would be a promise it does not keep.\n if (min !== undefined && min !== 1) {\n check.fail(\n `${path}.constraints.min`,\n \"must be the 1 this host enforces\",\n );\n }\n if (\n max !== undefined &&\n (!Number.isInteger(max) || (max as number) < 1)\n ) {\n check.fail(`${path}.constraints.max`, \"must be a positive integer\");\n }\n }\n }\n}\n\nfunction checkAttributes(check: InterfaceChecker, attributes: unknown): void {\n if (!check.record(attributes, \"attributes\")) return;\n const names = Object.keys(attributes);\n if (names.length === 0) {\n check.fail(\"attributes\", \"must declare at least one attribute\");\n }\n names.forEach((name) => {\n if (!ATTRIBUTE_NAMES.includes(name)) {\n check.fail(`attributes.${name}`, \"is not a settable attribute\");\n return;\n }\n checkAttribute(\n check,\n HOST_ATTRIBUTES[name as AutomationAttributeName],\n attributes[name],\n `attributes.${name}`,\n );\n });\n}\n\nfunction checkImportExport(\n check: InterfaceChecker,\n importExport: unknown,\n): void {\n if (!check.record(importExport, \"importExport\")) return;\n check.closed(\n importExport,\n [\"fileKind\", \"fileVersion\", \"filenameSuffix\", \"importDefaults\"],\n \"importExport\",\n );\n\n const { fileKind, fileVersion, filenameSuffix, importDefaults } =\n importExport;\n if (typeof fileKind !== \"string\" || !FILE_KIND_PATTERN.test(fileKind)) {\n check.fail(\"importExport.fileKind\", \"must be a lowercase slug\");\n }\n if (fileVersion !== 1) {\n check.fail(\"importExport.fileVersion\", \"must be 1\");\n }\n if (\n typeof filenameSuffix !== \"string\" ||\n !FILENAME_SUFFIX_PATTERN.test(filenameSuffix)\n ) {\n check.fail(\"importExport.filenameSuffix\", \"must be a .json suffix\");\n }\n if (check.record(importDefaults, \"importExport.importDefaults\")) {\n check.closed(\n importDefaults,\n [\"repoProvider\", \"placeholderEventSource\"],\n \"importExport.importDefaults\",\n );\n if (\n typeof importDefaults.repoProvider !== \"string\" ||\n !(GIT_PROVIDERS as readonly string[]).includes(\n importDefaults.repoProvider,\n )\n ) {\n check.fail(\n \"importExport.importDefaults.repoProvider\",\n \"is not a supported provider\",\n );\n }\n if (\n typeof importDefaults.placeholderEventSource !== \"string\" ||\n !EVENT_SOURCE_PATTERN.test(importDefaults.placeholderEventSource)\n ) {\n check.fail(\n \"importExport.importDefaults.placeholderEventSource\",\n \"must be a lowercase event source\",\n );\n }\n }\n}\n\nfunction checkEndpoints(check: InterfaceChecker, endpoints: unknown): void {\n if (!check.record(endpoints, \"endpoints\")) return;\n const allowed = [...PLAIN_ENDPOINT_NAMES, ...ID_ENDPOINT_NAMES];\n check.closed(endpoints, allowed, \"endpoints\");\n\n const endpointAt = (name: string): string | null => {\n const value = endpoints[name];\n if (\n typeof value !== \"string\" ||\n !ENDPOINT_PATTERN.test(value) ||\n value.includes(\"//\")\n ) {\n check.fail(`endpoints.${name}`, \"must be a rooted service-relative path\");\n return null;\n }\n return value;\n };\n\n PLAIN_ENDPOINT_NAMES.forEach((name) => {\n const value = endpointAt(name);\n if (value !== null && /[{}]/.test(value)) {\n check.fail(`endpoints.${name}`, \"must not carry a substitution\");\n }\n });\n ID_ENDPOINT_NAMES.forEach((name) => {\n const value = endpointAt(name);\n if (value !== null && !ID_ENDPOINT_PATTERN.test(value)) {\n check.fail(`endpoints.${name}`, \"must carry exactly one {id}\");\n }\n });\n}\n\nfunction checkSlugList(\n check: InterfaceChecker,\n value: unknown,\n path: string,\n): string[] {\n if (!Array.isArray(value) || value.length === 0) {\n check.fail(path, \"must be a non-empty array\");\n return [];\n }\n const slugs = value.filter((item): item is string => {\n if (typeof item === \"string\" && SLUG_PATTERN.test(item)) return true;\n check.fail(path, \"must contain only lowercase slugs\");\n return false;\n });\n if (new Set(slugs).size !== slugs.length) {\n check.fail(path, \"must not repeat an id\");\n }\n return slugs;\n}\n\nconst TOP_LEVEL_KEYS = [\n \"version\",\n \"routes\",\n \"navigation\",\n \"pages\",\n \"docsUrl\",\n \"attributes\",\n \"importExport\",\n \"endpoints\",\n \"featuredAutomationIds\",\n \"responderIntegrationIds\",\n];\n\n/**\n * Decide whether this host will act on a published interface manifest.\n *\n * The version is checked first and fails closed: a format this host does not\n * recognise is refused rather than interpreted with today's rules.\n */\nexport function validateInterfaceManifest(\n candidate: unknown,\n context: InterfaceValidationContext,\n): InterfaceValidationResult {\n if (!isRecord(candidate)) {\n return { valid: false, errors: [\"interface: must be an object\"] };\n }\n if (candidate.version !== INTERFACE_VERSION) {\n return {\n valid: false,\n errors: [`interface.version: must be \"${INTERFACE_VERSION}\"`],\n };\n }\n\n const check = new InterfaceChecker();\n check.closed(candidate, TOP_LEVEL_KEYS, \"interface\");\n\n checkRoutes(check, candidate.routes, context.mountedRoutes);\n checkNavigation(check, candidate.navigation);\n checkPages(check, candidate.pages);\n if (\n typeof candidate.docsUrl !== \"string\" ||\n !candidate.docsUrl.startsWith(DOCS_URL_PREFIX)\n ) {\n check.fail(\"docsUrl\", `must start with ${DOCS_URL_PREFIX}`);\n }\n checkAttributes(check, candidate.attributes);\n checkImportExport(check, candidate.importExport);\n checkEndpoints(check, candidate.endpoints);\n\n checkSlugList(\n check,\n candidate.featuredAutomationIds,\n \"featuredAutomationIds\",\n ).forEach((id) => {\n if (!context.catalogIds.has(id)) {\n check.fail(\"featuredAutomationIds\", `${id} is not a catalog entry`);\n }\n });\n checkSlugList(\n check,\n candidate.responderIntegrationIds,\n \"responderIntegrationIds\",\n );\n\n return { valid: check.errors.length === 0, errors: check.errors };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The action bridge — the only channel through which a manifest can make this
|
|
3
|
+
* host *do* something.
|
|
4
|
+
*
|
|
5
|
+
* A manifest is data from another repository, so it never describes a request.
|
|
6
|
+
* It chooses between the two outcomes this host offers, and it chooses by
|
|
7
|
+
* declaring a `mode`: a direct entry produces a create request the host derives,
|
|
8
|
+
* an assisted entry hands setup to a conversation.
|
|
9
|
+
*/
|
|
10
|
+
import type { SetupEntry, SetupFormValues, SetupRequestBody } from "./types";
|
|
11
|
+
export interface SetupActionResult {
|
|
12
|
+
/** The created resource, or the conversation that will finish setup. */
|
|
13
|
+
response: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export declare function useSetupAction(): (entry: SetupEntry, values: SetupFormValues, payload: SetupRequestBody | null) => Promise<SetupActionResult>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 2 — decide whether a deployment can run what a manifest requires.
|
|
3
|
+
*
|
|
4
|
+
* The manifest states what it needs — the features under `requires.features`,
|
|
5
|
+
* and, implicitly, the trigger kinds its form declares. The deployment states
|
|
6
|
+
* what it supports. Neither side is interpreted here beyond set membership, so
|
|
7
|
+
* this stays neutral about what any particular capability means.
|
|
8
|
+
*/
|
|
9
|
+
import type { DeploymentCapabilities, SetupEntry } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* "unknown" is a real outcome, not an error: a deployment that cannot be asked
|
|
12
|
+
* must not be treated as one that answered no.
|
|
13
|
+
*/
|
|
14
|
+
export type SetupCapabilitySupport = boolean | "unknown";
|
|
15
|
+
export interface SetupCapabilityAssessment {
|
|
16
|
+
supported: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Requirement names the deployment did not report, so a block can say which
|
|
19
|
+
* ones rather than only that there were some. Empty when a deployment that
|
|
20
|
+
* reports it is not accepting work blocks the entry, because then no single
|
|
21
|
+
* requirement is the reason.
|
|
22
|
+
*/
|
|
23
|
+
unmet: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare function assessCapabilityRequirements(entry: SetupEntry, reported: DeploymentCapabilities): SetupCapabilityAssessment;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate service-reported errors back to the form field that produced them.
|
|
3
|
+
*
|
|
4
|
+
* The host validates and submits the *derived payload*, so errors come back
|
|
5
|
+
* addressed by payload path (`trigger.schedule`) rather than by form field
|
|
6
|
+
* (`schedule`). The reverse lookup is derived from the same builder that made
|
|
7
|
+
* the payload; the mapping is lossy by nature, since one payload value can be
|
|
8
|
+
* built from several fields.
|
|
9
|
+
*/
|
|
10
|
+
import type { SetupRequestBody } from "./types";
|
|
11
|
+
/** An error the service reported, addressed by payload path where it gave one. */
|
|
12
|
+
export interface ManifestServiceError {
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
}
|
|
16
|
+
export interface MappedManifestErrors {
|
|
17
|
+
/** Keyed by form field name. */
|
|
18
|
+
fieldErrors: Record<string, string>;
|
|
19
|
+
/** Errors with no field to attach to; shown against the form as a whole. */
|
|
20
|
+
formErrors: string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Turn a service `loc` array into a path into the payload actually sent.
|
|
24
|
+
*
|
|
25
|
+
* A validation framework may address a value through segments that are not keys
|
|
26
|
+
* of the request body — a discriminated union reports
|
|
27
|
+
* `["body","trigger","cron","schedule"]` for a body whose trigger has no `cron`
|
|
28
|
+
* key. Walking the payload and skipping segments that do not resolve reduces
|
|
29
|
+
* that to `trigger.schedule` without knowing anything about the payload's
|
|
30
|
+
* meaning.
|
|
31
|
+
*/
|
|
32
|
+
export declare function locToPayloadPath(loc: readonly (string | number)[], payload: unknown): string;
|
|
33
|
+
/**
|
|
34
|
+
* Read errors out of a service response body, whichever of the two shapes it
|
|
35
|
+
* uses: a preflight result keyed by field, or a validation failure keyed by
|
|
36
|
+
* `loc`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeServiceErrors(body: unknown, payload: SetupRequestBody | null): ManifestServiceError[];
|
|
39
|
+
/** Apply the derived payload-path map, falling back to a form-level error. */
|
|
40
|
+
export declare function mapServiceErrors(errors: readonly ManifestServiceError[], errorMap: Record<string, string[]>): MappedManifestErrors;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The form model, and the host's own check of what the user typed into it.
|
|
3
|
+
*
|
|
4
|
+
* Local validation is a convenience, not the authority: it is instant and needs
|
|
5
|
+
* no round trip, so it catches empty required fields and obvious typos.
|
|
6
|
+
* Deployment-specific questions ("is a one-minute schedule allowed here?")
|
|
7
|
+
* belong to preflight, which is authoritative.
|
|
8
|
+
*
|
|
9
|
+
* Errors are returned as codes rather than sentences so the host can render
|
|
10
|
+
* them through its own translations; only manifest-authored copy is literal.
|
|
11
|
+
*/
|
|
12
|
+
import type { DeploymentCapabilities, SetupBlock, SetupFieldOption, SetupFormField, SetupFormFields, SetupFormValues } from "./types";
|
|
13
|
+
export type SetupFieldError = {
|
|
14
|
+
code: "required";
|
|
15
|
+
} | {
|
|
16
|
+
code: "minLength";
|
|
17
|
+
length: number;
|
|
18
|
+
} | {
|
|
19
|
+
code: "maxLength";
|
|
20
|
+
length: number;
|
|
21
|
+
} | {
|
|
22
|
+
code: "invalidOption";
|
|
23
|
+
} | {
|
|
24
|
+
code: "unsafeExpressionLiteral";
|
|
25
|
+
};
|
|
26
|
+
export type SetupFieldErrors = Record<string, SetupFieldError>;
|
|
27
|
+
/** Field constraints supplied by the deployment rather than by the manifest. */
|
|
28
|
+
export interface SetupFieldOverride {
|
|
29
|
+
options?: SetupFieldOption[];
|
|
30
|
+
}
|
|
31
|
+
export type SetupFieldOverrides = Record<string, SetupFieldOverride>;
|
|
32
|
+
/**
|
|
33
|
+
* Every input the form declares, keyed by name, whichever half it is in.
|
|
34
|
+
*
|
|
35
|
+
* Trigger inputs come first so the user is asked when it runs before what it
|
|
36
|
+
* runs on, and so every derived view of the form keeps that order. Admission
|
|
37
|
+
* rejects a name declared in both halves, so the merge cannot lose a field.
|
|
38
|
+
*/
|
|
39
|
+
export declare function collectFields(setup: SetupBlock): SetupFormFields;
|
|
40
|
+
/**
|
|
41
|
+
* Feed deployment values into form field constraints, so the form offers only
|
|
42
|
+
* what the deployment accepts.
|
|
43
|
+
*
|
|
44
|
+
* A `timezone` field is the case that needs it: a manifest declares no options
|
|
45
|
+
* for one, because the accepted zones belong to the deployment. The cron
|
|
46
|
+
* interval floor is deliberately left to preflight — the deployment owns that
|
|
47
|
+
* limit and states it in its own words, and a local approximation would
|
|
48
|
+
* pre-empt the authoritative message with a worse one.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveFieldOverrides(setup: SetupBlock, capabilities: DeploymentCapabilities | null): SetupFieldOverrides;
|
|
51
|
+
/** The options a field offers, after deployment constraints are applied. */
|
|
52
|
+
export declare function getFieldOptions(name: string, field: SetupFormField, overrides?: SetupFieldOverrides): SetupFieldOption[];
|
|
53
|
+
/** Initial form state: every declared field, seeded with its declared default. */
|
|
54
|
+
export declare function getInitialFormValues(setup: SetupBlock): SetupFormValues;
|
|
55
|
+
/** Check every declared field. Returns only the fields that failed. */
|
|
56
|
+
export declare function validateFormValues(setup: SetupBlock, values: SetupFormValues, overrides?: SetupFieldOverrides): SetupFieldErrors;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");const e=require("./manifest-validation.cjs");function t(t){let n=[],r=new Map;return t.forEach(t=>{if(!e.hasSetupBlock(t))return;let{valid:i,errors:a}=e.validateSetupEntry(t);if(!i){console.warn(`Rejected a setup manifest:`,a.join(`; `));return}let o=t;if(r.has(o.id)){console.warn(`Rejected a setup manifest: id "${o.id}" is already registered`);return}n.push(o),r.set(o.id,o)}),{entries:n,findById:e=>r.get(e)??null}}exports.createSetupRegistry=t;
|
|
2
|
+
//# sourceMappingURL=manifest-registry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-registry.cjs","names":[],"sources":["../../src/manifests/manifest-registry.ts"],"sourcesContent":["/**\n * Registry of admitted setup manifests.\n *\n * Stage 1 of the setup flow: load the catalog, decide which entries this host\n * will act on, and index the survivors by id. An entry that fails admission is\n * dropped entirely rather than rendered partially, because everything\n * downstream treats its content as instructions.\n */\n\nimport { hasSetupBlock, validateSetupEntry } from \"./manifest-validation\";\nimport type { SetupEntry } from \"./types\";\n\nexport interface SetupRegistry {\n /** Entries this host has admitted, in source order. */\n readonly entries: readonly SetupEntry[];\n findById(id: string): SetupEntry | null;\n}\n\nexport function createSetupRegistry(\n candidates: readonly unknown[],\n): SetupRegistry {\n const entries: SetupEntry[] = [];\n const byId = new Map<string, SetupEntry>();\n\n candidates.forEach((candidate) => {\n // A catalog entry without a setup block is a card, not a setup experience.\n // That is the normal case, so it is skipped rather than reported.\n if (!hasSetupBlock(candidate)) return;\n\n const { valid, errors } = validateSetupEntry(candidate);\n if (!valid) {\n console.warn(\"Rejected a setup manifest:\", errors.join(\"; \"));\n return;\n }\n\n const entry = candidate as SetupEntry;\n if (byId.has(entry.id)) {\n console.warn(\n `Rejected a setup manifest: id \"${entry.id}\" is already registered`,\n );\n return;\n }\n\n entries.push(entry);\n byId.set(entry.id, entry);\n });\n\n return {\n entries,\n findById: (id) => byId.get(id) ?? null,\n };\n}\n"],"mappings":"0FAkBA,SAAgB,EACd,EACe,CACf,IAAM,EAAwB,CAAC,EACzB,EAAO,IAAI,IAyBjB,OAvBA,EAAW,QAAS,GAAc,CAGhC,GAAI,CAAC,EAAA,cAAc,CAAS,EAAG,OAE/B,GAAM,CAAE,QAAO,UAAW,EAAA,mBAAmB,CAAS,EACtD,GAAI,CAAC,EAAO,CACV,QAAQ,KAAK,6BAA8B,EAAO,KAAK,IAAI,CAAC,EAC5D,MACF,CAEA,IAAM,EAAQ,EACd,GAAI,EAAK,IAAI,EAAM,EAAE,EAAG,CACtB,QAAQ,KACN,kCAAkC,EAAM,GAAG,wBAC7C,EACA,MACF,CAEA,EAAQ,KAAK,CAAK,EAClB,EAAK,IAAI,EAAM,GAAI,CAAK,CAC1B,CAAC,EAEM,CACL,UACA,SAAW,GAAO,EAAK,IAAI,CAAE,GAAK,IACpC,CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry of admitted setup manifests.
|
|
3
|
+
*
|
|
4
|
+
* Stage 1 of the setup flow: load the catalog, decide which entries this host
|
|
5
|
+
* will act on, and index the survivors by id. An entry that fails admission is
|
|
6
|
+
* dropped entirely rather than rendered partially, because everything
|
|
7
|
+
* downstream treats its content as instructions.
|
|
8
|
+
*/
|
|
9
|
+
import type { SetupEntry } from "./types";
|
|
10
|
+
export interface SetupRegistry {
|
|
11
|
+
/** Entries this host has admitted, in source order. */
|
|
12
|
+
readonly entries: readonly SetupEntry[];
|
|
13
|
+
findById(id: string): SetupEntry | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function createSetupRegistry(candidates: readonly unknown[]): SetupRegistry;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { hasSetupBlock as e, validateSetupEntry as t } from "./manifest-validation.js";
|
|
2
|
+
//#region src/manifests/manifest-registry.ts
|
|
3
|
+
function n(n) {
|
|
4
|
+
let r = [], i = /* @__PURE__ */ new Map();
|
|
5
|
+
return n.forEach((n) => {
|
|
6
|
+
if (!e(n)) return;
|
|
7
|
+
let { valid: a, errors: o } = t(n);
|
|
8
|
+
if (!a) {
|
|
9
|
+
console.warn("Rejected a setup manifest:", o.join("; "));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
let s = n;
|
|
13
|
+
if (i.has(s.id)) {
|
|
14
|
+
console.warn(`Rejected a setup manifest: id "${s.id}" is already registered`);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
r.push(s), i.set(s.id, s);
|
|
18
|
+
}), {
|
|
19
|
+
entries: r,
|
|
20
|
+
findById: (e) => i.get(e) ?? null
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { n as createSetupRegistry };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=manifest-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-registry.js","names":[],"sources":["../../src/manifests/manifest-registry.ts"],"sourcesContent":["/**\n * Registry of admitted setup manifests.\n *\n * Stage 1 of the setup flow: load the catalog, decide which entries this host\n * will act on, and index the survivors by id. An entry that fails admission is\n * dropped entirely rather than rendered partially, because everything\n * downstream treats its content as instructions.\n */\n\nimport { hasSetupBlock, validateSetupEntry } from \"./manifest-validation\";\nimport type { SetupEntry } from \"./types\";\n\nexport interface SetupRegistry {\n /** Entries this host has admitted, in source order. */\n readonly entries: readonly SetupEntry[];\n findById(id: string): SetupEntry | null;\n}\n\nexport function createSetupRegistry(\n candidates: readonly unknown[],\n): SetupRegistry {\n const entries: SetupEntry[] = [];\n const byId = new Map<string, SetupEntry>();\n\n candidates.forEach((candidate) => {\n // A catalog entry without a setup block is a card, not a setup experience.\n // That is the normal case, so it is skipped rather than reported.\n if (!hasSetupBlock(candidate)) return;\n\n const { valid, errors } = validateSetupEntry(candidate);\n if (!valid) {\n console.warn(\"Rejected a setup manifest:\", errors.join(\"; \"));\n return;\n }\n\n const entry = candidate as SetupEntry;\n if (byId.has(entry.id)) {\n console.warn(\n `Rejected a setup manifest: id \"${entry.id}\" is already registered`,\n );\n return;\n }\n\n entries.push(entry);\n byId.set(entry.id, entry);\n });\n\n return {\n entries,\n findById: (id) => byId.get(id) ?? null,\n };\n}\n"],"mappings":";;AAkBA,SAAgB,EACd,GACe;CACf,IAAM,IAAwB,CAAC,GACzB,oBAAO,IAAI,IAAwB;CAyBzC,OAvBA,EAAW,SAAS,MAAc;EAGhC,IAAI,CAAC,EAAc,CAAS,GAAG;EAE/B,IAAM,EAAE,UAAO,cAAW,EAAmB,CAAS;EACtD,IAAI,CAAC,GAAO;GACV,QAAQ,KAAK,8BAA8B,EAAO,KAAK,IAAI,CAAC;GAC5D;EACF;EAEA,IAAM,IAAQ;EACd,IAAI,EAAK,IAAI,EAAM,EAAE,GAAG;GACtB,QAAQ,KACN,kCAAkC,EAAM,GAAG,wBAC7C;GACA;EACF;EAGA,AADA,EAAQ,KAAK,CAAK,GAClB,EAAK,IAAI,EAAM,IAAI,CAAK;CAC1B,CAAC,GAEM;EACL;EACA,WAAW,MAAO,EAAK,IAAI,CAAE,KAAK;CACpC;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");const e=require("../node_modules/@openhands/extensions/automations/index.cjs");require("./manifest-registry.cjs").createSetupRegistry(e.default);var t=e.automations_exports,n=`AUTOMATION_INTERFACE`in t?t.AUTOMATION_INTERFACE:void 0;exports.AUTOMATION_INTERFACE_CANDIDATE=n;
|
|
2
|
+
//# sourceMappingURL=manifest-sources.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-sources.cjs","names":[],"sources":["../../src/manifests/manifest-sources.ts"],"sourcesContent":["/**\n * The one place that decides which manifests this host is offered.\n *\n * Setup manifests are published by `@openhands/extensions` as an optional\n * `setup` block on a catalog entry, so the catalog is the whole source. Entries\n * without one are skipped, which means the pinned package deciding to ship them\n * is the only step left — there is no wiring to add here.\n *\n * The catalog is passed as `unknown[]` on purpose: admission is a trust\n * boundary, so the host validates the published data rather than trusting the\n * types that shipped beside it.\n */\n\nimport * as automationsModule from \"@openhands/extensions/automations\";\nimport { AUTOMATION_CATALOG } from \"@openhands/extensions/automations\";\nimport { createSetupRegistry, type SetupRegistry } from \"./manifest-registry\";\n\nexport const SETUP_REGISTRY: SetupRegistry = createSetupRegistry(\n AUTOMATION_CATALOG as readonly unknown[],\n);\n\n/**\n * The interface manifest the pinned package publishes, if any. It is read off\n * the module namespace so a package that predates the export yields\n * `undefined` rather than a build error; admission in\n * `automation-interface.ts` decides what to do with it.\n */\nconst automationsExports: object = automationsModule;\nexport const AUTOMATION_INTERFACE_CANDIDATE: unknown =\n \"AUTOMATION_INTERFACE\" in automationsExports\n ? automationsExports.AUTOMATION_INTERFACE\n : undefined;\n"],"mappings":"6JAiB6C,EAAA,oBAC3C,EAAA,OACF,EAQA,IAAM,EAA6B,EAAA,oBACtB,EACX,yBAA0B,EACtB,EAAmB,qBACnB,IAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place that decides which manifests this host is offered.
|
|
3
|
+
*
|
|
4
|
+
* Setup manifests are published by `@openhands/extensions` as an optional
|
|
5
|
+
* `setup` block on a catalog entry, so the catalog is the whole source. Entries
|
|
6
|
+
* without one are skipped, which means the pinned package deciding to ship them
|
|
7
|
+
* is the only step left — there is no wiring to add here.
|
|
8
|
+
*
|
|
9
|
+
* The catalog is passed as `unknown[]` on purpose: admission is a trust
|
|
10
|
+
* boundary, so the host validates the published data rather than trusting the
|
|
11
|
+
* types that shipped beside it.
|
|
12
|
+
*/
|
|
13
|
+
import { type SetupRegistry } from "./manifest-registry";
|
|
14
|
+
export declare const SETUP_REGISTRY: SetupRegistry;
|
|
15
|
+
export declare const AUTOMATION_INTERFACE_CANDIDATE: unknown;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import e, { automations_exports as t } from "../node_modules/@openhands/extensions/automations/index.js";
|
|
2
|
+
import { createSetupRegistry as n } from "./manifest-registry.js";
|
|
3
|
+
n(e);
|
|
4
|
+
var r = t, i = "AUTOMATION_INTERFACE" in r ? r.AUTOMATION_INTERFACE : void 0;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { i as AUTOMATION_INTERFACE_CANDIDATE };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=manifest-sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-sources.js","names":[],"sources":["../../src/manifests/manifest-sources.ts"],"sourcesContent":["/**\n * The one place that decides which manifests this host is offered.\n *\n * Setup manifests are published by `@openhands/extensions` as an optional\n * `setup` block on a catalog entry, so the catalog is the whole source. Entries\n * without one are skipped, which means the pinned package deciding to ship them\n * is the only step left — there is no wiring to add here.\n *\n * The catalog is passed as `unknown[]` on purpose: admission is a trust\n * boundary, so the host validates the published data rather than trusting the\n * types that shipped beside it.\n */\n\nimport * as automationsModule from \"@openhands/extensions/automations\";\nimport { AUTOMATION_CATALOG } from \"@openhands/extensions/automations\";\nimport { createSetupRegistry, type SetupRegistry } from \"./manifest-registry\";\n\nexport const SETUP_REGISTRY: SetupRegistry = createSetupRegistry(\n AUTOMATION_CATALOG as readonly unknown[],\n);\n\n/**\n * The interface manifest the pinned package publishes, if any. It is read off\n * the module namespace so a package that predates the export yields\n * `undefined` rather than a build error; admission in\n * `automation-interface.ts` decides what to do with it.\n */\nconst automationsExports: object = automationsModule;\nexport const AUTOMATION_INTERFACE_CANDIDATE: unknown =\n \"AUTOMATION_INTERFACE\" in automationsExports\n ? automationsExports.AUTOMATION_INTERFACE\n : undefined;\n"],"mappings":";;AAiB6C,EAC3C,CACF;AAQA,IAAM,IAA6B,GACtB,IACX,0BAA0B,IACtB,EAAmB,uBACnB,KAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placeholder interpolation for setup copy and request-body strings.
|
|
3
|
+
*
|
|
4
|
+
* A setup block declares what the user sees and the two request strings the
|
|
5
|
+
* host cannot derive as templates over a small set of namespaces. Interpolation
|
|
6
|
+
* is plain substitution — there is no expression language, so a setup block
|
|
7
|
+
* cannot express behavior here.
|
|
8
|
+
*/
|
|
9
|
+
import type { SetupEntry, SetupFormValues } from "./types";
|
|
10
|
+
export interface SetupScope {
|
|
11
|
+
form?: SetupFormValues;
|
|
12
|
+
/** The catalog entry the setup block belongs to. */
|
|
13
|
+
automation?: SetupEntry;
|
|
14
|
+
}
|
|
15
|
+
/** Walk a dotted path through plain objects. */
|
|
16
|
+
export declare function getByPath(source: unknown, path: string): unknown;
|
|
17
|
+
/** Substitute placeholders inside a template string. */
|
|
18
|
+
export declare function interpolateText(template: string, scope: SetupScope): string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");const e=require("./types.cjs");var t=/^[a-z0-9]+(-[a-z0-9]+)*$/,n=/^[a-z][A-Za-z0-9]*$/,r=/<[A-Za-z/!]/,i=RegExp(`\\{\\{(?!(?:${e.SETUP_PLACEHOLDER_NAMESPACES.join(`|`)})\\.[A-Za-z0-9_.]+\\}\\})`),a=[`direct`,`assisted`],o=[`text`,`textarea`,`select`,`cron`,`timezone`,`repo-picker`],s=[`github`,`gitlab`,`bitbucket`],c=[`cron`,`event`],l=[`safeExpressionLiteral`],u=2e3;function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function f(e,t){return typeof e==`string`&&t.includes(e)}function p(e,t){return typeof e==`number`&&Number.isInteger(e)&&e>=t}var m=class{errors=[];fail(e,t){return this.errors.push(`${e}: ${t}`),!1}copy(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):r.test(e)?this.fail(t,`must not contain markup`):!0}placeholders(e,t){return i.test(e)?this.fail(t,`uses an unknown placeholder namespace`):!0}templateCopy(e,t){return this.copy(e,t)&&this.placeholders(e,t)}templateValue(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):this.placeholders(e,t)}absent(e,t,n,r){return t in e?this.fail(`${n}.${t}`,r):!0}};function h(e,t){if(!d(t)){e.fail(`requires`,`must be an object`);return}let{integrations:n,features:r}=t;!d(n)||Object.keys(n).length===0?e.fail(`requires.integrations`,`must be a non-empty object`):Object.entries(n).forEach(([t,n])=>{let r=`requires.integrations.${t}`;if(!d(n)){e.fail(r,`must be an object`);return}e.copy(n.message,`${r}.message`),`required`in n&&n.required!==!1&&e.fail(`${r}.required`,`may only be false`);let i=[`message`,`required`];Object.keys(n).filter(e=>!i.includes(e)).forEach(t=>e.fail(`${r}.${t}`,`is not allowed`))}),r!==void 0&&(!Array.isArray(r)||r.length===0?e.fail(`requires.features`,`must be a non-empty array`):r.forEach((t,n)=>{(typeof t!=`string`||t.length===0)&&e.fail(`requires.features[${n}]`,`must be a non-empty string`)}))}function g(e,t,n){if(!d(t)||Object.keys(t).length===0){e.fail(n,`must be a non-empty object`);return}let{minLength:r,maxLength:i,format:a}=t;r!==void 0&&!p(r,0)&&e.fail(`${n}.minLength`,`must be a non-negative integer`),i!==void 0&&!p(i,1)&&e.fail(`${n}.maxLength`,`must be a positive integer`),a!==void 0&&!f(a,l)&&e.fail(`${n}.format`,`is not a supported format`)}function _(e,t,n){if(!d(t)){e.fail(n,`must be an object`);return}let{type:r,label:i,help:a,placeholder:c,required:l,provider:u,options:p}=t;f(r,o)||e.fail(`${n}.type`,`is not a supported field type`),e.copy(i,`${n}.label`),e.copy(a,`${n}.help`),c!==void 0&&e.copy(c,`${n}.placeholder`),t.default!==void 0&&typeof t.default!=`string`&&e.fail(`${n}.default`,`must be a string`),typeof l!=`boolean`&&e.fail(`${n}.required`,`must be a boolean`),u!==void 0&&!f(u,s)&&e.fail(`${n}.provider`,`is not a supported provider`),r===`repo-picker`&&u===void 0&&e.fail(`${n}.provider`,`is required for a repository field`),p!==void 0&&(r===`select`?!Array.isArray(p)||p.length===0?e.fail(`${n}.options`,`must be a non-empty array`):p.forEach((t,r)=>{let i=`${n}.options[${r}]`;if(!d(t)){e.fail(i,`must be an object`);return}(typeof t.value!=`string`||t.value.length===0)&&e.fail(`${i}.value`,`must be a non-empty string`),e.copy(t.label,`${i}.label`)}):e.fail(`${n}.options`,`is only allowed on a select field`)),t.constraints!==void 0&&g(e,t.constraints,`${n}.constraints`)}function v(e,t,r){return!d(t)||Object.keys(t).length===0?(e.fail(r,`must be a non-empty object`),[]):Object.entries(t).map(([t,i])=>(n.test(t)||e.fail(`${r}.${t}`,`is not a valid field name`),_(e,i,`${r}.${t}`),t))}function y(e,t){if(!d(t))return e.fail(`setup.form`,`must be an object`),[];t.note!==void 0&&e.copy(t.note,`setup.form.note`);let n=v(e,t.args,`setup.form.args`),r=[];t.triggers!==void 0&&(!d(t.triggers)||Object.keys(t.triggers).length===0?e.fail(`setup.form.triggers`,`must be a non-empty object`):Object.entries(t.triggers).forEach(([t,i])=>{if(!f(t,c)){e.fail(`setup.form.triggers.${t}`,`is not a trigger kind`);return}r.push(t),n.push(...v(e,i,`setup.form.triggers.${t}`))}));let i=n.filter((e,t)=>n.indexOf(e)!==t);return Array.from(new Set(i)).forEach(t=>e.fail(`setup.form.${t}`,`is declared more than once`)),r}function b(e){return d(e)?[e.args,...Object.values(d(e.triggers)?e.triggers:{})].some(e=>d(e)&&Object.values(e).some(e=>d(e)&&e.type===`repo-picker`)):!1}function x(e,t){e.templateCopy(t,`setup.message`)&&t.length>u&&e.fail(`setup.message`,`must be at most ${u} characters`)}function S(e,t,n){if(!f(t.mode,a)){e.fail(`setup.mode`,`is not a supported mode`);return}if(t.mode===`direct`){e.templateValue(t.prompt,`setup.prompt`),t.message!==void 0&&x(e,t.message),n.length!==1&&e.fail(`setup.form.triggers`,`must declare exactly one trigger kind`),n.includes(`event`)&&!b(t.form)&&e.fail(`setup.form`,`must declare a repository field for an event trigger`),t.filter!==void 0&&(n.includes(`event`)?e.templateValue(t.filter,`setup.filter`):e.fail(`setup.filter`,`is only allowed for an event trigger`));return}x(e,t.message),e.absent(t,`prompt`,`setup`,`is only allowed for direct setup`),e.absent(t,`filter`,`setup`,`is only allowed for direct setup`)}function C(e){return d(e)&&e.setup!==void 0}function w(e){let n=new m;if(!d(e))return{valid:!1,errors:[`manifest: must be an object`]};let{setup:r}=e;return d(r)?r.version===`1.0`?((typeof e.id!=`string`||!t.test(e.id))&&n.fail(`id`,`must be a lowercase slug`),n.copy(e.name,`name`),n.copy(e.description,`description`),e.skill!==void 0&&(typeof e.skill!=`string`||!t.test(e.skill))&&n.fail(`skill`,`must be a lowercase slug`),h(n,e.requires),S(n,r,y(n,r.form)),{valid:n.errors.length===0,errors:n.errors}):{valid:!1,errors:[`setup.version: must be "1.0"`]}:{valid:!1,errors:[`setup: must be an object`]}}exports.hasSetupBlock=C,exports.validateSetupEntry=w;
|
|
2
|
+
//# sourceMappingURL=manifest-validation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-validation.cjs","names":[],"sources":["../../src/manifests/manifest-validation.ts"],"sourcesContent":["/**\n * Admission policy for extension-authored catalog manifests.\n *\n * A manifest is data authored in a different repository that instructs this host\n * to render copy and compose a request. The host therefore decides what a\n * manifest is *permitted* to do rather than trusting the file — validation here\n * is a trust boundary, not a convenience check, and it deliberately does not\n * defer to a schema shipped alongside the manifests it would be validating.\n *\n * Beyond mirroring the published schema, this adds the invariants the host's own\n * derivation depends on: a single trigger kind to read, a repository field for\n * an event trigger's source, and field names unique across the form. Without\n * them the derived request body would be silently wrong rather than rejected.\n *\n * A manifest that fails any check is rejected outright. It never renders a\n * partial UI, because everything downstream treats its content as instructions.\n */\n\nimport { SETUP_PLACEHOLDER_NAMESPACES, SETUP_VERSION } from \"./types\";\n\nconst ENTRY_ID_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;\nconst FIELD_NAME_PATTERN = /^[a-z][A-Za-z0-9]*$/;\n/** Copy must never be able to inject markup into the host. */\nconst MARKUP_PATTERN = /<[A-Za-z/!]/;\n/** Every `{{` must open a known namespace and close immediately. */\nconst UNKNOWN_PLACEHOLDER_PATTERN = new RegExp(\n `\\\\{\\\\{(?!(?:${SETUP_PLACEHOLDER_NAMESPACES.join(\"|\")})\\\\.[A-Za-z0-9_.]+\\\\}\\\\})`,\n);\n\nconst SETUP_MODES = [\"direct\", \"assisted\"] as const;\nconst FIELD_TYPES = [\n \"text\",\n \"textarea\",\n \"select\",\n \"cron\",\n \"timezone\",\n \"repo-picker\",\n] as const;\nconst GIT_PROVIDERS = [\"github\", \"gitlab\", \"bitbucket\"] as const;\nconst TRIGGER_KINDS = [\"cron\", \"event\"] as const;\nconst CONSTRAINT_FORMATS = [\"safeExpressionLiteral\"] as const;\n\n/** Setup context only, so this can never become a channel for runtime instructions. */\nconst MAX_MESSAGE_LENGTH = 2000;\n\nexport interface SetupValidationResult {\n valid: boolean;\n errors: string[];\n}\n\ntype Rec = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Rec {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isOneOf<T extends readonly string[]>(\n value: unknown,\n allowed: T,\n): value is T[number] {\n return (\n typeof value === \"string\" && (allowed as readonly string[]).includes(value)\n );\n}\n\nfunction isInteger(value: unknown, minimum: number): boolean {\n return (\n typeof value === \"number\" && Number.isInteger(value) && value >= minimum\n );\n}\n\nclass SetupChecker {\n readonly errors: string[] = [];\n\n fail(path: string, reason: string): false {\n this.errors.push(`${path}: ${reason}`);\n return false;\n }\n\n /** Literal user-visible copy. Carries no markup. */\n copy(value: unknown, path: string): boolean {\n if (typeof value !== \"string\" || value.length === 0) {\n return this.fail(path, \"must be a non-empty string\");\n }\n if (MARKUP_PATTERN.test(value)) {\n return this.fail(path, \"must not contain markup\");\n }\n return true;\n }\n\n placeholders(value: string, path: string): boolean {\n if (UNKNOWN_PLACEHOLDER_PATTERN.test(value)) {\n return this.fail(path, \"uses an unknown placeholder namespace\");\n }\n return true;\n }\n\n /** Copy that may embed `{{namespace.key}}` placeholders. */\n templateCopy(value: unknown, path: string): boolean {\n return this.copy(value, path) && this.placeholders(value as string, path);\n }\n\n /**\n * A request-body string that may embed placeholders. Never rendered, so\n * expression syntax such as a JMESPath filter is allowed through.\n */\n templateValue(value: unknown, path: string): boolean {\n if (typeof value !== \"string\" || value.length === 0) {\n return this.fail(path, \"must be a non-empty string\");\n }\n return this.placeholders(value, path);\n }\n\n absent(container: Rec, key: string, path: string, reason: string): boolean {\n if (key in container) return this.fail(`${path}.${key}`, reason);\n return true;\n }\n}\n\nfunction checkRequires(check: SetupChecker, requires: unknown): void {\n if (!isRecord(requires)) {\n check.fail(\"requires\", \"must be an object\");\n return;\n }\n\n const { integrations, features } = requires;\n if (!isRecord(integrations) || Object.keys(integrations).length === 0) {\n check.fail(\"requires.integrations\", \"must be a non-empty object\");\n } else {\n Object.entries(integrations).forEach(([id, requirement]) => {\n const path = `requires.integrations.${id}`;\n if (!isRecord(requirement)) {\n check.fail(path, \"must be an object\");\n return;\n }\n check.copy(requirement.message, `${path}.message`);\n if (\"required\" in requirement && requirement.required !== false) {\n check.fail(`${path}.required`, \"may only be false\");\n }\n const allowed = [\"message\", \"required\"];\n Object.keys(requirement)\n .filter((key) => !allowed.includes(key))\n .forEach((key) => check.fail(`${path}.${key}`, \"is not allowed\"));\n });\n }\n\n if (features !== undefined) {\n if (!Array.isArray(features) || features.length === 0) {\n check.fail(\"requires.features\", \"must be a non-empty array\");\n } else {\n features.forEach((feature, index) => {\n if (typeof feature !== \"string\" || feature.length === 0) {\n check.fail(\n `requires.features[${index}]`,\n \"must be a non-empty string\",\n );\n }\n });\n }\n }\n}\n\nfunction checkConstraints(\n check: SetupChecker,\n constraints: unknown,\n path: string,\n): void {\n if (!isRecord(constraints) || Object.keys(constraints).length === 0) {\n check.fail(path, \"must be a non-empty object\");\n return;\n }\n\n const { minLength, maxLength, format } = constraints;\n if (minLength !== undefined && !isInteger(minLength, 0)) {\n check.fail(`${path}.minLength`, \"must be a non-negative integer\");\n }\n if (maxLength !== undefined && !isInteger(maxLength, 1)) {\n check.fail(`${path}.maxLength`, \"must be a positive integer\");\n }\n if (format !== undefined && !isOneOf(format, CONSTRAINT_FORMATS)) {\n check.fail(`${path}.format`, \"is not a supported format\");\n }\n}\n\nfunction checkField(check: SetupChecker, field: unknown, path: string): void {\n if (!isRecord(field)) {\n check.fail(path, \"must be an object\");\n return;\n }\n\n const { type, label, help, placeholder, required, provider, options } = field;\n\n if (!isOneOf(type, FIELD_TYPES)) {\n check.fail(`${path}.type`, \"is not a supported field type\");\n }\n check.copy(label, `${path}.label`);\n check.copy(help, `${path}.help`);\n if (placeholder !== undefined) check.copy(placeholder, `${path}.placeholder`);\n if (field.default !== undefined && typeof field.default !== \"string\") {\n check.fail(`${path}.default`, \"must be a string\");\n }\n if (typeof required !== \"boolean\") {\n check.fail(`${path}.required`, \"must be a boolean\");\n }\n if (provider !== undefined && !isOneOf(provider, GIT_PROVIDERS)) {\n check.fail(`${path}.provider`, \"is not a supported provider\");\n }\n if (type === \"repo-picker\" && provider === undefined) {\n check.fail(`${path}.provider`, \"is required for a repository field\");\n }\n\n if (options !== undefined) {\n if (type !== \"select\") {\n check.fail(`${path}.options`, \"is only allowed on a select field\");\n } else if (!Array.isArray(options) || options.length === 0) {\n check.fail(`${path}.options`, \"must be a non-empty array\");\n } else {\n options.forEach((option, index) => {\n const optionPath = `${path}.options[${index}]`;\n if (!isRecord(option)) {\n check.fail(optionPath, \"must be an object\");\n return;\n }\n if (typeof option.value !== \"string\" || option.value.length === 0) {\n check.fail(`${optionPath}.value`, \"must be a non-empty string\");\n }\n check.copy(option.label, `${optionPath}.label`);\n });\n }\n }\n\n if (field.constraints !== undefined) {\n checkConstraints(check, field.constraints, `${path}.constraints`);\n }\n}\n\n/** Returns the declared field names, so the caller can check them for collisions. */\nfunction checkFields(\n check: SetupChecker,\n fields: unknown,\n path: string,\n): string[] {\n if (!isRecord(fields) || Object.keys(fields).length === 0) {\n check.fail(path, \"must be a non-empty object\");\n return [];\n }\n\n return Object.entries(fields).map(([name, field]) => {\n if (!FIELD_NAME_PATTERN.test(name)) {\n check.fail(`${path}.${name}`, \"is not a valid field name\");\n }\n checkField(check, field, `${path}.${name}`);\n return name;\n });\n}\n\n/** Returns the trigger kinds declared, in order. */\nfunction checkForm(check: SetupChecker, form: unknown): string[] {\n if (!isRecord(form)) {\n check.fail(\"setup.form\", \"must be an object\");\n return [];\n }\n\n if (form.note !== undefined) check.copy(form.note, \"setup.form.note\");\n\n const names = checkFields(check, form.args, \"setup.form.args\");\n const kinds: string[] = [];\n\n if (form.triggers !== undefined) {\n if (!isRecord(form.triggers) || Object.keys(form.triggers).length === 0) {\n check.fail(\"setup.form.triggers\", \"must be a non-empty object\");\n } else {\n Object.entries(form.triggers).forEach(([kind, fields]) => {\n if (!isOneOf(kind, TRIGGER_KINDS)) {\n check.fail(`setup.form.triggers.${kind}`, \"is not a trigger kind\");\n return;\n }\n kinds.push(kind);\n names.push(\n ...checkFields(check, fields, `setup.form.triggers.${kind}`),\n );\n });\n }\n }\n\n // The host merges both halves into one value map, so a repeated name would\n // silently shadow a field and misaddress every error reported against it.\n const duplicates = names.filter(\n (name, index) => names.indexOf(name) !== index,\n );\n Array.from(new Set(duplicates)).forEach((name) =>\n check.fail(`setup.form.${name}`, \"is declared more than once\"),\n );\n\n return kinds;\n}\n\nfunction hasRepoPicker(form: unknown): boolean {\n if (!isRecord(form)) return false;\n const groups = [\n form.args,\n ...Object.values(isRecord(form.triggers) ? form.triggers : {}),\n ];\n return groups.some(\n (group) =>\n isRecord(group) &&\n Object.values(group).some(\n (field) => isRecord(field) && field.type === \"repo-picker\",\n ),\n );\n}\n\nfunction checkMessage(check: SetupChecker, message: unknown): void {\n if (check.templateCopy(message, \"setup.message\")) {\n if ((message as string).length > MAX_MESSAGE_LENGTH) {\n check.fail(\n \"setup.message\",\n `must be at most ${MAX_MESSAGE_LENGTH} characters`,\n );\n }\n }\n}\n\nfunction checkMode(check: SetupChecker, setup: Rec, kinds: string[]): void {\n if (!isOneOf(setup.mode, SETUP_MODES)) {\n check.fail(\"setup.mode\", \"is not a supported mode\");\n return;\n }\n\n if (setup.mode === \"direct\") {\n check.templateValue(setup.prompt, \"setup.prompt\");\n // Optional here: it seeds the fallback conversation offered when the\n // deployment cannot run the direct path.\n if (setup.message !== undefined) checkMessage(check, setup.message);\n\n // The derivation reads a single trigger kind, and an event trigger takes\n // its source from the repository field's provider.\n if (kinds.length !== 1) {\n check.fail(\n \"setup.form.triggers\",\n \"must declare exactly one trigger kind\",\n );\n }\n if (kinds.includes(\"event\") && !hasRepoPicker(setup.form)) {\n check.fail(\n \"setup.form\",\n \"must declare a repository field for an event trigger\",\n );\n }\n if (setup.filter !== undefined) {\n if (!kinds.includes(\"event\")) {\n check.fail(\"setup.filter\", \"is only allowed for an event trigger\");\n } else {\n check.templateValue(setup.filter, \"setup.filter\");\n }\n }\n return;\n }\n\n checkMessage(check, setup.message);\n check.absent(setup, \"prompt\", \"setup\", \"is only allowed for direct setup\");\n check.absent(setup, \"filter\", \"setup\", \"is only allowed for direct setup\");\n}\n\n/** Whether a catalog entry ships a setup experience at all. It is optional. */\nexport function hasSetupBlock(candidate: unknown): boolean {\n return isRecord(candidate) && candidate.setup !== undefined;\n}\n\n/**\n * Decide whether this host will act on a catalog manifest.\n *\n * The version is checked first and fails closed: a format this host does not\n * recognise is refused rather than interpreted with today's rules.\n */\nexport function validateSetupEntry(candidate: unknown): SetupValidationResult {\n const check = new SetupChecker();\n\n if (!isRecord(candidate)) {\n return { valid: false, errors: [\"manifest: must be an object\"] };\n }\n\n const { setup } = candidate;\n if (!isRecord(setup)) {\n return { valid: false, errors: [\"setup: must be an object\"] };\n }\n if (setup.version !== SETUP_VERSION) {\n return {\n valid: false,\n errors: [`setup.version: must be \"${SETUP_VERSION}\"`],\n };\n }\n\n if (\n typeof candidate.id !== \"string\" ||\n !ENTRY_ID_PATTERN.test(candidate.id)\n ) {\n check.fail(\"id\", \"must be a lowercase slug\");\n }\n check.copy(candidate.name, \"name\");\n check.copy(candidate.description, \"description\");\n if (\n candidate.skill !== undefined &&\n (typeof candidate.skill !== \"string\" ||\n !ENTRY_ID_PATTERN.test(candidate.skill))\n ) {\n check.fail(\"skill\", \"must be a lowercase slug\");\n }\n\n checkRequires(check, candidate.requires);\n const kinds = checkForm(check, setup.form);\n checkMode(check, setup, kinds);\n\n return { valid: check.errors.length === 0, errors: check.errors };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admission policy for extension-authored catalog manifests.
|
|
3
|
+
*
|
|
4
|
+
* A manifest is data authored in a different repository that instructs this host
|
|
5
|
+
* to render copy and compose a request. The host therefore decides what a
|
|
6
|
+
* manifest is *permitted* to do rather than trusting the file — validation here
|
|
7
|
+
* is a trust boundary, not a convenience check, and it deliberately does not
|
|
8
|
+
* defer to a schema shipped alongside the manifests it would be validating.
|
|
9
|
+
*
|
|
10
|
+
* Beyond mirroring the published schema, this adds the invariants the host's own
|
|
11
|
+
* derivation depends on: a single trigger kind to read, a repository field for
|
|
12
|
+
* an event trigger's source, and field names unique across the form. Without
|
|
13
|
+
* them the derived request body would be silently wrong rather than rejected.
|
|
14
|
+
*
|
|
15
|
+
* A manifest that fails any check is rejected outright. It never renders a
|
|
16
|
+
* partial UI, because everything downstream treats its content as instructions.
|
|
17
|
+
*/
|
|
18
|
+
export interface SetupValidationResult {
|
|
19
|
+
valid: boolean;
|
|
20
|
+
errors: string[];
|
|
21
|
+
}
|
|
22
|
+
/** Whether a catalog entry ships a setup experience at all. It is optional. */
|
|
23
|
+
export declare function hasSetupBlock(candidate: unknown): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Decide whether this host will act on a catalog manifest.
|
|
26
|
+
*
|
|
27
|
+
* The version is checked first and fails closed: a format this host does not
|
|
28
|
+
* recognise is refused rather than interpreted with today's rules.
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateSetupEntry(candidate: unknown): SetupValidationResult;
|