@openhands/agent-canvas 1.17.0 → 1.19.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/acp-providers-BQ4o4vqy.js +1 -0
- package/build/assets/active-backend-context-BsLfwrXB.js +2 -0
- package/build/assets/{agent-context-settings-CJUrcBut.js → agent-context-settings-D9i6ezoJ.js} +1 -1
- package/build/assets/{agent-profiles-service.api-Biieml2L.js → agent-profiles-service.api-U-9YzDFU.js} +1 -1
- package/build/assets/agent-profiles-settings-D-bUV2PX.js +1 -0
- package/build/assets/agent-server-client-options-EHB23gyx.js +1 -0
- package/build/assets/agent-server-config-C_x8Otd9.js +1 -0
- package/build/assets/agent-server-conversation-service.api-BaVQ6NpE.js +88 -0
- package/build/assets/agent-settings-BZJHtaIK.js +2 -0
- package/build/assets/agent-settings-D4snDd6u.js +1 -0
- package/build/assets/alert-banner-BkVt_8Or.js +1 -0
- package/build/assets/{api-error-message-Ve79qDcN.js → api-error-message-BXo0lCI5.js} +1 -1
- package/build/assets/api-key-entry-screen-fAIld-n7.js +1 -0
- package/build/assets/app-settings-DITbrM2u.js +1 -0
- package/build/assets/automation-detail-DawHmaOl.js +3 -0
- package/build/assets/automation-disabled-reason-DtgC8Ppt.js +1 -0
- package/build/assets/{automation-export-DxY47m3T.js → automation-export-Kv6e0bHx.js} +1 -1
- package/build/assets/automation-git-sync-Dd98G_Oz.js +1 -0
- package/build/assets/automation-setup-route-Cdc109ZD.js +3 -0
- package/build/assets/{automation-templates-4C4PM8K7.js → automation-templates-Xhr-FDAB.js} +1 -1
- package/build/assets/automations-list-BeP1LuzQ.js +1 -0
- package/build/assets/{back-nav-button-B8tH0BEp.js → back-nav-button-DWNiN277.js} +1 -1
- package/build/assets/backend-form-modal-DeaUJIik.js +1 -0
- package/build/assets/backend-synced-settings-badge-Br85iWIY.js +1 -0
- package/build/assets/badge-Cdnei7Ly.js +1 -0
- package/build/assets/{base-modal-DTULovNc.js → base-modal-Ds7grR67.js} +1 -1
- package/build/assets/{bot-CLMxGFaq.js → bot-ByolqPEr.js} +1 -1
- package/build/assets/{brand-button-DxPO4Lf8.js → brand-button-mQq2Ld1I.js} +1 -1
- package/build/assets/browser-Bfum8fkE.js +46 -0
- package/build/assets/browser-tab-CmYT4j_r.js +1 -0
- package/build/assets/canvas-extension-page-CokKSVRG.js +1 -0
- package/build/assets/canvas-extensions-BoQEYG-2.js +1 -0
- package/build/assets/{canvas-extensions-runtime-DdnkgJXV.js → canvas-extensions-runtime-Du2M5iEX.js} +1 -1
- package/build/assets/{chat-send-button-B3SFSIg5.js → chat-send-button-DM3JgMc2.js} +1 -1
- package/build/assets/check-Bo8s5Ylg.js +1 -0
- package/build/assets/chevron-down-Cr6Fn_wS.js +1 -0
- package/build/assets/chevron-right-CfdfRn-8.js +1 -0
- package/build/assets/circle-check-5pH3qCji.js +1 -0
- package/build/assets/circle-plus-check-toggle-BbYBiUwv.js +1 -0
- package/build/assets/{cloud-funnel-analytics-BQanUEEC.js → cloud-funnel-analytics-D02kgq1s.js} +1 -1
- package/build/assets/{cog-VBlRo6iw.js → cog-Dy1eWbSZ.js} +1 -1
- package/build/assets/command-menu-mehU3Evb.js +1 -0
- package/build/assets/commits-tab-DhQW8CXi.js +1 -0
- package/build/assets/{condenser-settings-eVKFMvap.js → condenser-settings-eRk6Fkx6.js} +1 -1
- package/build/assets/confirmation-modal-BmVt_c0I.js +1 -0
- package/build/assets/{context-menu-list-item-DDROe12Z.js → context-menu-list-item-lx2zk9G7.js} +1 -1
- package/build/assets/{conversation-BnjJSFf5.js → conversation-BOj0ENI6.js} +8 -8
- package/build/assets/conversation-SouWlGvs.js +1 -0
- package/build/assets/conversation-panel-SouWlGvs.js +1 -0
- package/build/assets/conversation-state-store-C6YncQNo.js +1 -0
- package/build/assets/conversation-store-DC-JlJuq.js +6 -0
- package/build/assets/{conversation-tab-empty-state-DKlzAz5c.js → conversation-tab-empty-state-DIhwCC2J.js} +1 -1
- package/build/assets/copy-to-clipboard-button-DVNXLylP.js +1 -0
- package/build/assets/device-verify-LP-x7nra.js +1 -0
- package/build/assets/{dropdown-classes-B9kJVDIk.js → dropdown-classes-goDldkiu.js} +1 -1
- package/build/assets/edit-automation-modal-BJJR9wSW.js +1 -0
- package/build/assets/empty-state-Cd-TFe7i.js +1 -0
- package/build/assets/{entry.client-Ds8LVp-E.js → entry.client-CJdjIvMZ.js} +2 -2
- package/build/assets/enum-filter-dropdown-pocrz9AL.js +1 -0
- package/build/assets/environment-switch-overlay-Dwe78wRl.js +1 -0
- package/build/assets/error-state-SuWwztxV.js +1 -0
- package/build/assets/extensions-hub-O0esK3Er.js +1 -0
- package/build/assets/extensions-navigation-CgCVSXje.js +1 -0
- package/build/assets/{external-link-DQtv7eTh.js → external-link-Bd7Tga-1.js} +1 -1
- package/build/assets/files-tab-B_6t8ljw.js +1 -0
- package/build/assets/{form-control-classes-B-z85REi.js → form-control-classes-lQfLxzH4.js} +1 -1
- package/build/assets/format-model-name-Dfh9Udrx.js +1 -0
- package/build/assets/get-git-path-Bp5rsUkl.js +1 -0
- package/build/assets/git-repo-dropdown-CbD0_LPN.js +1 -0
- package/build/assets/git-repo-dropdown-DPQVumZg.js +1 -0
- package/build/assets/highlighted-source-view-Bp0sgK-f.js +1 -0
- package/build/assets/home-BghzJd-D.js +1 -0
- package/build/assets/home-CXZ8zawS.js +1 -0
- package/build/assets/home-automation-run-tooltip-BdpCckKO.js +1 -0
- package/build/assets/home-store-DNQpfIEO.js +1 -0
- package/build/assets/hooks-service-DkxnQa4N.js +1 -0
- package/build/assets/index-home-Ca6Q5CtT.js +1 -0
- package/build/assets/info-BcajzHn1.js +1 -0
- package/build/assets/install-server-modal-DvxxYKia.js +1 -0
- package/build/assets/{key-CfXbJa8w.js → key-CwTE6XJj.js} +1 -1
- package/build/assets/launch-jsRGPRBx.js +1 -0
- package/build/assets/link-external-B4gx3EeM.js +1 -0
- package/build/assets/list-filter-B8PQk3RA.js +1 -0
- package/build/assets/{list-todo-ByXMdY4W.js → list-todo-Caa8E1X_.js} +1 -1
- package/build/assets/llm-not-configured-banner-DMdL1vaX.js +27 -0
- package/build/assets/llm-settings-dkQ5Oq7W.js +1 -0
- package/build/assets/llm-settings-lNDerSlu.js +1 -0
- package/build/assets/{llm-subscription-service-aDNBQ7Gq.js → llm-subscription-service-BiQaZbvv.js} +1 -1
- package/build/assets/loader-circle-BxJgk73D.js +1 -0
- package/build/assets/{loading-spinner-DfHI77BA.js → loading-spinner-DK1sAwVg.js} +1 -1
- package/build/assets/manage-backends-modal-DqCJohsX.js +1 -0
- package/build/assets/manifest-ff93dc8c.js +1 -0
- package/build/assets/manifest-subpage-layout-sxuPqfUr.js +1 -0
- package/build/assets/{map-provider-DXvssjw9.js → map-provider-iRs80q_6.js} +1 -1
- package/build/assets/markdown-renderer-BH5pqDuJ.js +8 -0
- package/build/assets/mcp-BtaJDXnP.js +1 -0
- package/build/assets/mcp-installed-servers-Br4ZLsjr.js +1 -0
- package/build/assets/mcp-marketplace-utils-BwEnDYqm.js +1 -0
- package/build/assets/mcp-page-DwbnQpVs.js +9 -0
- package/build/assets/messages-DmFJlW6c.js +41 -0
- package/build/assets/{modal-body-DJw4xBki.js → modal-body-DBweM2EN.js} +1 -1
- package/build/assets/{modal-classes-Dg0ngBPO.js → modal-classes-jvG85nkU.js} +1 -1
- package/build/assets/modal-close-button-BrM5fNnn.js +1 -0
- package/build/assets/{mouse-pointer-click-DEhsSUpu.js → mouse-pointer-click-BXlRN92t.js} +1 -1
- package/build/assets/onboarding-CQ8T6T0U.js +1 -0
- package/build/assets/onboarding-modal-CnliiaSN.js +1 -0
- package/build/assets/{organization-service.api-Cyg1Tn03.js → organization-service.api-DmFUEmu5.js} +1 -1
- package/build/assets/parse-git-remote-url-BG8pcKL8.js +1 -0
- package/build/assets/{pencil-D5c47kyN.js → pencil-q-ihqDYv.js} +1 -1
- package/build/assets/{pin-C7vMagvf.js → pin-BdroVQdN.js} +1 -1
- package/build/assets/planner-tab-CXph_C9F.js +1 -0
- package/build/assets/{plug-CeaqeF6u.js → plug-7ACOEbMs.js} +1 -1
- package/build/assets/{plugins-management-service-Bh_pBuf-.js → plugins-management-service-CcEpfNKz.js} +1 -1
- package/build/assets/plus-C2e21TFC.js +1 -0
- package/build/assets/{profiles-service.api-BbOK0EkF.js → profiles-service.api-DdF_4Zhe.js} +1 -1
- package/build/assets/providers-BWRnl31s.js +1 -0
- package/build/assets/proxy-DbEf3Nqr.js +1 -0
- package/build/assets/{puzzle-DdAqbUrb.js → puzzle-LJYnuxKe.js} +1 -1
- package/build/assets/react-BX7IV650.js +1 -0
- package/build/assets/recommended-automations-launcher-r0oI91HN.js +1 -0
- package/build/assets/{refresh-cw-DEQdPCpH.js → refresh-cw-BtdC3T8P.js} +1 -1
- package/build/assets/root-j2fFRlWS.js +2 -0
- package/build/assets/root-layout-CfGgm2lo.js +2 -0
- package/build/assets/root-sEWn3ha1.css +1 -0
- package/build/assets/schema-field-c3Ncgm4x.js +1 -0
- package/build/assets/sdk-section-page-DFEiuiFQ.js +1 -0
- package/build/assets/secret-form-WXXNFqTM.js +1 -0
- package/build/assets/{secrets-service-Cr8g8xuv.js → secrets-service-DU6wh3wX.js} +1 -1
- package/build/assets/secrets-settings-BEqbPvjy.js +1 -0
- package/build/assets/settings-DjaSQwFh.js +1 -0
- package/build/assets/settings-dropdown-input-BRR2OZwi.js +1 -0
- package/build/assets/settings-index-DHv4XFcM.js +1 -0
- package/build/assets/settings-input-Cm4VxUon.js +1 -0
- package/build/assets/{settings-list-classes-Ds4jPBHK.js → settings-list-classes-CaUfKZ33.js} +1 -1
- package/build/assets/settings-modal-djXuAnBO.js +1 -0
- package/build/assets/settings-nav-DFb3hBMr.js +16 -0
- package/build/assets/{settings-service.api-9_xdv_mh.js → settings-service.api-Q9lKW1TX.js} +1 -1
- package/build/assets/settings-switch-seaSJc7t.js +1 -0
- package/build/assets/{settings-utils-8GIIgOQL.js → settings-utils-BTaaRhLZ.js} +1 -1
- package/build/assets/shared-conversation-x3rxVCon.js +1 -0
- package/build/assets/{shield-check-DO7wa_eu.js → shield-check-C3Rl0NF8.js} +1 -1
- package/build/assets/{sidebar-layout-EPfWxk11.js → sidebar-layout-B6mcvvdV.js} +1 -1
- package/build/assets/sidebar-mobile-menu-toggle-CEqS8KnA.js +1 -0
- package/build/assets/{sidebar-nav-link-_t4_Ef-9.js → sidebar-nav-link-BTHX11LG.js} +1 -1
- package/build/assets/{sidebar-onboarding-checklist-storage-DbDX-Wvj.js → sidebar-onboarding-checklist-storage-BP1kzn6p.js} +1 -1
- package/build/assets/sidebar-store-DAZVH-DR.js +1 -0
- package/build/assets/skill-card-pill-row-TD39nfP3.js +1 -0
- package/build/assets/{skill-filter-BBeZ4JEP.js → skill-filter-CdBbbwjm.js} +2 -2
- package/build/assets/{skill-icon-badge-BDhQ-tQ0.js → skill-icon-badge-vUEp7gsC.js} +1 -1
- package/build/assets/skill-scope-BTRBQt0-.js +1 -0
- package/build/assets/skills-plugins-k1tUNAw4.js +1 -0
- package/build/assets/skills-settings-CENviPT7.js +1 -0
- package/build/assets/{styled-tooltip-Pd22BIvr.js → styled-tooltip-DVAlWYnL.js} +1 -1
- package/build/assets/task-list-tab-BLKF_x9f.js +1 -0
- package/build/assets/{terminal-onXx0_Qz.js → terminal-Ckbnqb23.js} +1 -1
- package/build/assets/{toggle-switch-lwQtxDcm.js → toggle-switch-DeiG9Mf6.js} +1 -1
- package/build/assets/{trash-2-ZhKuTLiz.js → trash-2-Bb40zQzs.js} +1 -1
- package/build/assets/trash-CXN2R54L.js +1 -0
- package/build/assets/{triangle-alert-BajLPpQg.js → triangle-alert-DEdu-b_L.js} +1 -1
- package/build/assets/{typography-HLLg_FAn.js → typography-NarNyelM.js} +1 -1
- package/build/assets/usage-tab-Drd3O006.js +1 -0
- package/build/assets/use-acp-credential-form-CJ5wPsQm.js +1 -0
- package/build/assets/{use-activate-agent-profile-BLKML6vQ.js → use-activate-agent-profile-iQZ0U3qV.js} +1 -1
- package/build/assets/use-agent-profiles-LCvb5OXT.js +1 -0
- package/build/assets/{use-automation-health-BZkQNEA8.js → use-automation-health-DdgSa8sA.js} +1 -1
- package/build/assets/{use-automation-permissions-B_RpvL-s.js → use-automation-permissions-D3kEeieu.js} +1 -1
- package/build/assets/{use-automations-Cg0PDIZr.js → use-automations-CEubcYTD.js} +1 -1
- package/build/assets/{use-can-manage-org-profiles-BbN6KfDr.js → use-can-manage-org-profiles-CB8ybxFK.js} +1 -1
- package/build/assets/{use-canvas-extensions-CFUpHat6.js → use-canvas-extensions-BMacwi2v.js} +1 -1
- package/build/assets/{use-cloud-current-user-id-Dk0rjr63.js → use-cloud-current-user-id-BEKRd6XZ.js} +1 -1
- package/build/assets/{use-config-DpafU_QP.js → use-config-3WYcJsgC.js} +1 -1
- package/build/assets/{use-create-conversation-1YgmAHt-.js → use-create-conversation-Be-eVpFp.js} +1 -1
- package/build/assets/use-create-secret-Bk9ZxTjl.js +1 -0
- package/build/assets/use-free-models-Ci3FkKEm.js +1 -0
- package/build/assets/{use-get-secrets-CQ4b0qK8.js → use-get-secrets-fqS0kxt6.js} +1 -1
- package/build/assets/use-is-authed-A2Yinlt0.js +1 -0
- package/build/assets/{use-launch-skill-in-chat-DeYa1tFM.js → use-launch-skill-in-chat-QbXDhiHr.js} +1 -1
- package/build/assets/use-llm-configured-B71ZEVg2.js +1 -0
- package/build/assets/use-llm-profiles-xtCBMbef.js +1 -0
- package/build/assets/{use-manifest-capabilities-AOWGcu0j.js → use-manifest-capabilities-Bso6A_-A.js} +1 -1
- package/build/assets/{use-onboarding-completion-CoINurkm.js → use-onboarding-completion-CEgjL02y.js} +1 -1
- package/build/assets/{use-pinned-home-route-D6krwXjy.js → use-pinned-home-route-pK4IlJ-p.js} +1 -1
- package/build/assets/{use-plugins-marketplace-mLsIDhBv.js → use-plugins-marketplace-B8-ZEB34.js} +1 -1
- package/build/assets/use-save-agent-profile-D7hJuW_u.js +1 -0
- package/build/assets/{use-save-settings-3U5K9-8x.js → use-save-settings-CikTu5xV.js} +1 -1
- package/build/assets/{use-settings-Dn00UISA.js → use-settings-BWIH5EuN.js} +1 -1
- package/build/assets/use-settings-nav-items-DSKwLDnd.js +1 -0
- package/build/assets/use-tracking-ChnSFChv.js +3 -0
- package/build/assets/{use-user-conversation-ZWlXtbZb.js → use-user-conversation-C_l65DqW.js} +1 -1
- package/build/assets/{useInfiniteQuery-BzrRqjLg.js → useInfiniteQuery-CtSRG7uW.js} +1 -1
- package/build/assets/{useMutation-CJuK90oc.js → useMutation-Cszf8mKy.js} +1 -1
- package/build/assets/useQueries-pUohFMSP.js +1 -0
- package/build/assets/useQuery-DAAacS7O.js +1 -0
- package/build/assets/useTranslation-CCgUjPJF.js +1 -0
- package/build/assets/utils-D-gOfhmN.js +1 -0
- package/build/assets/{vendor~conversation-panel~conversation-4eJ0tml3.js → vendor~conversation-panel~conversation-C22sJuWZ.js} +1 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-D6owle9R.js +2 -0
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BXXGJNDU.js +185 -0
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-40UR63Gt.js +1 -0
- package/build/assets/{vendor~index-home~home~conversation-panel~conversation-CSFLzmTN.js → vendor~index-home~home~conversation-panel~conversation-UTl7gUo9.js} +1 -1
- package/build/assets/{vendor~root-layout-n8XCEXG8.js → vendor~root-layout-CcdIqs-C.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-3Idg1_U3.js → vendor~root-layout~conversation-panel~conversation-C3EBV3kp.js} +1 -1
- package/build/assets/vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-BCe0JJVy.js +1 -0
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-DgQ564nC.js → vendor~root-layout~index-home~home~conversation-panel~conversation-BGGbPcYh.js} +1 -1
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-BFRW8wt-.js +48 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-BPjI-atc.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-3eJ4ExtV.js} +1 -1
- package/build/assets/{verification-settings-u2POabjH.js → verification-settings-PKtoIUUY.js} +1 -1
- package/build/assets/{wrench-CkgI4rxA.js → wrench-B8Wg_nbp.js} +1 -1
- package/build/assets/{x-By6qCmtY.js → x-CX8lVGwm.js} +1 -1
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +16 -2
- package/build/locales/ca/openhands.json +16 -2
- package/build/locales/de/openhands.json +16 -2
- package/build/locales/en/openhands.json +16 -2
- package/build/locales/es/openhands.json +16 -2
- package/build/locales/fr/openhands.json +16 -2
- package/build/locales/it/openhands.json +16 -2
- package/build/locales/ja/openhands.json +16 -2
- package/build/locales/ko-KR/openhands.json +16 -2
- package/build/locales/no/openhands.json +16 -2
- package/build/locales/pt/openhands.json +16 -2
- package/build/locales/tr/openhands.json +16 -2
- package/build/locales/uk/openhands.json +16 -2
- package/build/locales/zh-CN/openhands.json +16 -2
- package/build/locales/zh-TW/openhands.json +16 -2
- package/config/defaults.json +3 -3
- package/dist/api/cloud/organization-service.api.cjs.map +1 -1
- package/dist/api/cloud/organization-service.api.d.ts +9 -1
- package/dist/api/cloud/organization-service.api.js.map +1 -1
- package/dist/api/config-service/config-service.api.cjs +1 -1
- package/dist/api/config-service/config-service.api.cjs.map +1 -1
- package/dist/api/config-service/config-service.api.js +6 -2
- package/dist/api/config-service/config-service.api.js.map +1 -1
- package/dist/api/config-service/config-service.types.d.ts +13 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs +3 -3
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js +12 -16
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js.map +1 -1
- package/dist/components/features/automations/automation-card.cjs +1 -1
- package/dist/components/features/automations/automation-card.cjs.map +1 -1
- package/dist/components/features/automations/automation-card.js +39 -38
- package/dist/components/features/automations/automation-card.js.map +1 -1
- package/dist/components/features/automations/automation-list-row.cjs +1 -1
- package/dist/components/features/automations/automation-list-row.cjs.map +1 -1
- package/dist/components/features/automations/automation-list-row.js +73 -72
- package/dist/components/features/automations/automation-list-row.js.map +1 -1
- package/dist/components/features/automations/build-automation-menu-items.cjs +1 -1
- package/dist/components/features/automations/build-automation-menu-items.cjs.map +1 -1
- package/dist/components/features/automations/build-automation-menu-items.d.ts +3 -1
- package/dist/components/features/automations/build-automation-menu-items.js +12 -11
- package/dist/components/features/automations/build-automation-menu-items.js.map +1 -1
- package/dist/components/features/automations/detail/configuration-section.d.ts +7 -1
- package/dist/components/features/automations/detail/detail-header.d.ts +8 -5
- package/dist/components/features/automations/detail/disabled-reason-banner.d.ts +16 -0
- package/dist/components/features/backends/backend-selector.cjs +1 -1
- package/dist/components/features/backends/backend-selector.cjs.map +1 -1
- package/dist/components/features/backends/backend-selector.js +112 -112
- package/dist/components/features/backends/backend-selector.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.js +62 -61
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.js.map +1 -1
- package/dist/components/features/chat/model-messages.cjs +1 -1
- package/dist/components/features/chat/model-messages.cjs.map +1 -1
- package/dist/components/features/chat/model-messages.js +27 -26
- package/dist/components/features/chat/model-messages.js.map +1 -1
- package/dist/components/features/conversation-panel/budget-display.cjs +1 -1
- package/dist/components/features/conversation-panel/budget-display.cjs.map +1 -1
- package/dist/components/features/conversation-panel/budget-display.d.ts +1 -2
- package/dist/components/features/conversation-panel/budget-display.js +12 -19
- package/dist/components/features/conversation-panel/budget-display.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +45 -44
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js.map +1 -1
- package/dist/components/features/home/featured-automations/build-home-automation-menu-items.d.ts +1 -2
- package/dist/components/features/home/featured-automations/build-pinned-automation-menu-items.d.ts +0 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +38 -29
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
- package/dist/components/features/images/image-lightbox.cjs +2 -0
- package/dist/components/features/images/image-lightbox.cjs.map +1 -0
- package/dist/components/features/images/image-lightbox.d.ts +11 -0
- package/dist/components/features/images/image-lightbox.js +37 -0
- package/dist/components/features/images/image-lightbox.js.map +1 -0
- package/dist/components/features/images/image-preview.cjs +1 -1
- package/dist/components/features/images/image-preview.cjs.map +1 -1
- package/dist/components/features/images/image-preview.d.ts +2 -1
- package/dist/components/features/images/image-preview.js +33 -13
- package/dist/components/features/images/image-preview.js.map +1 -1
- package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +3 -4
- package/dist/components/features/settings/agent-profiles/profile-scope-list.d.ts +20 -0
- package/dist/components/features/settings/cloud-settings-link.cjs +1 -1
- package/dist/components/features/settings/cloud-settings-link.cjs.map +1 -1
- package/dist/components/features/settings/cloud-settings-link.d.ts +3 -1
- package/dist/components/features/settings/cloud-settings-link.js +22 -21
- package/dist/components/features/settings/cloud-settings-link.js.map +1 -1
- package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
- package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +2 -1
- package/dist/components/features/settings/llm-profiles/profile-row.cjs +1 -1
- package/dist/components/features/settings/llm-profiles/profile-row.js +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.d.ts +2 -1
- package/dist/components/features/sidebar/sidebar-rail-body.js +143 -142
- package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
- package/dist/components/features/sidebar/sidebar.cjs +1 -1
- package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar.js +28 -27
- package/dist/components/features/sidebar/sidebar.js.map +1 -1
- package/dist/components/providers/agent-server-ui-providers.cjs +1 -1
- package/dist/components/providers/agent-server-ui-providers.cjs.map +1 -1
- package/dist/components/providers/agent-server-ui-providers.js +33 -29
- package/dist/components/providers/agent-server-ui-providers.js.map +1 -1
- package/dist/components/shared/buttons/remove-button.cjs +1 -1
- package/dist/components/shared/buttons/remove-button.cjs.map +1 -1
- package/dist/components/shared/buttons/remove-button.d.ts +2 -1
- package/dist/components/shared/buttons/remove-button.js +2 -1
- package/dist/components/shared/buttons/remove-button.js.map +1 -1
- package/dist/components/shared/free-models-note.cjs +2 -0
- package/dist/components/shared/free-models-note.cjs.map +1 -0
- package/dist/components/shared/free-models-note.d.ts +3 -0
- package/dist/components/shared/free-models-note.js +20 -0
- package/dist/components/shared/free-models-note.js.map +1 -0
- package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
- package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
- package/dist/components/shared/modals/settings/model-selector.js +102 -112
- package/dist/components/shared/modals/settings/model-selector.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/constants/acp-providers.cjs +1 -1
- package/dist/constants/acp-providers.cjs.map +1 -1
- package/dist/constants/acp-providers.d.ts +7 -0
- package/dist/constants/acp-providers.js +20 -16
- package/dist/constants/acp-providers.js.map +1 -1
- package/dist/constants/profile-scope.d.ts +21 -0
- package/dist/hooks/chat/use-slash-command.cjs +1 -1
- package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
- package/dist/hooks/chat/use-slash-command.js +63 -62
- package/dist/hooks/chat/use-slash-command.js.map +1 -1
- package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
- package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
- package/dist/hooks/query/use-automation-sdk-version.js +3 -1
- package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
- package/dist/hooks/query/use-free-models.cjs +2 -0
- package/dist/hooks/query/use-free-models.cjs.map +1 -0
- package/dist/hooks/query/use-free-models.d.ts +23 -0
- package/dist/hooks/query/use-free-models.js +67 -0
- package/dist/hooks/query/use-free-models.js.map +1 -0
- package/dist/hooks/query/use-local-git-info.cjs.map +1 -1
- package/dist/hooks/query/use-local-git-info.js.map +1 -1
- package/dist/hooks/query/use-provider-models.cjs +1 -1
- package/dist/hooks/query/use-provider-models.cjs.map +1 -1
- package/dist/hooks/query/use-provider-models.js +34 -25
- package/dist/hooks/query/use-provider-models.js.map +1 -1
- package/dist/hooks/query/use-search-providers.cjs +1 -1
- package/dist/hooks/query/use-search-providers.cjs.map +1 -1
- package/dist/hooks/query/use-search-providers.js +31 -19
- package/dist/hooks/query/use-search-providers.js.map +1 -1
- package/dist/hooks/use-drag-resize.cjs +1 -1
- package/dist/hooks/use-drag-resize.cjs.map +1 -1
- package/dist/hooks/use-drag-resize.js +8 -9
- package/dist/hooks/use-drag-resize.js.map +1 -1
- package/dist/hooks/use-home-automation-actions.cjs +1 -1
- package/dist/hooks/use-home-automation-actions.cjs.map +1 -1
- package/dist/hooks/use-home-automation-actions.d.ts +1 -2
- package/dist/hooks/use-home-automation-actions.js +0 -1
- package/dist/hooks/use-home-automation-actions.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 +16 -2
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +3 -3
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +255 -17
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +16 -2
- package/dist/locales/ca/openhands.json +16 -2
- package/dist/locales/de/openhands.json +16 -2
- package/dist/locales/en/openhands.json +16 -2
- package/dist/locales/es/openhands.json +16 -2
- package/dist/locales/fr/openhands.json +16 -2
- package/dist/locales/it/openhands.json +16 -2
- package/dist/locales/ja/openhands.json +16 -2
- package/dist/locales/ko-KR/openhands.json +16 -2
- package/dist/locales/no/openhands.json +16 -2
- package/dist/locales/pt/openhands.json +16 -2
- package/dist/locales/tr/openhands.json +16 -2
- package/dist/locales/uk/openhands.json +16 -2
- package/dist/locales/zh-CN/openhands.json +16 -2
- package/dist/locales/zh-TW/openhands.json +16 -2
- package/dist/manifests/manifest-validation.cjs +1 -1
- package/dist/manifests/manifest-validation.cjs.map +1 -1
- package/dist/manifests/manifest-validation.js +2 -2
- package/dist/manifests/manifest-validation.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js +15 -8
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js +11 -13
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js +6 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js +3 -6
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js +9 -12
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js +41 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js +3 -6
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/clients.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/clients.js +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js +199 -61
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js +9 -8
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/dist/routes/agent-settings.d.ts +5 -0
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.cjs.map +1 -1
- package/dist/routes/app-settings.js +52 -47
- package/dist/routes/app-settings.js.map +1 -1
- package/dist/routes/llm-settings.cjs +1 -1
- package/dist/routes/llm-settings.cjs.map +1 -1
- package/dist/routes/llm-settings.js +137 -145
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/stores/free-models-store.cjs +2 -0
- package/dist/stores/free-models-store.cjs.map +1 -0
- package/dist/stores/free-models-store.d.ts +30 -0
- package/dist/stores/free-models-store.js +22 -0
- package/dist/stores/free-models-store.js.map +1 -0
- package/dist/types/automation.cjs.map +1 -1
- package/dist/types/automation.d.ts +23 -1
- package/dist/types/automation.js.map +1 -1
- package/dist/utils/automation-disabled-reason.cjs +2 -0
- package/dist/utils/automation-disabled-reason.cjs.map +1 -0
- package/dist/utils/automation-disabled-reason.d.ts +32 -0
- package/dist/utils/automation-disabled-reason.js +19 -0
- package/dist/utils/automation-disabled-reason.js.map +1 -0
- package/dist/utils/format-model-name.cjs +1 -1
- package/dist/utils/format-model-name.cjs.map +1 -1
- package/dist/utils/format-model-name.d.ts +27 -6
- package/dist/utils/format-model-name.js +14 -6
- package/dist/utils/format-model-name.js.map +1 -1
- package/dist/utils/parse-git-remote-url.cjs +1 -1
- package/dist/utils/parse-git-remote-url.cjs.map +1 -1
- package/dist/utils/parse-git-remote-url.d.ts +5 -1
- package/dist/utils/parse-git-remote-url.js +20 -13
- package/dist/utils/parse-git-remote-url.js.map +1 -1
- package/package.json +2 -2
- package/scripts/check-sdk-version-sync.mjs +79 -8
- package/scripts/dev-safe.mjs +1 -1
- package/scripts/static-server.mjs +24 -7
- package/build/assets/acp-providers-DrjNsPOH.js +0 -1
- package/build/assets/active-backend-context-rZiLJRUc.js +0 -2
- package/build/assets/agent-profiles-settings-x6RvPsq7.js +0 -1
- package/build/assets/agent-server-client-options-BikiNwTa.js +0 -1
- package/build/assets/agent-server-conversation-service.api-DYFsNHKf.js +0 -88
- package/build/assets/agent-settings-BJyovpJ_.js +0 -1
- package/build/assets/agent-settings-CpY3zObk.js +0 -2
- package/build/assets/alert-banner-vARz1idS.js +0 -1
- package/build/assets/api-key-entry-screen-CsMuBhoP.js +0 -1
- package/build/assets/app-settings-BaJ7nfHt.js +0 -1
- package/build/assets/automation-detail-CVoGDrKq.js +0 -3
- package/build/assets/automation-git-sync-CRMP9Bbm.js +0 -1
- package/build/assets/automation-setup-route-072beLz1.js +0 -3
- package/build/assets/automations-list-xuqTSQL4.js +0 -1
- package/build/assets/backend-form-modal-0aJmWdsa.js +0 -1
- package/build/assets/backend-synced-settings-badge-B7rKWBir.js +0 -1
- package/build/assets/badge-CcGx2TaV.js +0 -1
- package/build/assets/browser-C-_qBasq.js +0 -46
- package/build/assets/browser-tab-DZanIw5m.js +0 -1
- package/build/assets/canvas-extension-page-o_cWgE9B.js +0 -1
- package/build/assets/canvas-extensions-DSgNlCha.js +0 -1
- package/build/assets/check-fDEfgSzj.js +0 -1
- package/build/assets/chevron-down-CFrWHqu8.js +0 -1
- package/build/assets/chevron-right-C5roOrJu.js +0 -1
- package/build/assets/circle-check-ClTzJTdb.js +0 -1
- package/build/assets/circle-plus-check-toggle-Fr-h-mbL.js +0 -1
- package/build/assets/command-menu-BT3Ia5Ru.js +0 -1
- package/build/assets/commits-tab-2jhtaohl.js +0 -1
- package/build/assets/confirmation-modal-gIFHeZt6.js +0 -1
- package/build/assets/conversation-DZ578rOX.js +0 -1
- package/build/assets/conversation-panel-DZ578rOX.js +0 -1
- package/build/assets/conversation-state-store-D1_G_9I-.js +0 -1
- package/build/assets/conversation-store-DVVfkCsk.js +0 -6
- package/build/assets/copy-to-clipboard-button-B3w0X7WH.js +0 -1
- package/build/assets/device-verify-BfkCzyFB.js +0 -1
- package/build/assets/edit-automation-modal-BwhJ39JT.js +0 -1
- package/build/assets/empty-state-RZz0OfnY.js +0 -1
- package/build/assets/enum-filter-dropdown-C4pW0ORd.js +0 -1
- package/build/assets/environment-switch-overlay-P2ZAuzov.js +0 -1
- package/build/assets/error-state-B_5cgNPJ.js +0 -1
- package/build/assets/extensions-hub-DsaUr4ca.js +0 -1
- package/build/assets/extensions-navigation-CRMZd-FE.js +0 -1
- package/build/assets/files-tab-CCgAcVdc.js +0 -1
- package/build/assets/format-model-name-CasAP3nd.js +0 -1
- package/build/assets/get-git-path-EHrSDxTM.js +0 -1
- package/build/assets/git-repo-dropdown-D2WEQ97X.js +0 -1
- package/build/assets/git-repo-dropdown-DVeCUUXG.js +0 -1
- package/build/assets/highlighted-source-view-DjHO3SdW.js +0 -1
- package/build/assets/home-BorS_vdS.js +0 -1
- package/build/assets/home-aIMbHw5M.js +0 -1
- package/build/assets/home-automation-run-tooltip-CpHNFiFl.js +0 -1
- package/build/assets/home-store-DyXz0w6d.js +0 -1
- package/build/assets/hooks-service-C6dpRtZM.js +0 -1
- package/build/assets/index-home-zKFuKK2B.js +0 -1
- package/build/assets/info-CTIdjttz.js +0 -1
- package/build/assets/install-server-modal-DUiZMc8u.js +0 -1
- package/build/assets/kebab-menu-item-content-mm04SBD3.js +0 -1
- package/build/assets/launch-BSIf9KEg.js +0 -1
- package/build/assets/link-external-BNZzCM1I.js +0 -1
- package/build/assets/list-filter-CNpqTWVY.js +0 -1
- package/build/assets/llm-not-configured-banner-z_QRSeV0.js +0 -27
- package/build/assets/llm-settings-B-5AHMiX.js +0 -1
- package/build/assets/llm-settings-B3SjHDmA.js +0 -1
- package/build/assets/loader-circle-Dex47vVW.js +0 -1
- package/build/assets/manage-backends-modal-q1NdFisr.js +0 -1
- package/build/assets/manifest-8920b615.js +0 -1
- package/build/assets/manifest-subpage-layout-BQQy5ipR.js +0 -1
- package/build/assets/markdown-renderer-rivLvYh-.js +0 -8
- package/build/assets/mcp-CEXDhQWn.js +0 -1
- package/build/assets/mcp-marketplace-utils-Cn_NIMWM.js +0 -1
- package/build/assets/mcp-page-LGYIICMG.js +0 -9
- package/build/assets/messages-DUSeANAh.js +0 -41
- package/build/assets/modal-close-button-B9j4nasm.js +0 -1
- package/build/assets/onboarding-BjFebfs5.js +0 -1
- package/build/assets/onboarding-modal-DDTjOpyd.js +0 -1
- package/build/assets/parse-git-remote-url-DpDM9bK6.js +0 -1
- package/build/assets/planner-tab-D8f2Y3rn.js +0 -1
- package/build/assets/plus-B3wvU06-.js +0 -1
- package/build/assets/providers-2gIIkz2N.js +0 -1
- package/build/assets/proxy-CBgMd2zf.js +0 -1
- package/build/assets/recommended-automations-launcher-YLAQTp4s.js +0 -1
- package/build/assets/root-Bye_XmEL.js +0 -2
- package/build/assets/root-Cnwwzgo0.css +0 -1
- package/build/assets/root-layout-CSAwxBGM.js +0 -2
- package/build/assets/schema-field-CK0xYNbO.js +0 -1
- package/build/assets/sdk-section-page-Da73Rs_o.js +0 -1
- package/build/assets/secret-form-CB2VwYYg.js +0 -1
- package/build/assets/secrets-settings-Bh0udeKv.js +0 -1
- package/build/assets/settings-DmyIgRxO.js +0 -1
- package/build/assets/settings-dropdown-input-DVpyD87C.js +0 -1
- package/build/assets/settings-index-BSJUFmjE.js +0 -1
- package/build/assets/settings-input-C0dd8Utu.js +0 -1
- package/build/assets/settings-modal-yStgEh2o.js +0 -1
- package/build/assets/settings-switch-B78Khmyz.js +0 -1
- package/build/assets/shared-conversation-DM96X4KV.js +0 -1
- package/build/assets/sidebar-mobile-menu-toggle-D5GR5xT9.js +0 -1
- package/build/assets/sidebar-store-CSDFK0W5.js +0 -1
- package/build/assets/skill-card-pill-row-989y15jV.js +0 -1
- package/build/assets/skill-scope-Dz3kPH3P.js +0 -1
- package/build/assets/skills-plugins-e3CYGdUJ.js +0 -1
- package/build/assets/skills-settings-3e-FuHw_.js +0 -1
- package/build/assets/task-list-tab-3Jg8ywch.js +0 -1
- package/build/assets/trash-B6OIe4yX.js +0 -1
- package/build/assets/usage-tab-Cm-9j3UK.js +0 -1
- package/build/assets/use-acp-credential-form-BARcvjYE.js +0 -1
- package/build/assets/use-agent-profiles-1P91KSXz.js +0 -1
- package/build/assets/use-create-secret-D8p9ybQj.js +0 -1
- package/build/assets/use-is-authed-BRPjCRKM.js +0 -1
- package/build/assets/use-llm-configured-DGm8FiRR.js +0 -1
- package/build/assets/use-llm-profiles-BTTtpW4z.js +0 -1
- package/build/assets/use-save-agent-profile-CxyO9YG-.js +0 -1
- package/build/assets/use-settings-nav-items-vrjxTqcu.js +0 -16
- package/build/assets/use-tracking-B9prBsrq.js +0 -3
- package/build/assets/useQueries-CykmpT-a.js +0 -1
- package/build/assets/useQuery-S6j94er1.js +0 -1
- package/build/assets/utils-BOco8mxR.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +0 -2
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BfkNGovw.js +0 -185
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-DnDoaYNi.js +0 -1
- package/build/assets/vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-DkPlXWl9.js +0 -1
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js +0 -48
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-CV850oio.js +0 -1
|
@@ -321,6 +321,13 @@
|
|
|
321
321
|
"SETTINGS$AGENT_PAGE_DESCRIPTION": "Escolha entre o agente OpenHands integrado e um subprocesso ACP (Agent Client Protocol) externo, como Claude Code, Codex ou Gemini CLI.",
|
|
322
322
|
"SETTINGS$AGENT_TYPE_OPENHANDS": "OpenHands",
|
|
323
323
|
"SETTINGS$AGENT_TYPE_ACP": "ACP (subprocesso externo)",
|
|
324
|
+
"SETTINGS$AGENT_PROFILE_MCP": "Servidores MCP",
|
|
325
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL": "Todos os servidores",
|
|
326
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE": "Escolher servidores",
|
|
327
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL_HINT": "Este agente pode usar todos os servidores MCP que você configurou, incluindo os que podem fazer alterações.",
|
|
328
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE_HINT": "Este agente pode usar apenas os servidores que você selecionar. Todos os outros servidores MCP permanecem ocultos para ele.",
|
|
329
|
+
"SETTINGS$AGENT_PROFILE_MCP_NONE": "Você ainda não configurou nenhum servidor MCP.",
|
|
330
|
+
"SETTINGS$AGENT_PROFILE_MCP_DANGLING": "{{names}} não está mais configurado. Salvar com ele selecionado impedirá que este agente inicie — desmarque-o ou adicione o servidor novamente.",
|
|
324
331
|
"SETTINGS$AGENT_PRESET": "Predefinição",
|
|
325
332
|
"SETTINGS$AGENT_PRESET_CUSTOM": "Personalizado",
|
|
326
333
|
"SETTINGS$AGENT_COMMAND": "Comando",
|
|
@@ -693,6 +700,7 @@
|
|
|
693
700
|
"SETTINGS$RESET": "Configurações redefinidas",
|
|
694
701
|
"SETTINGS$API_KEYS": "Chaves API",
|
|
695
702
|
"SETTINGS$API_KEYS_DESCRIPTION": "As chaves de API permitem que você se autentique com a API OpenHands programaticamente. Mantenha suas chaves de API seguras; qualquer pessoa com sua chave de API pode acessar sua conta. Para obter mais informações sobre como usar a API, consulte nossa <a>documentação da API</a>.",
|
|
703
|
+
"SETTINGS$OPENHANDS_FREE_MODELS_NOTE": "Modelos OpenHands gratuitos: {{ids}}. Endpoints de outros provedores com nomes de modelo semelhantes podem exigir cobrança separada.",
|
|
696
704
|
"SETTINGS$OPENHANDS_API_KEY_HELP_TEXT": "Você pode encontrar sua OpenHands Provider LLM Key na",
|
|
697
705
|
"SETTINGS$OPENHANDS_API_KEY_HELP_LINK": "OpenHands LLM Key",
|
|
698
706
|
"SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX": "seção do OpenHands Cloud -",
|
|
@@ -839,6 +847,9 @@
|
|
|
839
847
|
"AUTOMATIONS$DETAIL$PHASE_PREPARING": "Preparando",
|
|
840
848
|
"AUTOMATIONS$DETAIL$PHASE_RUNNING_AGENT": "Executando agente",
|
|
841
849
|
"AUTOMATIONS$DETAIL$INACTIVE": "Inativa",
|
|
850
|
+
"AUTOMATIONS$DETAIL$DISABLED_MANUAL": "Desativada manualmente",
|
|
851
|
+
"AUTOMATIONS$DETAIL$DISABLED_REASON_HEADING": "Por que está pausada",
|
|
852
|
+
"AUTOMATIONS$DETAIL$DISABLED_AT": "Pausada {{time}}",
|
|
842
853
|
"AUTOMATIONS$DETAIL$LAST_RUN": "Última execução",
|
|
843
854
|
"AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "Carregar mais",
|
|
844
855
|
"AUTOMATIONS$DETAIL$EXPORT_JSON": "Exportar JSON",
|
|
@@ -875,6 +886,7 @@
|
|
|
875
886
|
"AUTOMATIONS$DETAIL$PLUGINS": "Plugins",
|
|
876
887
|
"AUTOMATIONS$DETAIL$PROMPT": "Prompt",
|
|
877
888
|
"AUTOMATIONS$DETAIL$REPOSITORIES": "Repositórios",
|
|
889
|
+
"AUTOMATIONS$DETAIL$RUNS_AS": "A automação é executada como",
|
|
878
890
|
"AUTOMATIONS$DETAIL$SCHEDULE": "Agendamento",
|
|
879
891
|
"AUTOMATIONS$DETAIL$SUCCESSFUL": "Bem-sucedido",
|
|
880
892
|
"AUTOMATIONS$DETAIL$TRIGGER": "Acionador",
|
|
@@ -1147,7 +1159,6 @@
|
|
|
1147
1159
|
"CONVERSATION$TOTAL_COST": "Custo total",
|
|
1148
1160
|
"CONVERSATION$BUDGET": "Orçamento",
|
|
1149
1161
|
"CONVERSATION$BUDGET_USAGE": "% utilizado",
|
|
1150
|
-
"CONVERSATION$NO_BUDGET_LIMIT": "Sem limite de orçamento",
|
|
1151
1162
|
"CONVERSATION$INPUT": "Entrada",
|
|
1152
1163
|
"CONVERSATION$OUTPUT": "Saída",
|
|
1153
1164
|
"CONVERSATION$TOTAL": "Total",
|
|
@@ -2451,5 +2462,8 @@
|
|
|
2451
2462
|
"SETTINGS$PROVIDER_CONNECTION_PROVIDER": "Provedor",
|
|
2452
2463
|
"SETTINGS$PROVIDER_CONNECTION_ROTATE_HINT": "Deixe em branco para manter a chave atual.",
|
|
2453
2464
|
"SETTINGS$PROVIDER_CONNECTION_SELECT_LABEL": "Conexão de provedor",
|
|
2454
|
-
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "Conexão \"{{name}}\" atualizada"
|
|
2465
|
+
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "Conexão \"{{name}}\" atualizada",
|
|
2466
|
+
"BUTTON$VIEW_FULL_SIZE_IMAGE": "Ver imagem em tamanho original",
|
|
2467
|
+
"BUTTON$REMOVE_IMAGE": "Remover imagem",
|
|
2468
|
+
"IMAGE$FULL_SIZE_PREVIEW": "Pré-visualização da imagem em tamanho original"
|
|
2455
2469
|
}
|
|
@@ -321,6 +321,13 @@
|
|
|
321
321
|
"SETTINGS$AGENT_PAGE_DESCRIPTION": "Yerleşik OpenHands aracısı ile Claude Code, Codex veya Gemini CLI gibi harici bir ACP (Agent Client Protocol) alt süreci arasında seçim yapın.",
|
|
322
322
|
"SETTINGS$AGENT_TYPE_OPENHANDS": "OpenHands",
|
|
323
323
|
"SETTINGS$AGENT_TYPE_ACP": "ACP (harici alt süreç)",
|
|
324
|
+
"SETTINGS$AGENT_PROFILE_MCP": "MCP sunucuları",
|
|
325
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL": "Tüm sunucular",
|
|
326
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE": "Sunucuları seçin",
|
|
327
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL_HINT": "Bu aracı, yapılandırdığınız tüm MCP sunucularını kullanabilir; bunlara değişiklik yapabilenler de dahildir.",
|
|
328
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE_HINT": "Bu aracı yalnızca seçtiğiniz sunucuları kullanabilir. Diğer tüm MCP sunucuları ona gizli kalır.",
|
|
329
|
+
"SETTINGS$AGENT_PROFILE_MCP_NONE": "Henüz MCP sunucusu yapılandırmadınız.",
|
|
330
|
+
"SETTINGS$AGENT_PROFILE_MCP_DANGLING": "{{names}} artık yapılandırılmış değil. Seçili bırakarak kaydederseniz bu aracı başlatılamaz — seçimi kaldırın veya sunucuyu yeniden ekleyin.",
|
|
324
331
|
"SETTINGS$AGENT_PRESET": "Ön ayar",
|
|
325
332
|
"SETTINGS$AGENT_PRESET_CUSTOM": "Özel",
|
|
326
333
|
"SETTINGS$AGENT_COMMAND": "Komut",
|
|
@@ -693,6 +700,7 @@
|
|
|
693
700
|
"SETTINGS$RESET": "Ayarlar sıfırlandı",
|
|
694
701
|
"SETTINGS$API_KEYS": "API Anahtarları",
|
|
695
702
|
"SETTINGS$API_KEYS_DESCRIPTION": "API anahtarları, OpenHands API ile programlı olarak kimlik doğrulamanıza olanak tanır. API anahtarlarınızı güvende tutun; API anahtarınıza sahip olan herkes hesabınıza erişebilir. API'nin nasıl kullanılacağı hakkında daha fazla bilgi için <a>API belgelerimize</a> bakın.",
|
|
703
|
+
"SETTINGS$OPENHANDS_FREE_MODELS_NOTE": "Ücretsiz OpenHands modelleri: {{ids}}. Benzer model adlarına sahip diğer sağlayıcı uç noktaları ayrı ücretlendirme gerektirebilir.",
|
|
696
704
|
"SETTINGS$OPENHANDS_API_KEY_HELP_TEXT": "OpenHands Provider LLM Key'inizi",
|
|
697
705
|
"SETTINGS$OPENHANDS_API_KEY_HELP_LINK": "OpenHands LLM Key",
|
|
698
706
|
"SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX": "OpenHands Cloud'un bölümünde bulabilirsiniz -",
|
|
@@ -839,6 +847,9 @@
|
|
|
839
847
|
"AUTOMATIONS$DETAIL$PHASE_PREPARING": "Hazırlanıyor",
|
|
840
848
|
"AUTOMATIONS$DETAIL$PHASE_RUNNING_AGENT": "Ajan çalışıyor",
|
|
841
849
|
"AUTOMATIONS$DETAIL$INACTIVE": "Pasif",
|
|
850
|
+
"AUTOMATIONS$DETAIL$DISABLED_MANUAL": "El ile kapatıldı",
|
|
851
|
+
"AUTOMATIONS$DETAIL$DISABLED_REASON_HEADING": "Neden duraklatıldı",
|
|
852
|
+
"AUTOMATIONS$DETAIL$DISABLED_AT": "{{time}} duraklatıldı",
|
|
842
853
|
"AUTOMATIONS$DETAIL$LAST_RUN": "Son çalıştırma",
|
|
843
854
|
"AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "Daha fazla yükle",
|
|
844
855
|
"AUTOMATIONS$DETAIL$EXPORT_JSON": "JSON dışa aktar",
|
|
@@ -875,6 +886,7 @@
|
|
|
875
886
|
"AUTOMATIONS$DETAIL$PLUGINS": "Eklentiler",
|
|
876
887
|
"AUTOMATIONS$DETAIL$PROMPT": "İstem",
|
|
877
888
|
"AUTOMATIONS$DETAIL$REPOSITORIES": "Depolar",
|
|
889
|
+
"AUTOMATIONS$DETAIL$RUNS_AS": "Otomasyon şu kimlikle çalışır",
|
|
878
890
|
"AUTOMATIONS$DETAIL$SCHEDULE": "Zamanlama",
|
|
879
891
|
"AUTOMATIONS$DETAIL$SUCCESSFUL": "Başarılı",
|
|
880
892
|
"AUTOMATIONS$DETAIL$TRIGGER": "Tetikleyici",
|
|
@@ -1147,7 +1159,6 @@
|
|
|
1147
1159
|
"CONVERSATION$TOTAL_COST": "Toplam Maliyet",
|
|
1148
1160
|
"CONVERSATION$BUDGET": "Bütçe",
|
|
1149
1161
|
"CONVERSATION$BUDGET_USAGE": "% kullanıldı",
|
|
1150
|
-
"CONVERSATION$NO_BUDGET_LIMIT": "Bütçe limiti yok",
|
|
1151
1162
|
"CONVERSATION$INPUT": "Giriş",
|
|
1152
1163
|
"CONVERSATION$OUTPUT": "Çıkış",
|
|
1153
1164
|
"CONVERSATION$TOTAL": "Toplam",
|
|
@@ -2451,5 +2462,8 @@
|
|
|
2451
2462
|
"SETTINGS$PROVIDER_CONNECTION_PROVIDER": "Sağlayıcı",
|
|
2452
2463
|
"SETTINGS$PROVIDER_CONNECTION_ROTATE_HINT": "Mevcut anahtarı korumak için boş bırakın.",
|
|
2453
2464
|
"SETTINGS$PROVIDER_CONNECTION_SELECT_LABEL": "Sağlayıcı bağlantısı",
|
|
2454
|
-
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "\"{{name}}\" bağlantısı güncellendi"
|
|
2465
|
+
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "\"{{name}}\" bağlantısı güncellendi",
|
|
2466
|
+
"BUTTON$VIEW_FULL_SIZE_IMAGE": "Görseli tam boyutta görüntüle",
|
|
2467
|
+
"BUTTON$REMOVE_IMAGE": "Görseli kaldır",
|
|
2468
|
+
"IMAGE$FULL_SIZE_PREVIEW": "Tam boyutlu görsel önizlemesi"
|
|
2455
2469
|
}
|
|
@@ -321,6 +321,13 @@
|
|
|
321
321
|
"SETTINGS$AGENT_PAGE_DESCRIPTION": "Оберіть між вбудованим агентом OpenHands і зовнішнім підпроцесом ACP (Agent Client Protocol), як-от Claude Code, Codex або Gemini CLI.",
|
|
322
322
|
"SETTINGS$AGENT_TYPE_OPENHANDS": "OpenHands",
|
|
323
323
|
"SETTINGS$AGENT_TYPE_ACP": "ACP (зовнішній підпроцес)",
|
|
324
|
+
"SETTINGS$AGENT_PROFILE_MCP": "Сервери MCP",
|
|
325
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL": "Усі сервери",
|
|
326
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE": "Вибрати сервери",
|
|
327
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL_HINT": "Цей агент може використовувати всі налаштовані вами сервери MCP, зокрема ті, що здатні вносити зміни.",
|
|
328
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE_HINT": "Цей агент може використовувати лише вибрані вами сервери. Усі інші сервери MCP залишаються прихованими від нього.",
|
|
329
|
+
"SETTINGS$AGENT_PROFILE_MCP_NONE": "Ви ще не налаштували жодного сервера MCP.",
|
|
330
|
+
"SETTINGS$AGENT_PROFILE_MCP_DANGLING": "{{names}} більше не налаштовано. Якщо зберегти з цим вибором, агент не запуститься — зніміть позначку або додайте сервер знову.",
|
|
324
331
|
"SETTINGS$AGENT_PRESET": "Пресет",
|
|
325
332
|
"SETTINGS$AGENT_PRESET_CUSTOM": "Власний",
|
|
326
333
|
"SETTINGS$AGENT_COMMAND": "Команда",
|
|
@@ -693,6 +700,7 @@
|
|
|
693
700
|
"SETTINGS$RESET": "Скидання налаштувань",
|
|
694
701
|
"SETTINGS$API_KEYS": "API ключі",
|
|
695
702
|
"SETTINGS$API_KEYS_DESCRIPTION": "Ключі API дозволяють вам програмно автентифікуватися за допомогою API OpenHands. Зберігайте свої ключі API в безпеці; будь-хто, хто має ваш ключ API, може отримати доступ до вашого облікового запису. Для отримання додаткової інформації про використання API, перегляньте нашу <a>документацію API</a>.",
|
|
703
|
+
"SETTINGS$OPENHANDS_FREE_MODELS_NOTE": "Безкоштовні моделі OpenHands: {{ids}}. Кінцеві точки інших постачальників зі схожими назвами моделей можуть потребувати окремої оплати.",
|
|
696
704
|
"SETTINGS$OPENHANDS_API_KEY_HELP_TEXT": "Ви можете знайти свій OpenHands Provider LLM Key у",
|
|
697
705
|
"SETTINGS$OPENHANDS_API_KEY_HELP_LINK": "OpenHands LLM Key",
|
|
698
706
|
"SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX": "розділі OpenHands Cloud -",
|
|
@@ -839,6 +847,9 @@
|
|
|
839
847
|
"AUTOMATIONS$DETAIL$PHASE_PREPARING": "Підготовка",
|
|
840
848
|
"AUTOMATIONS$DETAIL$PHASE_RUNNING_AGENT": "Агент виконується",
|
|
841
849
|
"AUTOMATIONS$DETAIL$INACTIVE": "Неактивний",
|
|
850
|
+
"AUTOMATIONS$DETAIL$DISABLED_MANUAL": "Вимкнено вручну",
|
|
851
|
+
"AUTOMATIONS$DETAIL$DISABLED_REASON_HEADING": "Чому призупинено",
|
|
852
|
+
"AUTOMATIONS$DETAIL$DISABLED_AT": "Призупинено {{time}}",
|
|
842
853
|
"AUTOMATIONS$DETAIL$LAST_RUN": "Останнє виконання",
|
|
843
854
|
"AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "Завантажити більше",
|
|
844
855
|
"AUTOMATIONS$DETAIL$EXPORT_JSON": "Експортувати JSON",
|
|
@@ -875,6 +886,7 @@
|
|
|
875
886
|
"AUTOMATIONS$DETAIL$PLUGINS": "Плагіни",
|
|
876
887
|
"AUTOMATIONS$DETAIL$PROMPT": "Запит",
|
|
877
888
|
"AUTOMATIONS$DETAIL$REPOSITORIES": "Репозиторії",
|
|
889
|
+
"AUTOMATIONS$DETAIL$RUNS_AS": "Автоматизація виконується від імені",
|
|
878
890
|
"AUTOMATIONS$DETAIL$SCHEDULE": "Розклад",
|
|
879
891
|
"AUTOMATIONS$DETAIL$SUCCESSFUL": "Успішно",
|
|
880
892
|
"AUTOMATIONS$DETAIL$TRIGGER": "Тригер",
|
|
@@ -1147,7 +1159,6 @@
|
|
|
1147
1159
|
"CONVERSATION$TOTAL_COST": "Загальна вартість",
|
|
1148
1160
|
"CONVERSATION$BUDGET": "Бюджет",
|
|
1149
1161
|
"CONVERSATION$BUDGET_USAGE": "% використано",
|
|
1150
|
-
"CONVERSATION$NO_BUDGET_LIMIT": "Без обмеження бюджету",
|
|
1151
1162
|
"CONVERSATION$INPUT": "Вхідні дані",
|
|
1152
1163
|
"CONVERSATION$OUTPUT": "Результат",
|
|
1153
1164
|
"CONVERSATION$TOTAL": "Всього",
|
|
@@ -2451,5 +2462,8 @@
|
|
|
2451
2462
|
"SETTINGS$PROVIDER_CONNECTION_PROVIDER": "Постачальник",
|
|
2452
2463
|
"SETTINGS$PROVIDER_CONNECTION_ROTATE_HINT": "Залиште порожнім, щоб зберегти поточний ключ.",
|
|
2453
2464
|
"SETTINGS$PROVIDER_CONNECTION_SELECT_LABEL": "Підключення постачальника",
|
|
2454
|
-
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "Підключення \"{{name}}\" оновлено"
|
|
2465
|
+
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "Підключення \"{{name}}\" оновлено",
|
|
2466
|
+
"BUTTON$VIEW_FULL_SIZE_IMAGE": "Переглянути зображення в повному розмірі",
|
|
2467
|
+
"BUTTON$REMOVE_IMAGE": "Видалити зображення",
|
|
2468
|
+
"IMAGE$FULL_SIZE_PREVIEW": "Попередній перегляд зображення в повному розмірі"
|
|
2455
2469
|
}
|
|
@@ -321,6 +321,13 @@
|
|
|
321
321
|
"SETTINGS$AGENT_PAGE_DESCRIPTION": "在内置的 OpenHands 代理和外部 ACP(Agent Client Protocol)子进程(如 Claude Code、Codex 或 Gemini CLI)之间进行选择。",
|
|
322
322
|
"SETTINGS$AGENT_TYPE_OPENHANDS": "OpenHands",
|
|
323
323
|
"SETTINGS$AGENT_TYPE_ACP": "ACP(外部子进程)",
|
|
324
|
+
"SETTINGS$AGENT_PROFILE_MCP": "MCP 服务器",
|
|
325
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL": "全部服务器",
|
|
326
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE": "自选服务器",
|
|
327
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL_HINT": "该代理可以使用你配置的所有 MCP 服务器,其中也包括能够进行修改的服务器。",
|
|
328
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE_HINT": "该代理只能使用你选择的服务器。其他 MCP 服务器对它不可见。",
|
|
329
|
+
"SETTINGS$AGENT_PROFILE_MCP_NONE": "你还没有配置任何 MCP 服务器。",
|
|
330
|
+
"SETTINGS$AGENT_PROFILE_MCP_DANGLING": "{{names}} 已不再配置。保持选中并保存会导致该代理无法启动——请取消选择或重新添加该服务器。",
|
|
324
331
|
"SETTINGS$AGENT_PRESET": "预设",
|
|
325
332
|
"SETTINGS$AGENT_PRESET_CUSTOM": "自定义",
|
|
326
333
|
"SETTINGS$AGENT_COMMAND": "命令",
|
|
@@ -693,6 +700,7 @@
|
|
|
693
700
|
"SETTINGS$RESET": "设置已重置",
|
|
694
701
|
"SETTINGS$API_KEYS": "API密钥",
|
|
695
702
|
"SETTINGS$API_KEYS_DESCRIPTION": "API密钥允许您以编程方式验证OpenHands API。请确保您的API密钥安全;任何拥有您API密钥的人都可以访问您的账户。有关如何使用API的更多信息,请参阅我们的<a>API文档</a>。",
|
|
703
|
+
"SETTINGS$OPENHANDS_FREE_MODELS_NOTE": "免费的 OpenHands 模型:{{ids}}。其他提供商中名称相似的模型端点可能需要单独付费。",
|
|
696
704
|
"SETTINGS$OPENHANDS_API_KEY_HELP_TEXT": "您可以在",
|
|
697
705
|
"SETTINGS$OPENHANDS_API_KEY_HELP_LINK": "OpenHands LLM Key",
|
|
698
706
|
"SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX": "部分中找到您的 OpenHands Provider LLM Key -",
|
|
@@ -839,6 +847,9 @@
|
|
|
839
847
|
"AUTOMATIONS$DETAIL$PHASE_PREPARING": "正在准备",
|
|
840
848
|
"AUTOMATIONS$DETAIL$PHASE_RUNNING_AGENT": "代理运行中",
|
|
841
849
|
"AUTOMATIONS$DETAIL$INACTIVE": "非活动",
|
|
850
|
+
"AUTOMATIONS$DETAIL$DISABLED_MANUAL": "已手动关闭",
|
|
851
|
+
"AUTOMATIONS$DETAIL$DISABLED_REASON_HEADING": "暂停原因",
|
|
852
|
+
"AUTOMATIONS$DETAIL$DISABLED_AT": "{{time}} 暂停",
|
|
842
853
|
"AUTOMATIONS$DETAIL$LAST_RUN": "上次运行",
|
|
843
854
|
"AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "加载更多",
|
|
844
855
|
"AUTOMATIONS$DETAIL$EXPORT_JSON": "导出 JSON",
|
|
@@ -875,6 +886,7 @@
|
|
|
875
886
|
"AUTOMATIONS$DETAIL$PLUGINS": "插件",
|
|
876
887
|
"AUTOMATIONS$DETAIL$PROMPT": "提示",
|
|
877
888
|
"AUTOMATIONS$DETAIL$REPOSITORIES": "仓库",
|
|
889
|
+
"AUTOMATIONS$DETAIL$RUNS_AS": "自动化运行身份",
|
|
878
890
|
"AUTOMATIONS$DETAIL$SCHEDULE": "计划",
|
|
879
891
|
"AUTOMATIONS$DETAIL$SUCCESSFUL": "成功",
|
|
880
892
|
"AUTOMATIONS$DETAIL$TRIGGER": "触发器",
|
|
@@ -1147,7 +1159,6 @@
|
|
|
1147
1159
|
"CONVERSATION$TOTAL_COST": "总成本",
|
|
1148
1160
|
"CONVERSATION$BUDGET": "预算",
|
|
1149
1161
|
"CONVERSATION$BUDGET_USAGE": "% 已使用",
|
|
1150
|
-
"CONVERSATION$NO_BUDGET_LIMIT": "无预算限制",
|
|
1151
1162
|
"CONVERSATION$INPUT": "输入",
|
|
1152
1163
|
"CONVERSATION$OUTPUT": "输出",
|
|
1153
1164
|
"CONVERSATION$TOTAL": "总计",
|
|
@@ -2451,5 +2462,8 @@
|
|
|
2451
2462
|
"SETTINGS$PROVIDER_CONNECTION_PROVIDER": "提供商",
|
|
2452
2463
|
"SETTINGS$PROVIDER_CONNECTION_ROTATE_HINT": "留空以保留当前密钥。",
|
|
2453
2464
|
"SETTINGS$PROVIDER_CONNECTION_SELECT_LABEL": "提供商连接",
|
|
2454
|
-
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "已更新连接“{{name}}”"
|
|
2465
|
+
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "已更新连接“{{name}}”",
|
|
2466
|
+
"BUTTON$VIEW_FULL_SIZE_IMAGE": "查看原始尺寸图片",
|
|
2467
|
+
"BUTTON$REMOVE_IMAGE": "移除图片",
|
|
2468
|
+
"IMAGE$FULL_SIZE_PREVIEW": "原始尺寸图片预览"
|
|
2455
2469
|
}
|
|
@@ -321,6 +321,13 @@
|
|
|
321
321
|
"SETTINGS$AGENT_PAGE_DESCRIPTION": "在內建的 OpenHands 代理和外部 ACP(Agent Client Protocol)子處理程序(如 Claude Code、Codex 或 Gemini CLI)之間進行選擇。",
|
|
322
322
|
"SETTINGS$AGENT_TYPE_OPENHANDS": "OpenHands",
|
|
323
323
|
"SETTINGS$AGENT_TYPE_ACP": "ACP(外部子處理程序)",
|
|
324
|
+
"SETTINGS$AGENT_PROFILE_MCP": "MCP 伺服器",
|
|
325
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL": "全部伺服器",
|
|
326
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE": "自選伺服器",
|
|
327
|
+
"SETTINGS$AGENT_PROFILE_MCP_ALL_HINT": "該代理可以使用你設定的所有 MCP 伺服器,其中也包括能夠進行修改的伺服器。",
|
|
328
|
+
"SETTINGS$AGENT_PROFILE_MCP_CHOOSE_HINT": "該代理只能使用你選擇的伺服器。其他 MCP 伺服器對它不可見。",
|
|
329
|
+
"SETTINGS$AGENT_PROFILE_MCP_NONE": "你還沒有設定任何 MCP 伺服器。",
|
|
330
|
+
"SETTINGS$AGENT_PROFILE_MCP_DANGLING": "{{names}} 已不再設定。保持選取並儲存會導致該代理無法啟動——請取消選取或重新新增該伺服器。",
|
|
324
331
|
"SETTINGS$AGENT_PRESET": "預設集",
|
|
325
332
|
"SETTINGS$AGENT_PRESET_CUSTOM": "自訂",
|
|
326
333
|
"SETTINGS$AGENT_COMMAND": "命令",
|
|
@@ -693,6 +700,7 @@
|
|
|
693
700
|
"SETTINGS$RESET": "設置已重置",
|
|
694
701
|
"SETTINGS$API_KEYS": "API金鑰",
|
|
695
702
|
"SETTINGS$API_KEYS_DESCRIPTION": "API密鑰允許您以編程方式驗證OpenHands API。請確保您的API密鑰安全;任何擁有您API密鑰的人都可以訪問您的賬戶。有關如何使用API的更多信息,請參閱我們的<a>API文檔</a>。",
|
|
703
|
+
"SETTINGS$OPENHANDS_FREE_MODELS_NOTE": "免費的 OpenHands 模型:{{ids}}。其他供應商中名稱相似的模型端點可能需要另外付費。",
|
|
696
704
|
"SETTINGS$OPENHANDS_API_KEY_HELP_TEXT": "您可以在",
|
|
697
705
|
"SETTINGS$OPENHANDS_API_KEY_HELP_LINK": "OpenHands LLM Key",
|
|
698
706
|
"SETTINGS$OPENHANDS_API_KEY_HELP_SUFFIX": "區塊中找到您的 OpenHands Provider LLM Key -",
|
|
@@ -839,6 +847,9 @@
|
|
|
839
847
|
"AUTOMATIONS$DETAIL$PHASE_PREPARING": "正在準備",
|
|
840
848
|
"AUTOMATIONS$DETAIL$PHASE_RUNNING_AGENT": "代理執行中",
|
|
841
849
|
"AUTOMATIONS$DETAIL$INACTIVE": "非作用中",
|
|
850
|
+
"AUTOMATIONS$DETAIL$DISABLED_MANUAL": "已手動關閉",
|
|
851
|
+
"AUTOMATIONS$DETAIL$DISABLED_REASON_HEADING": "暫停原因",
|
|
852
|
+
"AUTOMATIONS$DETAIL$DISABLED_AT": "{{time}} 暫停",
|
|
842
853
|
"AUTOMATIONS$DETAIL$LAST_RUN": "上次執行",
|
|
843
854
|
"AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "載入更多",
|
|
844
855
|
"AUTOMATIONS$DETAIL$EXPORT_JSON": "匯出 JSON",
|
|
@@ -875,6 +886,7 @@
|
|
|
875
886
|
"AUTOMATIONS$DETAIL$PLUGINS": "外掛",
|
|
876
887
|
"AUTOMATIONS$DETAIL$PROMPT": "提示",
|
|
877
888
|
"AUTOMATIONS$DETAIL$REPOSITORIES": "存放庫",
|
|
889
|
+
"AUTOMATIONS$DETAIL$RUNS_AS": "自動化執行身分",
|
|
878
890
|
"AUTOMATIONS$DETAIL$SCHEDULE": "排程",
|
|
879
891
|
"AUTOMATIONS$DETAIL$SUCCESSFUL": "成功",
|
|
880
892
|
"AUTOMATIONS$DETAIL$TRIGGER": "觸發器",
|
|
@@ -1147,7 +1159,6 @@
|
|
|
1147
1159
|
"CONVERSATION$TOTAL_COST": "總成本",
|
|
1148
1160
|
"CONVERSATION$BUDGET": "預算",
|
|
1149
1161
|
"CONVERSATION$BUDGET_USAGE": "% 已使用",
|
|
1150
|
-
"CONVERSATION$NO_BUDGET_LIMIT": "無預算限制",
|
|
1151
1162
|
"CONVERSATION$INPUT": "輸入",
|
|
1152
1163
|
"CONVERSATION$OUTPUT": "輸出",
|
|
1153
1164
|
"CONVERSATION$TOTAL": "總計",
|
|
@@ -2451,5 +2462,8 @@
|
|
|
2451
2462
|
"SETTINGS$PROVIDER_CONNECTION_PROVIDER": "提供者",
|
|
2452
2463
|
"SETTINGS$PROVIDER_CONNECTION_ROTATE_HINT": "留空以保留目前的金鑰。",
|
|
2453
2464
|
"SETTINGS$PROVIDER_CONNECTION_SELECT_LABEL": "提供者連線",
|
|
2454
|
-
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "已更新連線「{{name}}」"
|
|
2465
|
+
"SETTINGS$PROVIDER_CONNECTION_UPDATED": "已更新連線「{{name}}」",
|
|
2466
|
+
"BUTTON$VIEW_FULL_SIZE_IMAGE": "檢視原始尺寸圖片",
|
|
2467
|
+
"BUTTON$REMOVE_IMAGE": "移除圖片",
|
|
2468
|
+
"IMAGE$FULL_SIZE_PREVIEW": "原始尺寸圖片預覽"
|
|
2455
2469
|
}
|
|
@@ -1,2 +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=/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/,a=/^[A-Za-z0-9 ._/-]+$/,o=/^[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/,s=/^(skills|automations)\/[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/,c=RegExp(`\\{\\{(?!(?:${e.SETUP_PLACEHOLDER_NAMESPACES.join(`|`)})\\.[A-Za-z0-9_.]+\\}\\})`),l=[`direct`,`assisted`],u=[`text`,`textarea`,`select`,`number`,`cron`,`timezone`,`repo-picker`,`llm-profile`,`event-source`,`event-type`,`plugin-sources`,`tarball-upload`],d=[`github`,`gitlab`,`bitbucket`],f=[`cron`,`event`],p=[`safeExpressionLiteral`],m=2e3;function h(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function g(e,t){return typeof e==`string`&&t.includes(e)}function _(e,t){return typeof e==`number`&&Number.isInteger(e)&&e>=t}var v=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 c.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 y(e,t){return typeof e==`string`&&t.test(e)&&!e.split(`/`).some(e=>e===`.`||e===`..`)}function b(e){if(typeof e!=`string`||!a.test(e))return!1;let t=e.split(` `).filter(e=>e.length>0);return t.length>0&&t.every(e=>!e.startsWith(`/`)&&!e.split(`/`).some(e=>e===`..`))}function x(e,t){if(!h(t)){e.fail(`requires`,`must be an object`);return}let{integrations:n,features:r}=t;h(n)?Object.entries(n).forEach(([t,n])=>{let r=`requires.integrations.${t}`;if(!h(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`))}):e.fail(`requires.integrations`,`must be an object`),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 S(e,t,n){if(!h(t)||Object.keys(t).length===0){e.fail(n,`must be a non-empty object`);return}let{minLength:r,maxLength:i,min:a,max:o,format:s}=t;r!==void 0&&!_(r,0)&&e.fail(`${n}.minLength`,`must be a non-negative integer`),i!==void 0&&!_(i,1)&&e.fail(`${n}.maxLength`,`must be a positive integer`),a!==void 0&&!_(a,0)&&e.fail(`${n}.min`,`must be a non-negative integer`),o!==void 0&&!_(o,1)&&e.fail(`${n}.max`,`must be a positive integer`),s!==void 0&&!g(s,p)&&e.fail(`${n}.format`,`is not a supported format`)}function C(e,t,n){if(!h(t)){e.fail(n,`must be an object`);return}let{type:r,label:i,help:a,placeholder:o,required:s,provider:c,options:l}=t;g(r,u)||e.fail(`${n}.type`,`is not a supported field type`),e.copy(i,`${n}.label`),e.copy(a,`${n}.help`),o!==void 0&&e.copy(o,`${n}.placeholder`),t.default!==void 0&&typeof t.default!=`string`&&typeof t.default!=`number`&&typeof t.default!=`boolean`&&t.default!==null&&e.fail(`${n}.default`,`must be a string, number, boolean or null`),typeof s!=`boolean`&&e.fail(`${n}.required`,`must be a boolean`),c!==void 0&&!g(c,d)&&e.fail(`${n}.provider`,`is not a supported provider`),r===`repo-picker`&&c===void 0&&e.fail(`${n}.provider`,`is required for a repository field`),t.multiple!==void 0&&(t.multiple!==!0||r!==`repo-picker`)&&e.fail(`${n}.multiple`,`may only be true, and only on a repository field`),l!==void 0&&(r===`select`?!Array.isArray(l)||l.length===0?e.fail(`${n}.options`,`must be a non-empty array`):l.forEach((t,r)=>{let i=`${n}.options[${r}]`;if(!h(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&&S(e,t.constraints,`${n}.constraints`)}function w(e,t,r){return!h(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`),C(e,i,`${r}.${t}`),t))}function T(e,t){if(!h(t))return e.fail(`setup.form`,`must be an object`),{kinds:[],fieldNames:[]};t.note!==void 0&&e.copy(t.note,`setup.form.note`);let n=w(e,t.args,`setup.form.args`),r=[];t.triggers!==void 0&&(!h(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(!g(t,f)){e.fail(`setup.form.triggers.${t}`,`is not a trigger kind`);return}r.push(t),n.push(...w(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`)),{kinds:r,fieldNames:n}}function E(e,t,n){if(!Array.isArray(t)||t.length===0){e.fail(n,`must be a non-empty array`);return}t.forEach((t,r)=>{(typeof t!=`string`||t.length===0)&&e.fail(`${n}[${r}]`,`must be a non-empty string`)})}function D(e,t,n,r){let i=`setup.actions.${t}`;if(!h(n)){e.fail(i,`must be an object`);return}e.copy(n.label,`${i}.label`),e.copy(n.help,`${i}.help`),E(e,n.features,`${i}.features`),w(e,n.args,`${i}.args`).filter(e=>r.includes(e)).forEach(t=>e.fail(`${i}.args.${t}`,`is already declared by the form`)),t===`prompt`?e.templateValue(n.prompt,`${i}.prompt`):t===`plugin`?(e.templateValue(n.prompt,`${i}.prompt`),e.templateValue(n.plugins,`${i}.plugins`)):t===`upload`?(e.templateValue(n.tarballPath,`${i}.tarballPath`),e.templateValue(n.entrypoint,`${i}.entrypoint`),n.setupScript!==void 0&&e.templateValue(n.setupScript,`${i}.setupScript`)):e.fail(i,`is not a supported action kind`);let a={prompt:[`label`,`help`,`features`,`args`,`prompt`],plugin:[`label`,`help`,`features`,`args`,`prompt`,`plugins`],upload:[`label`,`help`,`features`,`args`,`tarballPath`,`entrypoint`,`setupScript`]}[t]??[];Object.keys(n).filter(e=>!a.includes(e)).forEach(t=>e.fail(`${i}.${t}`,`is not allowed`))}function O(e,t,n){if(!h(t)||Object.keys(t).length===0){e.fail(`setup.actions`,`must be a non-empty object`);return}Object.entries(t).forEach(([t,r])=>D(e,t,r,n))}function k(e,t){return h(e)?Object.values(e).some(e=>h(e)&&e.type===t):!1}function A(e){return h(e)&&k(e.args,`repo-picker`)}function j(e){let t=h(e.form)?e.form:{},n=h(t.triggers)?t.triggers:{},r=n.event;return k(r,`event-source`)||`event`in n&&Object.keys(n).length===1&&k(r,`repo-picker`)||k(t.args,`repo-picker`)?!0:!h(e.actions)||Object.keys(e.actions).length===0?!1:Object.values(e.actions).every(A)}function M(e,t){e.templateCopy(t,`setup.message`)&&t.length>m&&e.fail(`setup.message`,`must be at most ${m} characters`)}function N(e,t){if(!h(t)){e.fail(`setup.bundle`,`must be an object`);return}(typeof t.version!=`string`||!i.test(t.version))&&e.fail(`setup.bundle.version`,`must be a semantic version`),b(t.entrypoint)||e.fail(`setup.bundle.entrypoint`,`must be a plain command that stays inside the archive`),t.setupScript!==void 0&&!y(t.setupScript,o)&&e.fail(`setup.bundle.setupScript`,`must be a relative path`),t.timeout!==void 0&&!_(t.timeout,1)&&e.fail(`setup.bundle.timeout`,`must be a positive integer`),!h(t.files)||Object.keys(t.files).length===0?e.fail(`setup.bundle.files`,`must be a non-empty object`):(Object.entries(t.files).forEach(([t,n])=>{y(t,o)||e.fail(`setup.bundle.files.${t}`,`is not a packed path`),t===`config.json`&&e.fail(`setup.bundle.files.${t}`,`is the name the rendered config is packed under`),y(n,s)||e.fail(`setup.bundle.files.${t}`,`must name a file under skills/ or automations/`)}),typeof t.setupScript==`string`&&!(t.setupScript in t.files)&&e.fail(`setup.bundle.setupScript`,`must name a packed file`)),!h(t.config)||Object.keys(t.config).length===0?e.fail(`setup.bundle.config`,`must be a non-empty object`):P(e,t.config,`setup.bundle.config`)}function P(e,t,n){if(typeof t==`string`){e.templateValue(t,n);return}if(Array.isArray(t)){t.forEach((t,r)=>P(e,t,`${n}[${r}]`));return}if(h(t)){Object.entries(t).forEach(([t,r])=>P(e,r,`${n}.${t}`));return}t!==null&&typeof t!=`number`&&typeof t!=`boolean`&&e.fail(n,`must be a string, number, boolean, null, array or object`)}function F(e,t,n,r){if(!g(t.mode,l)){e.fail(`setup.mode`,`is not a supported mode`);return}if(t.mode===`direct`){let i=t.prompt!==void 0,a=t.bundle!==void 0,o=t.actions!==void 0;[i,a,o].filter(Boolean).length===1?a?N(e,t.bundle):o?O(e,t.actions,r):e.templateValue(t.prompt,`setup.prompt`):e.fail(`setup`,`must declare exactly one of prompt, bundle or actions for direct setup`),t.message!==void 0&&M(e,t.message),n.length===0&&e.fail(`setup.form.triggers`,`must declare at least one trigger kind`),n.includes(`event`)&&!j(t)&&e.fail(`setup.form.triggers.event`,`must declare an event source field or repository picker`),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}M(e,t.message),e.absent(t,`prompt`,`setup`,`is only allowed for direct setup`),e.absent(t,`bundle`,`setup`,`is only allowed for direct setup`),e.absent(t,`actions`,`setup`,`is only allowed for direct setup`),e.absent(t,`filter`,`setup`,`is only allowed for direct setup`)}function I(e){return h(e)&&e.setup!==void 0}function L(e){let n=new v;if(!h(e))return{valid:!1,errors:[`manifest: must be an object`]};let{setup:r}=e;if(!h(r))return{valid:!1,errors:[`setup: must be an object`]};if(r.version!==`1.0`)return{valid:!1,errors:[`setup.version: must be "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.version!==void 0&&(typeof e.version!=`string`||!i.test(e.version))&&n.fail(`version`,`must be a semantic version`),e.skill!==void 0&&(typeof e.skill!=`string`||!t.test(e.skill))&&n.fail(`skill`,`must be a lowercase slug`),x(n,e.requires);let{kinds:a,fieldNames:o}=T(n,r.form);return F(n,r,a,o),{valid:n.errors.length===0,errors:n.errors}}exports.hasSetupBlock=I,exports.validateSetupEntry=L;
|
|
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=/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/,a=/^[A-Za-z0-9 ._/-]+$/,o=/^[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/,s=/^(skills|automations|plugins)\/[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/,c=RegExp(`\\{\\{(?!(?:${e.SETUP_PLACEHOLDER_NAMESPACES.join(`|`)})\\.[A-Za-z0-9_.]+\\}\\})`),l=[`direct`,`assisted`],u=[`text`,`textarea`,`select`,`number`,`cron`,`timezone`,`repo-picker`,`llm-profile`,`event-source`,`event-type`,`plugin-sources`,`tarball-upload`],d=[`github`,`gitlab`,`bitbucket`],f=[`cron`,`event`],p=[`safeExpressionLiteral`],m=2e3;function h(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function g(e,t){return typeof e==`string`&&t.includes(e)}function _(e,t){return typeof e==`number`&&Number.isInteger(e)&&e>=t}var v=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 c.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 y(e,t){return typeof e==`string`&&t.test(e)&&!e.split(`/`).some(e=>e===`.`||e===`..`)}function b(e){if(typeof e!=`string`||!a.test(e))return!1;let t=e.split(` `).filter(e=>e.length>0);return t.length>0&&t.every(e=>!e.startsWith(`/`)&&!e.split(`/`).some(e=>e===`..`))}function x(e,t){if(!h(t)){e.fail(`requires`,`must be an object`);return}let{integrations:n,features:r}=t;h(n)?Object.entries(n).forEach(([t,n])=>{let r=`requires.integrations.${t}`;if(!h(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`))}):e.fail(`requires.integrations`,`must be an object`),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 S(e,t,n){if(!h(t)||Object.keys(t).length===0){e.fail(n,`must be a non-empty object`);return}let{minLength:r,maxLength:i,min:a,max:o,format:s}=t;r!==void 0&&!_(r,0)&&e.fail(`${n}.minLength`,`must be a non-negative integer`),i!==void 0&&!_(i,1)&&e.fail(`${n}.maxLength`,`must be a positive integer`),a!==void 0&&!_(a,0)&&e.fail(`${n}.min`,`must be a non-negative integer`),o!==void 0&&!_(o,1)&&e.fail(`${n}.max`,`must be a positive integer`),s!==void 0&&!g(s,p)&&e.fail(`${n}.format`,`is not a supported format`)}function C(e,t,n){if(!h(t)){e.fail(n,`must be an object`);return}let{type:r,label:i,help:a,placeholder:o,required:s,provider:c,options:l}=t;g(r,u)||e.fail(`${n}.type`,`is not a supported field type`),e.copy(i,`${n}.label`),e.copy(a,`${n}.help`),o!==void 0&&e.copy(o,`${n}.placeholder`),t.default!==void 0&&typeof t.default!=`string`&&typeof t.default!=`number`&&typeof t.default!=`boolean`&&t.default!==null&&e.fail(`${n}.default`,`must be a string, number, boolean or null`),typeof s!=`boolean`&&e.fail(`${n}.required`,`must be a boolean`),c!==void 0&&!g(c,d)&&e.fail(`${n}.provider`,`is not a supported provider`),r===`repo-picker`&&c===void 0&&e.fail(`${n}.provider`,`is required for a repository field`),t.multiple!==void 0&&(t.multiple!==!0||r!==`repo-picker`)&&e.fail(`${n}.multiple`,`may only be true, and only on a repository field`),l!==void 0&&(r===`select`?!Array.isArray(l)||l.length===0?e.fail(`${n}.options`,`must be a non-empty array`):l.forEach((t,r)=>{let i=`${n}.options[${r}]`;if(!h(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&&S(e,t.constraints,`${n}.constraints`)}function w(e,t,r){return!h(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`),C(e,i,`${r}.${t}`),t))}function T(e,t){if(!h(t))return e.fail(`setup.form`,`must be an object`),{kinds:[],fieldNames:[]};t.note!==void 0&&e.copy(t.note,`setup.form.note`);let n=w(e,t.args,`setup.form.args`),r=[];t.triggers!==void 0&&(!h(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(!g(t,f)){e.fail(`setup.form.triggers.${t}`,`is not a trigger kind`);return}r.push(t),n.push(...w(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`)),{kinds:r,fieldNames:n}}function E(e,t,n){if(!Array.isArray(t)||t.length===0){e.fail(n,`must be a non-empty array`);return}t.forEach((t,r)=>{(typeof t!=`string`||t.length===0)&&e.fail(`${n}[${r}]`,`must be a non-empty string`)})}function D(e,t,n,r){let i=`setup.actions.${t}`;if(!h(n)){e.fail(i,`must be an object`);return}e.copy(n.label,`${i}.label`),e.copy(n.help,`${i}.help`),E(e,n.features,`${i}.features`),w(e,n.args,`${i}.args`).filter(e=>r.includes(e)).forEach(t=>e.fail(`${i}.args.${t}`,`is already declared by the form`)),t===`prompt`?e.templateValue(n.prompt,`${i}.prompt`):t===`plugin`?(e.templateValue(n.prompt,`${i}.prompt`),e.templateValue(n.plugins,`${i}.plugins`)):t===`upload`?(e.templateValue(n.tarballPath,`${i}.tarballPath`),e.templateValue(n.entrypoint,`${i}.entrypoint`),n.setupScript!==void 0&&e.templateValue(n.setupScript,`${i}.setupScript`)):e.fail(i,`is not a supported action kind`);let a={prompt:[`label`,`help`,`features`,`args`,`prompt`],plugin:[`label`,`help`,`features`,`args`,`prompt`,`plugins`],upload:[`label`,`help`,`features`,`args`,`tarballPath`,`entrypoint`,`setupScript`]}[t]??[];Object.keys(n).filter(e=>!a.includes(e)).forEach(t=>e.fail(`${i}.${t}`,`is not allowed`))}function O(e,t,n){if(!h(t)||Object.keys(t).length===0){e.fail(`setup.actions`,`must be a non-empty object`);return}Object.entries(t).forEach(([t,r])=>D(e,t,r,n))}function k(e,t){return h(e)?Object.values(e).some(e=>h(e)&&e.type===t):!1}function A(e){return h(e)&&k(e.args,`repo-picker`)}function j(e){let t=h(e.form)?e.form:{},n=h(t.triggers)?t.triggers:{},r=n.event;return k(r,`event-source`)||`event`in n&&Object.keys(n).length===1&&k(r,`repo-picker`)||k(t.args,`repo-picker`)?!0:!h(e.actions)||Object.keys(e.actions).length===0?!1:Object.values(e.actions).every(A)}function M(e,t){e.templateCopy(t,`setup.message`)&&t.length>m&&e.fail(`setup.message`,`must be at most ${m} characters`)}function N(e,t){if(!h(t)){e.fail(`setup.bundle`,`must be an object`);return}(typeof t.version!=`string`||!i.test(t.version))&&e.fail(`setup.bundle.version`,`must be a semantic version`),b(t.entrypoint)||e.fail(`setup.bundle.entrypoint`,`must be a plain command that stays inside the archive`),t.setupScript!==void 0&&!y(t.setupScript,o)&&e.fail(`setup.bundle.setupScript`,`must be a relative path`),t.timeout!==void 0&&!_(t.timeout,1)&&e.fail(`setup.bundle.timeout`,`must be a positive integer`),!h(t.files)||Object.keys(t.files).length===0?e.fail(`setup.bundle.files`,`must be a non-empty object`):(Object.entries(t.files).forEach(([t,n])=>{y(t,o)||e.fail(`setup.bundle.files.${t}`,`is not a packed path`),t===`config.json`&&e.fail(`setup.bundle.files.${t}`,`is the name the rendered config is packed under`),y(n,s)||e.fail(`setup.bundle.files.${t}`,`must name a file under skills/, automations/, or plugins/`)}),typeof t.setupScript==`string`&&!(t.setupScript in t.files)&&e.fail(`setup.bundle.setupScript`,`must name a packed file`)),!h(t.config)||Object.keys(t.config).length===0?e.fail(`setup.bundle.config`,`must be a non-empty object`):P(e,t.config,`setup.bundle.config`)}function P(e,t,n){if(typeof t==`string`){e.templateValue(t,n);return}if(Array.isArray(t)){t.forEach((t,r)=>P(e,t,`${n}[${r}]`));return}if(h(t)){Object.entries(t).forEach(([t,r])=>P(e,r,`${n}.${t}`));return}t!==null&&typeof t!=`number`&&typeof t!=`boolean`&&e.fail(n,`must be a string, number, boolean, null, array or object`)}function F(e,t,n,r){if(!g(t.mode,l)){e.fail(`setup.mode`,`is not a supported mode`);return}if(t.mode===`direct`){let i=t.prompt!==void 0,a=t.bundle!==void 0,o=t.actions!==void 0;[i,a,o].filter(Boolean).length===1?a?N(e,t.bundle):o?O(e,t.actions,r):e.templateValue(t.prompt,`setup.prompt`):e.fail(`setup`,`must declare exactly one of prompt, bundle or actions for direct setup`),t.message!==void 0&&M(e,t.message),n.length===0&&e.fail(`setup.form.triggers`,`must declare at least one trigger kind`),n.includes(`event`)&&!j(t)&&e.fail(`setup.form.triggers.event`,`must declare an event source field or repository picker`),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}M(e,t.message),e.absent(t,`prompt`,`setup`,`is only allowed for direct setup`),e.absent(t,`bundle`,`setup`,`is only allowed for direct setup`),e.absent(t,`actions`,`setup`,`is only allowed for direct setup`),e.absent(t,`filter`,`setup`,`is only allowed for direct setup`)}function I(e){return h(e)&&e.setup!==void 0}function L(e){let n=new v;if(!h(e))return{valid:!1,errors:[`manifest: must be an object`]};let{setup:r}=e;if(!h(r))return{valid:!1,errors:[`setup: must be an object`]};if(r.version!==`1.0`)return{valid:!1,errors:[`setup.version: must be "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.version!==void 0&&(typeof e.version!=`string`||!i.test(e.version))&&n.fail(`version`,`must be a semantic version`),e.skill!==void 0&&(typeof e.skill!=`string`||!t.test(e.skill))&&n.fail(`skill`,`must be a lowercase slug`),x(n,e.requires);let{kinds:a,fieldNames:o}=T(n,r.form);return F(n,r,a,o),{valid:n.errors.length===0,errors:n.errors}}exports.hasSetupBlock=I,exports.validateSetupEntry=L;
|
|
2
2
|
//# sourceMappingURL=manifest-validation.cjs.map
|
|
@@ -1 +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 {\n BUNDLE_CONFIG_FILENAME,\n SETUP_PLACEHOLDER_NAMESPACES,\n SETUP_VERSION,\n} 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/**\n * A template version, declared as `version` by a prompt entry and as\n * `setup.bundle.version` by a bundle one. Sent to the service as template\n * provenance, so it is checked at admission. Full semver, as the spec at\n * semver.org states it: a catalog entry published with a pre-release or build\n * suffix is still a version this host may forward, and refusing one would drop\n * the entry from the registry outright.\n */\nconst TEMPLATE_VERSION_PATTERN =\n /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\\+[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*)?$/;\n// The characters a command of plain words and paths is made of. No shell\n// metacharacters, which the service rejects anyway and a bundle has no reason\n// to need; where those words may point is `isPlainCommand`'s to say.\nconst BUNDLE_COMMAND_PATTERN = /^[A-Za-z0-9 ._/-]+$/;\nconst BUNDLE_PATH_PATTERN = /^[A-Za-z0-9._-]+(\\/[A-Za-z0-9._-]+)*$/;\nconst BUNDLE_SOURCE_PATTERN =\n /^(skills|automations)\\/[A-Za-z0-9._-]+(\\/[A-Za-z0-9._-]+)*$/;\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 \"number\",\n \"cron\",\n \"timezone\",\n \"repo-picker\",\n \"llm-profile\",\n \"event-source\",\n \"event-type\",\n \"plugin-sources\",\n \"tarball-upload\",\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\n/**\n * A relative path that stays inside the archive it names.\n *\n * The character class alone is not enough: `.` and `..` are made of allowed\n * characters, so a segment check is what actually keeps a packed file from\n * climbing out of the directory it is extracted into.\n */\nfunction isRelativePath(value: unknown, pattern: RegExp): value is string {\n return (\n typeof value === \"string\" &&\n pattern.test(value) &&\n !value.split(\"/\").some((segment) => segment === \".\" || segment === \"..\")\n );\n}\n\n/**\n * A command whose every word stays inside the archive it is run in.\n *\n * The character class is not what keeps it there: `/` and `.` are allowed\n * characters, so `/bin/sh setup.sh` and `python3 ../../etc/x.py` are made of\n * them and each names something outside the extracted directory. The segment\n * rule packed paths are held to is what refuses those, and requiring a word at\n * all is what refuses an entrypoint of nothing but spaces.\n */\nfunction isPlainCommand(value: unknown): value is string {\n if (typeof value !== \"string\" || !BUNDLE_COMMAND_PATTERN.test(value)) {\n return false;\n }\n const words = value.split(\" \").filter((word) => word.length > 0);\n return (\n words.length > 0 &&\n words.every(\n (word) =>\n !word.startsWith(\"/\") &&\n !word.split(\"/\").some((segment) => segment === \"..\"),\n )\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 // Empty is meaningful rather than malformed: an automation that needs no\n // credential connects to nothing, and the key stays required so that saying\n // so is a deliberate statement instead of an omission.\n if (!isRecord(integrations)) {\n check.fail(\"requires.integrations\", \"must be an 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, min, max, 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 (min !== undefined && !isInteger(min, 0)) {\n check.fail(`${path}.min`, \"must be a non-negative integer\");\n }\n if (max !== undefined && !isInteger(max, 1)) {\n check.fail(`${path}.max`, \"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 (\n field.default !== undefined &&\n typeof field.default !== \"string\" &&\n typeof field.default !== \"number\" &&\n typeof field.default !== \"boolean\" &&\n field.default !== null\n ) {\n check.fail(`${path}.default`, \"must be a string, number, boolean or null\");\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 // The host branches on this key to decide whether a field's value is a list,\n // so a field declaring it anywhere else would be seeded with a list and\n // rendered as a string.\n if (\n field.multiple !== undefined &&\n (field.multiple !== true || type !== \"repo-picker\")\n ) {\n check.fail(\n `${path}.multiple`,\n \"may only be true, and only on a repository field\",\n );\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(\n check: SetupChecker,\n form: unknown,\n): { kinds: string[]; fieldNames: string[] } {\n if (!isRecord(form)) {\n check.fail(\"setup.form\", \"must be an object\");\n return { kinds: [], fieldNames: [] };\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, fieldNames: names };\n}\n\nfunction checkActionFeatures(\n check: SetupChecker,\n features: unknown,\n path: string,\n): void {\n if (!Array.isArray(features) || features.length === 0) {\n check.fail(path, \"must be a non-empty array\");\n return;\n }\n features.forEach((feature, index) => {\n if (typeof feature !== \"string\" || feature.length === 0) {\n check.fail(`${path}[${index}]`, \"must be a non-empty string\");\n }\n });\n}\n\nfunction checkAction(\n check: SetupChecker,\n kind: string,\n action: unknown,\n commonFieldNames: string[],\n): void {\n const path = `setup.actions.${kind}`;\n if (!isRecord(action)) {\n check.fail(path, \"must be an object\");\n return;\n }\n\n check.copy(action.label, `${path}.label`);\n check.copy(action.help, `${path}.help`);\n checkActionFeatures(check, action.features, `${path}.features`);\n const actionFieldNames = checkFields(check, action.args, `${path}.args`);\n actionFieldNames\n .filter((name) => commonFieldNames.includes(name))\n .forEach((name) =>\n check.fail(`${path}.args.${name}`, \"is already declared by the form\"),\n );\n\n if (kind === \"prompt\") {\n check.templateValue(action.prompt, `${path}.prompt`);\n } else if (kind === \"plugin\") {\n check.templateValue(action.prompt, `${path}.prompt`);\n check.templateValue(action.plugins, `${path}.plugins`);\n } else if (kind === \"upload\") {\n check.templateValue(action.tarballPath, `${path}.tarballPath`);\n check.templateValue(action.entrypoint, `${path}.entrypoint`);\n if (action.setupScript !== undefined) {\n check.templateValue(action.setupScript, `${path}.setupScript`);\n }\n } else {\n check.fail(path, \"is not a supported action kind\");\n }\n\n const allowedByKind: Record<string, string[]> = {\n prompt: [\"label\", \"help\", \"features\", \"args\", \"prompt\"],\n plugin: [\"label\", \"help\", \"features\", \"args\", \"prompt\", \"plugins\"],\n upload: [\n \"label\",\n \"help\",\n \"features\",\n \"args\",\n \"tarballPath\",\n \"entrypoint\",\n \"setupScript\",\n ],\n };\n const allowed = allowedByKind[kind] ?? [];\n Object.keys(action)\n .filter((key) => !allowed.includes(key))\n .forEach((key) => check.fail(`${path}.${key}`, \"is not allowed\"));\n}\n\nfunction checkActions(\n check: SetupChecker,\n actions: unknown,\n commonFieldNames: string[],\n): void {\n if (!isRecord(actions) || Object.keys(actions).length === 0) {\n check.fail(\"setup.actions\", \"must be a non-empty object\");\n return;\n }\n Object.entries(actions).forEach(([kind, action]) =>\n checkAction(check, kind, action, commonFieldNames),\n );\n}\n\nfunction fieldsContainType(fields: unknown, type: string): boolean {\n if (!isRecord(fields)) return false;\n return Object.values(fields).some(\n (field) => isRecord(field) && field.type === type,\n );\n}\n\nfunction actionHasRepoPicker(action: unknown): boolean {\n return isRecord(action) && fieldsContainType(action.args, \"repo-picker\");\n}\n\n/**\n * Whether an event trigger's `source` is derivable for every selectable action.\n *\n * `buildTrigger` fills `source` from a field named `source` in the event\n * trigger, or failing that from the selected action's repo-picker provider. A\n * picker in another trigger group (such as `cron`) is never collected for the\n * event trigger, and a picker in only some actions is invisible when one of the\n * others is selected — so neither may satisfy this check, or the user can end\n * up with an empty `source` no form field can fix.\n */\nfunction setupSuppliesEventSource(setup: Rec): boolean {\n const form = isRecord(setup.form) ? setup.form : {};\n const triggers = isRecord(form.triggers) ? form.triggers : {};\n const eventFields = triggers.event;\n\n // An explicit event-source field fills `source` directly, regardless of which\n // action is selected.\n if (fieldsContainType(eventFields, \"event-source\")) return true;\n\n // A repo-picker in the event trigger is only collected when `event` is the\n // sole trigger kind; with a sibling trigger the derivation reads no trigger\n // fields for the picker. `form.args` is shared across every selection, so a\n // picker there is always available.\n const singleEventTrigger =\n \"event\" in triggers && Object.keys(triggers).length === 1;\n if (\n (singleEventTrigger && fieldsContainType(eventFields, \"repo-picker\")) ||\n fieldsContainType(form.args, \"repo-picker\")\n ) {\n return true;\n }\n\n // Without a shared or event-trigger picker, every selectable action must\n // carry its own repo-picker; otherwise selecting an action without one\n // derives `source: \"\"`.\n if (!isRecord(setup.actions) || Object.keys(setup.actions).length === 0) {\n return false;\n }\n return Object.values(setup.actions).every(actionHasRepoPicker);\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\n/**\n * The script tarball a direct entry may ship.\n *\n * The strings here are commands and paths this host acts on, so they are held\n * to a closed character set rather than the placeholder rules copy uses: an\n * entrypoint with a shell metacharacter, or a packed path that escapes the\n * archive, is refused here rather than by the service.\n */\nfunction checkBundle(check: SetupChecker, bundle: unknown): void {\n if (!isRecord(bundle)) {\n check.fail(\"setup.bundle\", \"must be an object\");\n return;\n }\n\n if (\n typeof bundle.version !== \"string\" ||\n !TEMPLATE_VERSION_PATTERN.test(bundle.version)\n ) {\n check.fail(\"setup.bundle.version\", \"must be a semantic version\");\n }\n if (!isPlainCommand(bundle.entrypoint)) {\n check.fail(\n \"setup.bundle.entrypoint\",\n \"must be a plain command that stays inside the archive\",\n );\n }\n if (\n bundle.setupScript !== undefined &&\n !isRelativePath(bundle.setupScript, BUNDLE_PATH_PATTERN)\n ) {\n check.fail(\"setup.bundle.setupScript\", \"must be a relative path\");\n }\n if (bundle.timeout !== undefined && !isInteger(bundle.timeout, 1)) {\n check.fail(\"setup.bundle.timeout\", \"must be a positive integer\");\n }\n\n if (!isRecord(bundle.files) || Object.keys(bundle.files).length === 0) {\n check.fail(\"setup.bundle.files\", \"must be a non-empty object\");\n } else {\n Object.entries(bundle.files).forEach(([packedPath, source]) => {\n if (!isRelativePath(packedPath, BUNDLE_PATH_PATTERN)) {\n check.fail(`setup.bundle.files.${packedPath}`, \"is not a packed path\");\n }\n // The rendered config is packed under this name too, and a tar carrying\n // the name twice leaves which one the script reads to whichever\n // extractor unpacks it.\n if (packedPath === BUNDLE_CONFIG_FILENAME) {\n check.fail(\n `setup.bundle.files.${packedPath}`,\n \"is the name the rendered config is packed under\",\n );\n }\n if (!isRelativePath(source, BUNDLE_SOURCE_PATTERN)) {\n check.fail(\n `setup.bundle.files.${packedPath}`,\n \"must name a file under skills/ or automations/\",\n );\n }\n });\n\n // A setup script the archive does not carry is a create request the\n // service accepts and the first run fails on, and it is also the only\n // thing packed executable - naming an unpacked file makes that rule\n // unreachable.\n if (\n typeof bundle.setupScript === \"string\" &&\n !(bundle.setupScript in bundle.files)\n ) {\n check.fail(\"setup.bundle.setupScript\", \"must name a packed file\");\n }\n }\n\n if (!isRecord(bundle.config) || Object.keys(bundle.config).length === 0) {\n check.fail(\"setup.bundle.config\", \"must be a non-empty object\");\n } else {\n checkBundleConfig(check, bundle.config, \"setup.bundle.config\");\n }\n}\n\n/** Every string leaf of the config is a payload value: placeholders, no markup rule. */\nfunction checkBundleConfig(\n check: SetupChecker,\n node: unknown,\n path: string,\n): void {\n if (typeof node === \"string\") {\n check.templateValue(node, path);\n return;\n }\n if (Array.isArray(node)) {\n node.forEach((item, index) =>\n checkBundleConfig(check, item, `${path}[${index}]`),\n );\n return;\n }\n if (isRecord(node)) {\n Object.entries(node).forEach(([key, value]) =>\n checkBundleConfig(check, value, `${path}.${key}`),\n );\n return;\n }\n if (node !== null && typeof node !== \"number\" && typeof node !== \"boolean\") {\n check.fail(\n path,\n \"must be a string, number, boolean, null, array or object\",\n );\n }\n}\n\nfunction checkMode(\n check: SetupChecker,\n setup: Rec,\n kinds: string[],\n commonFieldNames: string[],\n): 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 // A direct entry produces one of three things: a prompt, a script bundle\n // the host packs and uploads, or a selectable set of action variants.\n // More than one would be ambiguous, and none is nothing to create.\n const hasPrompt = setup.prompt !== undefined;\n const hasBundle = setup.bundle !== undefined;\n const hasActions = setup.actions !== undefined;\n const variants = [hasPrompt, hasBundle, hasActions].filter(Boolean);\n if (variants.length !== 1) {\n check.fail(\n \"setup\",\n \"must declare exactly one of prompt, bundle or actions for direct setup\",\n );\n } else if (hasBundle) {\n checkBundle(check, setup.bundle);\n } else if (hasActions) {\n checkActions(check, setup.actions, commonFieldNames);\n } else {\n check.templateValue(setup.prompt, \"setup.prompt\");\n }\n // A direct entry may carry a fallback-conversation seed for deployments\n // that cannot run the direct path, held to the same rules as an assisted\n // message.\n if (setup.message !== undefined) checkMessage(check, setup.message);\n\n if (kinds.length === 0) {\n check.fail(\n \"setup.form.triggers\",\n \"must declare at least one trigger kind\",\n );\n }\n if (kinds.includes(\"event\") && !setupSuppliesEventSource(setup)) {\n check.fail(\n \"setup.form.triggers.event\",\n \"must declare an event source field or repository picker\",\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, \"bundle\", \"setup\", \"is only allowed for direct setup\");\n check.absent(setup, \"actions\", \"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.version !== undefined &&\n (typeof candidate.version !== \"string\" ||\n !TEMPLATE_VERSION_PATTERN.test(candidate.version))\n ) {\n check.fail(\"version\", \"must be a semantic version\");\n }\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, fieldNames } = checkForm(check, setup.form);\n checkMode(check, setup, kinds, fieldNames);\n\n return { valid: check.errors.length === 0, errors: check.errors };\n}\n"],"mappings":"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"}
|
|
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 {\n BUNDLE_CONFIG_FILENAME,\n SETUP_PLACEHOLDER_NAMESPACES,\n SETUP_VERSION,\n} 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/**\n * A template version, declared as `version` by a prompt entry and as\n * `setup.bundle.version` by a bundle one. Sent to the service as template\n * provenance, so it is checked at admission. Full semver, as the spec at\n * semver.org states it: a catalog entry published with a pre-release or build\n * suffix is still a version this host may forward, and refusing one would drop\n * the entry from the registry outright.\n */\nconst TEMPLATE_VERSION_PATTERN =\n /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\\+[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*)?$/;\n// The characters a command of plain words and paths is made of. No shell\n// metacharacters, which the service rejects anyway and a bundle has no reason\n// to need; where those words may point is `isPlainCommand`'s to say.\nconst BUNDLE_COMMAND_PATTERN = /^[A-Za-z0-9 ._/-]+$/;\nconst BUNDLE_PATH_PATTERN = /^[A-Za-z0-9._-]+(\\/[A-Za-z0-9._-]+)*$/;\nconst BUNDLE_SOURCE_PATTERN =\n /^(skills|automations|plugins)\\/[A-Za-z0-9._-]+(\\/[A-Za-z0-9._-]+)*$/;\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 \"number\",\n \"cron\",\n \"timezone\",\n \"repo-picker\",\n \"llm-profile\",\n \"event-source\",\n \"event-type\",\n \"plugin-sources\",\n \"tarball-upload\",\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\n/**\n * A relative path that stays inside the archive it names.\n *\n * The character class alone is not enough: `.` and `..` are made of allowed\n * characters, so a segment check is what actually keeps a packed file from\n * climbing out of the directory it is extracted into.\n */\nfunction isRelativePath(value: unknown, pattern: RegExp): value is string {\n return (\n typeof value === \"string\" &&\n pattern.test(value) &&\n !value.split(\"/\").some((segment) => segment === \".\" || segment === \"..\")\n );\n}\n\n/**\n * A command whose every word stays inside the archive it is run in.\n *\n * The character class is not what keeps it there: `/` and `.` are allowed\n * characters, so `/bin/sh setup.sh` and `python3 ../../etc/x.py` are made of\n * them and each names something outside the extracted directory. The segment\n * rule packed paths are held to is what refuses those, and requiring a word at\n * all is what refuses an entrypoint of nothing but spaces.\n */\nfunction isPlainCommand(value: unknown): value is string {\n if (typeof value !== \"string\" || !BUNDLE_COMMAND_PATTERN.test(value)) {\n return false;\n }\n const words = value.split(\" \").filter((word) => word.length > 0);\n return (\n words.length > 0 &&\n words.every(\n (word) =>\n !word.startsWith(\"/\") &&\n !word.split(\"/\").some((segment) => segment === \"..\"),\n )\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 // Empty is meaningful rather than malformed: an automation that needs no\n // credential connects to nothing, and the key stays required so that saying\n // so is a deliberate statement instead of an omission.\n if (!isRecord(integrations)) {\n check.fail(\"requires.integrations\", \"must be an 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, min, max, 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 (min !== undefined && !isInteger(min, 0)) {\n check.fail(`${path}.min`, \"must be a non-negative integer\");\n }\n if (max !== undefined && !isInteger(max, 1)) {\n check.fail(`${path}.max`, \"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 (\n field.default !== undefined &&\n typeof field.default !== \"string\" &&\n typeof field.default !== \"number\" &&\n typeof field.default !== \"boolean\" &&\n field.default !== null\n ) {\n check.fail(`${path}.default`, \"must be a string, number, boolean or null\");\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 // The host branches on this key to decide whether a field's value is a list,\n // so a field declaring it anywhere else would be seeded with a list and\n // rendered as a string.\n if (\n field.multiple !== undefined &&\n (field.multiple !== true || type !== \"repo-picker\")\n ) {\n check.fail(\n `${path}.multiple`,\n \"may only be true, and only on a repository field\",\n );\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(\n check: SetupChecker,\n form: unknown,\n): { kinds: string[]; fieldNames: string[] } {\n if (!isRecord(form)) {\n check.fail(\"setup.form\", \"must be an object\");\n return { kinds: [], fieldNames: [] };\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, fieldNames: names };\n}\n\nfunction checkActionFeatures(\n check: SetupChecker,\n features: unknown,\n path: string,\n): void {\n if (!Array.isArray(features) || features.length === 0) {\n check.fail(path, \"must be a non-empty array\");\n return;\n }\n features.forEach((feature, index) => {\n if (typeof feature !== \"string\" || feature.length === 0) {\n check.fail(`${path}[${index}]`, \"must be a non-empty string\");\n }\n });\n}\n\nfunction checkAction(\n check: SetupChecker,\n kind: string,\n action: unknown,\n commonFieldNames: string[],\n): void {\n const path = `setup.actions.${kind}`;\n if (!isRecord(action)) {\n check.fail(path, \"must be an object\");\n return;\n }\n\n check.copy(action.label, `${path}.label`);\n check.copy(action.help, `${path}.help`);\n checkActionFeatures(check, action.features, `${path}.features`);\n const actionFieldNames = checkFields(check, action.args, `${path}.args`);\n actionFieldNames\n .filter((name) => commonFieldNames.includes(name))\n .forEach((name) =>\n check.fail(`${path}.args.${name}`, \"is already declared by the form\"),\n );\n\n if (kind === \"prompt\") {\n check.templateValue(action.prompt, `${path}.prompt`);\n } else if (kind === \"plugin\") {\n check.templateValue(action.prompt, `${path}.prompt`);\n check.templateValue(action.plugins, `${path}.plugins`);\n } else if (kind === \"upload\") {\n check.templateValue(action.tarballPath, `${path}.tarballPath`);\n check.templateValue(action.entrypoint, `${path}.entrypoint`);\n if (action.setupScript !== undefined) {\n check.templateValue(action.setupScript, `${path}.setupScript`);\n }\n } else {\n check.fail(path, \"is not a supported action kind\");\n }\n\n const allowedByKind: Record<string, string[]> = {\n prompt: [\"label\", \"help\", \"features\", \"args\", \"prompt\"],\n plugin: [\"label\", \"help\", \"features\", \"args\", \"prompt\", \"plugins\"],\n upload: [\n \"label\",\n \"help\",\n \"features\",\n \"args\",\n \"tarballPath\",\n \"entrypoint\",\n \"setupScript\",\n ],\n };\n const allowed = allowedByKind[kind] ?? [];\n Object.keys(action)\n .filter((key) => !allowed.includes(key))\n .forEach((key) => check.fail(`${path}.${key}`, \"is not allowed\"));\n}\n\nfunction checkActions(\n check: SetupChecker,\n actions: unknown,\n commonFieldNames: string[],\n): void {\n if (!isRecord(actions) || Object.keys(actions).length === 0) {\n check.fail(\"setup.actions\", \"must be a non-empty object\");\n return;\n }\n Object.entries(actions).forEach(([kind, action]) =>\n checkAction(check, kind, action, commonFieldNames),\n );\n}\n\nfunction fieldsContainType(fields: unknown, type: string): boolean {\n if (!isRecord(fields)) return false;\n return Object.values(fields).some(\n (field) => isRecord(field) && field.type === type,\n );\n}\n\nfunction actionHasRepoPicker(action: unknown): boolean {\n return isRecord(action) && fieldsContainType(action.args, \"repo-picker\");\n}\n\n/**\n * Whether an event trigger's `source` is derivable for every selectable action.\n *\n * `buildTrigger` fills `source` from a field named `source` in the event\n * trigger, or failing that from the selected action's repo-picker provider. A\n * picker in another trigger group (such as `cron`) is never collected for the\n * event trigger, and a picker in only some actions is invisible when one of the\n * others is selected — so neither may satisfy this check, or the user can end\n * up with an empty `source` no form field can fix.\n */\nfunction setupSuppliesEventSource(setup: Rec): boolean {\n const form = isRecord(setup.form) ? setup.form : {};\n const triggers = isRecord(form.triggers) ? form.triggers : {};\n const eventFields = triggers.event;\n\n // An explicit event-source field fills `source` directly, regardless of which\n // action is selected.\n if (fieldsContainType(eventFields, \"event-source\")) return true;\n\n // A repo-picker in the event trigger is only collected when `event` is the\n // sole trigger kind; with a sibling trigger the derivation reads no trigger\n // fields for the picker. `form.args` is shared across every selection, so a\n // picker there is always available.\n const singleEventTrigger =\n \"event\" in triggers && Object.keys(triggers).length === 1;\n if (\n (singleEventTrigger && fieldsContainType(eventFields, \"repo-picker\")) ||\n fieldsContainType(form.args, \"repo-picker\")\n ) {\n return true;\n }\n\n // Without a shared or event-trigger picker, every selectable action must\n // carry its own repo-picker; otherwise selecting an action without one\n // derives `source: \"\"`.\n if (!isRecord(setup.actions) || Object.keys(setup.actions).length === 0) {\n return false;\n }\n return Object.values(setup.actions).every(actionHasRepoPicker);\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\n/**\n * The script tarball a direct entry may ship.\n *\n * The strings here are commands and paths this host acts on, so they are held\n * to a closed character set rather than the placeholder rules copy uses: an\n * entrypoint with a shell metacharacter, or a packed path that escapes the\n * archive, is refused here rather than by the service.\n */\nfunction checkBundle(check: SetupChecker, bundle: unknown): void {\n if (!isRecord(bundle)) {\n check.fail(\"setup.bundle\", \"must be an object\");\n return;\n }\n\n if (\n typeof bundle.version !== \"string\" ||\n !TEMPLATE_VERSION_PATTERN.test(bundle.version)\n ) {\n check.fail(\"setup.bundle.version\", \"must be a semantic version\");\n }\n if (!isPlainCommand(bundle.entrypoint)) {\n check.fail(\n \"setup.bundle.entrypoint\",\n \"must be a plain command that stays inside the archive\",\n );\n }\n if (\n bundle.setupScript !== undefined &&\n !isRelativePath(bundle.setupScript, BUNDLE_PATH_PATTERN)\n ) {\n check.fail(\"setup.bundle.setupScript\", \"must be a relative path\");\n }\n if (bundle.timeout !== undefined && !isInteger(bundle.timeout, 1)) {\n check.fail(\"setup.bundle.timeout\", \"must be a positive integer\");\n }\n\n if (!isRecord(bundle.files) || Object.keys(bundle.files).length === 0) {\n check.fail(\"setup.bundle.files\", \"must be a non-empty object\");\n } else {\n Object.entries(bundle.files).forEach(([packedPath, source]) => {\n if (!isRelativePath(packedPath, BUNDLE_PATH_PATTERN)) {\n check.fail(`setup.bundle.files.${packedPath}`, \"is not a packed path\");\n }\n // The rendered config is packed under this name too, and a tar carrying\n // the name twice leaves which one the script reads to whichever\n // extractor unpacks it.\n if (packedPath === BUNDLE_CONFIG_FILENAME) {\n check.fail(\n `setup.bundle.files.${packedPath}`,\n \"is the name the rendered config is packed under\",\n );\n }\n if (!isRelativePath(source, BUNDLE_SOURCE_PATTERN)) {\n check.fail(\n `setup.bundle.files.${packedPath}`,\n \"must name a file under skills/, automations/, or plugins/\",\n );\n }\n });\n\n // A setup script the archive does not carry is a create request the\n // service accepts and the first run fails on, and it is also the only\n // thing packed executable - naming an unpacked file makes that rule\n // unreachable.\n if (\n typeof bundle.setupScript === \"string\" &&\n !(bundle.setupScript in bundle.files)\n ) {\n check.fail(\"setup.bundle.setupScript\", \"must name a packed file\");\n }\n }\n\n if (!isRecord(bundle.config) || Object.keys(bundle.config).length === 0) {\n check.fail(\"setup.bundle.config\", \"must be a non-empty object\");\n } else {\n checkBundleConfig(check, bundle.config, \"setup.bundle.config\");\n }\n}\n\n/** Every string leaf of the config is a payload value: placeholders, no markup rule. */\nfunction checkBundleConfig(\n check: SetupChecker,\n node: unknown,\n path: string,\n): void {\n if (typeof node === \"string\") {\n check.templateValue(node, path);\n return;\n }\n if (Array.isArray(node)) {\n node.forEach((item, index) =>\n checkBundleConfig(check, item, `${path}[${index}]`),\n );\n return;\n }\n if (isRecord(node)) {\n Object.entries(node).forEach(([key, value]) =>\n checkBundleConfig(check, value, `${path}.${key}`),\n );\n return;\n }\n if (node !== null && typeof node !== \"number\" && typeof node !== \"boolean\") {\n check.fail(\n path,\n \"must be a string, number, boolean, null, array or object\",\n );\n }\n}\n\nfunction checkMode(\n check: SetupChecker,\n setup: Rec,\n kinds: string[],\n commonFieldNames: string[],\n): 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 // A direct entry produces one of three things: a prompt, a script bundle\n // the host packs and uploads, or a selectable set of action variants.\n // More than one would be ambiguous, and none is nothing to create.\n const hasPrompt = setup.prompt !== undefined;\n const hasBundle = setup.bundle !== undefined;\n const hasActions = setup.actions !== undefined;\n const variants = [hasPrompt, hasBundle, hasActions].filter(Boolean);\n if (variants.length !== 1) {\n check.fail(\n \"setup\",\n \"must declare exactly one of prompt, bundle or actions for direct setup\",\n );\n } else if (hasBundle) {\n checkBundle(check, setup.bundle);\n } else if (hasActions) {\n checkActions(check, setup.actions, commonFieldNames);\n } else {\n check.templateValue(setup.prompt, \"setup.prompt\");\n }\n // A direct entry may carry a fallback-conversation seed for deployments\n // that cannot run the direct path, held to the same rules as an assisted\n // message.\n if (setup.message !== undefined) checkMessage(check, setup.message);\n\n if (kinds.length === 0) {\n check.fail(\n \"setup.form.triggers\",\n \"must declare at least one trigger kind\",\n );\n }\n if (kinds.includes(\"event\") && !setupSuppliesEventSource(setup)) {\n check.fail(\n \"setup.form.triggers.event\",\n \"must declare an event source field or repository picker\",\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, \"bundle\", \"setup\", \"is only allowed for direct setup\");\n check.absent(setup, \"actions\", \"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.version !== undefined &&\n (typeof candidate.version !== \"string\" ||\n !TEMPLATE_VERSION_PATTERN.test(candidate.version))\n ) {\n check.fail(\"version\", \"must be a semantic version\");\n }\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, fieldNames } = checkForm(check, setup.form);\n checkMode(check, setup, kinds, fieldNames);\n\n return { valid: check.errors.length === 0, errors: check.errors };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SETUP_PLACEHOLDER_NAMESPACES as e } from "./types.js";
|
|
2
2
|
//#region src/manifests/manifest-validation.ts
|
|
3
|
-
var t = /^[a-z0-9]+(-[a-z0-9]+)*$/, n = /^[a-z][A-Za-z0-9]*$/, r = /<[A-Za-z/!]/, i = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/, a = /^[A-Za-z0-9 ._/-]+$/, o = /^[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/, s = /^(skills|automations)\/[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/, c = RegExp(`\\{\\{(?!(?:${e.join("|")})\\.[A-Za-z0-9_.]+\\}\\})`), l = ["direct", "assisted"], u = [
|
|
3
|
+
var t = /^[a-z0-9]+(-[a-z0-9]+)*$/, n = /^[a-z][A-Za-z0-9]*$/, r = /<[A-Za-z/!]/, i = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/, a = /^[A-Za-z0-9 ._/-]+$/, o = /^[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/, s = /^(skills|automations|plugins)\/[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/, c = RegExp(`\\{\\{(?!(?:${e.join("|")})\\.[A-Za-z0-9_.]+\\}\\})`), l = ["direct", "assisted"], u = [
|
|
4
4
|
"text",
|
|
5
5
|
"textarea",
|
|
6
6
|
"select",
|
|
@@ -191,7 +191,7 @@ function N(e, t) {
|
|
|
191
191
|
return;
|
|
192
192
|
}
|
|
193
193
|
(typeof t.version != "string" || !i.test(t.version)) && e.fail("setup.bundle.version", "must be a semantic version"), b(t.entrypoint) || e.fail("setup.bundle.entrypoint", "must be a plain command that stays inside the archive"), t.setupScript !== void 0 && !y(t.setupScript, o) && e.fail("setup.bundle.setupScript", "must be a relative path"), t.timeout !== void 0 && !_(t.timeout, 1) && e.fail("setup.bundle.timeout", "must be a positive integer"), !h(t.files) || Object.keys(t.files).length === 0 ? e.fail("setup.bundle.files", "must be a non-empty object") : (Object.entries(t.files).forEach(([t, n]) => {
|
|
194
|
-
y(t, o) || e.fail(`setup.bundle.files.${t}`, "is not a packed path"), t === "config.json" && e.fail(`setup.bundle.files.${t}`, "is the name the rendered config is packed under"), y(n, s) || e.fail(`setup.bundle.files.${t}`, "must name a file under skills
|
|
194
|
+
y(t, o) || e.fail(`setup.bundle.files.${t}`, "is not a packed path"), t === "config.json" && e.fail(`setup.bundle.files.${t}`, "is the name the rendered config is packed under"), y(n, s) || e.fail(`setup.bundle.files.${t}`, "must name a file under skills/, automations/, or plugins/");
|
|
195
195
|
}), typeof t.setupScript == "string" && !(t.setupScript in t.files) && e.fail("setup.bundle.setupScript", "must name a packed file")), !h(t.config) || Object.keys(t.config).length === 0 ? e.fail("setup.bundle.config", "must be a non-empty object") : P(e, t.config, "setup.bundle.config");
|
|
196
196
|
}
|
|
197
197
|
function P(e, t, n) {
|