@openhands/agent-canvas 1.15.0 → 1.16.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 +15 -1
- package/README.windows.md +2 -2
- package/build/assets/{acp-providers-BKvmTf82.js → acp-providers-CX3Lh9gj.js} +1 -1
- package/build/assets/active-backend-context-CrHTlgvN.js +2 -0
- package/build/assets/{agent-context-settings-D3PjSTU1.js → agent-context-settings-DSZlXrLj.js} +1 -1
- package/build/assets/{agent-profiles-settings-D4cY5U2T.js → agent-profiles-settings-Dzgb7G9z.js} +1 -1
- package/build/assets/agent-server-conversation-service.api-tnqNjbpE.js +86 -0
- package/build/assets/agent-settings-DLtsqaOs.js +2 -0
- package/build/assets/agent-settings-fFvR-XC2.js +1 -0
- package/build/assets/alert-banner-HP6mX-Vr.js +1 -0
- package/build/assets/{api-error-message-BJyfWp6p.js → api-error-message-B-XdSk3b.js} +1 -1
- package/build/assets/api-key-entry-screen-qTzrmJcr.js +1 -0
- package/build/assets/{app-settings-CbHqzQus.js → app-settings-dbnneVaV.js} +1 -1
- package/build/assets/automation-detail-BmwlCUAB.js +3 -0
- package/build/assets/{automation-export-BRopEHMu.js → automation-export-D3a3of4G.js} +1 -1
- package/build/assets/{automation-git-sync-CzyS4cn1.js → automation-git-sync-CprN5DcU.js} +1 -1
- package/build/assets/automation-setup-route-C40kXjMY.js +1 -0
- package/build/assets/{automation-templates-C_0FZgLG.js → automation-templates-BRppNh99.js} +1 -1
- package/build/assets/automations-list-DuNcRawl.js +1 -0
- package/build/assets/{back-nav-button-Dm9tIjVf.js → back-nav-button-Cjl_hoxq.js} +1 -1
- package/build/assets/backend-form-modal-lhGwzXFI.js +1 -0
- package/build/assets/{backend-synced-settings-badge-3fOwg6Bd.js → backend-synced-settings-badge-DPkz30BE.js} +1 -1
- package/build/assets/{badge-D4SqUCsR.js → badge-BU3S0VtE.js} +1 -1
- package/build/assets/{base-modal-C7_BDl_U.js → base-modal-D_L0oEbG.js} +1 -1
- package/build/assets/{bot-C-0Wu7vQ.js → bot-dMYHVfYM.js} +1 -1
- package/build/assets/{brand-button-Dxv6PDeN.js → brand-button-BAfk4wGP.js} +1 -1
- package/build/assets/browser-DSAo0tz1.js +46 -0
- package/build/assets/{browser-tab-BAl4ckJE.js → browser-tab-C9vy56R5.js} +1 -1
- package/build/assets/canvas-extension-page-dx1gFrfW.js +1 -0
- package/build/assets/canvas-extensions-8A-XhpgP.js +1 -0
- package/build/assets/canvas-extensions-runtime-2_x5Ezmi.js +1 -0
- package/build/assets/{chat-send-button-DWwR2cgI.js → chat-send-button-MUQqCZCS.js} +1 -1
- package/build/assets/check-CS0vmpQQ.js +1 -0
- package/build/assets/chevron-down-e1QBpjVy.js +1 -0
- package/build/assets/chevron-right-ZG4R5G4Q.js +1 -0
- package/build/assets/circle-check-DzWLNsbE.js +1 -0
- package/build/assets/{circle-plus-check-toggle-CBh_qomE.js → circle-plus-check-toggle-BO_kFZt3.js} +1 -1
- package/build/assets/{cloud-funnel-analytics-287iIERo.js → cloud-funnel-analytics-CztBCCPp.js} +1 -1
- package/build/assets/{cog-C4rrw-ZK.js → cog-D-MPQW6G.js} +1 -1
- package/build/assets/command-menu--UIlGL72.js +1 -0
- package/build/assets/{commits-tab-DZtJgaDM.js → commits-tab-AnZwLvh-.js} +1 -1
- package/build/assets/{condenser-settings-BcNmYR4s.js → condenser-settings-DmEOje-7.js} +1 -1
- package/build/assets/{confirmation-modal-Bk4JRcCM.js → confirmation-modal-Dv1ktp8K.js} +1 -1
- package/build/assets/{context-menu-list-item-lVYETtY5.js → context-menu-list-item-I86vKcmM.js} +1 -1
- package/build/assets/conversation-BbGrAO4Z.js +93 -0
- package/build/assets/conversation-mYT6NAoj.js +1 -0
- package/build/assets/conversation-panel-mYT6NAoj.js +1 -0
- package/build/assets/conversation-state-store-B0ImPLHO.js +1 -0
- package/build/assets/{conversation-tab-empty-state-HJtkmHZj.js → conversation-tab-empty-state-FIbh_lc8.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-Cjkswvnj.js → copy-to-clipboard-button-Ca8iSkkA.js} +1 -1
- package/build/assets/{device-verify-EZhHhBT7.js → device-verify-Bhn2e_Ye.js} +1 -1
- package/build/assets/{dropdown-classes-DJe-E6MC.js → dropdown-classes-Bc1djN0-.js} +1 -1
- package/build/assets/{edit-automation-modal-D-urtv8n.js → edit-automation-modal-DadGbJ2u.js} +1 -1
- package/build/assets/empty-state-BoGVDecT.js +1 -0
- package/build/assets/{entry.client-C7Bi2tkU.js → entry.client-CqyPPjOq.js} +2 -2
- package/build/assets/{enum-filter-dropdown-DliX_Lo0.js → enum-filter-dropdown-Bgca129f.js} +1 -1
- package/build/assets/{environment-switch-overlay-CEKrFiMw.js → environment-switch-overlay-BmBRT7gv.js} +1 -1
- package/build/assets/{error-state-BALXiBNy.js → error-state-Body8Ngd.js} +1 -1
- package/build/assets/extensions-hub-CcDqq_vR.js +1 -0
- package/build/assets/extensions-navigation-Cr4yzYk4.js +1 -0
- package/build/assets/{external-link-DFpYunfj.js → external-link-DKUlnCQV.js} +1 -1
- package/build/assets/files-tab-D4o2VyE_.js +1 -0
- package/build/assets/{form-control-classes-CGw40z5h.js → form-control-classes-Bkh5FGrD.js} +1 -1
- package/build/assets/format-model-name-CasAP3nd.js +1 -0
- package/build/assets/get-git-path-ChKDVHZp.js +1 -0
- package/build/assets/{git-repo-dropdown-ai8qaNkD.js → git-repo-dropdown-4ROKl2cB.js} +1 -1
- package/build/assets/git-repo-dropdown-BkqzkMmM.js +1 -0
- package/build/assets/{highlighted-source-view-C3sxykQi.js → highlighted-source-view-BFRxGT_Q.js} +1 -1
- package/build/assets/home-ChpSuepX.js +1 -0
- package/build/assets/home-DIsB440S.js +1 -0
- package/build/assets/home-automation-run-tooltip-BVNDWjAH.js +1 -0
- package/build/assets/home-store-CY9Ej0ux.js +1 -0
- package/build/assets/index-home-BdlrFIif.js +1 -0
- package/build/assets/info-B6RQawoW.js +1 -0
- package/build/assets/install-server-modal-Dpy89p4g.js +1 -0
- package/build/assets/kebab-menu-item-content-D8hSNGmm.js +1 -0
- package/build/assets/{key-Cn5za3rg.js → key-BmVyxs-2.js} +1 -1
- package/build/assets/{launch-C1ieiOGe.js → launch-IrTDEFCs.js} +1 -1
- package/build/assets/list-filter-DsEK7NFC.js +1 -0
- package/build/assets/{list-todo-Cuu-STFc.js → list-todo-apgLVjMw.js} +1 -1
- package/build/assets/llm-not-configured-banner-CIFABh3K.js +27 -0
- package/build/assets/llm-settings-B9juXhIa.js +1 -0
- package/build/assets/llm-settings-De1d5dfr.js +1 -0
- package/build/assets/llm-subscription-service-BpJ0ouQo.js +1 -0
- package/build/assets/loader-circle-CC1au6hc.js +1 -0
- package/build/assets/{loading-spinner-0L3ZTToZ.js → loading-spinner-BY9N3pOe.js} +1 -1
- package/build/assets/manage-backends-modal-BrPV3oB-.js +1 -0
- package/build/assets/manifest-80fb1c29.js +1 -0
- package/build/assets/{manifest-subpage-layout-BGhiUQbA.js → manifest-subpage-layout-CAOYzrYp.js} +1 -1
- package/build/assets/{map-provider-B9LTm23I.js → map-provider-Cu3Zgumb.js} +1 -1
- package/build/assets/markdown-renderer-BzTlxI8x.js +8 -0
- package/build/assets/{mcp-CKbR4Vft.js → mcp-BTs_SXfZ.js} +1 -1
- package/build/assets/{mcp-marketplace-utils-C13fFccR.js → mcp-marketplace-utils-AIBzzHTO.js} +1 -1
- package/build/assets/{mcp-page-Bm4K2NQq.js → mcp-page-BEBYqH_K.js} +2 -2
- package/build/assets/messages-DKV9cRc2.js +41 -0
- package/build/assets/{modal-body-CMOc2tLl.js → modal-body-BxZjsju9.js} +1 -1
- package/build/assets/{modal-classes-BAb4Y_BG.js → modal-classes-C8eycCwG.js} +1 -1
- package/build/assets/{modal-close-button-CkJ0Ktjj.js → modal-close-button-DDzdRvCs.js} +1 -1
- package/build/assets/{mouse-pointer-click-CsgRs_-r.js → mouse-pointer-click-Co2uyaPA.js} +1 -1
- package/build/assets/onboarding-DV_OXoeP.js +1 -0
- package/build/assets/onboarding-modal-rkyBYkeQ.js +1 -0
- package/build/assets/{organization-service.api-C8XpQ0pM.js → organization-service.api-DrYNkEN_.js} +1 -1
- package/build/assets/{pencil-Clh1Wjvh.js → pencil-47jAZH_V.js} +1 -1
- package/build/assets/pin-By41Vl5J.js +1 -0
- package/build/assets/{planner-tab-DQvDU3ap.js → planner-tab-C9uZmhme.js} +1 -1
- package/build/assets/{plug-BuQhHSSG.js → plug-CG5HFcNG.js} +1 -1
- package/build/assets/plugins-management-service-BMJgC3Ga.js +1 -0
- package/build/assets/plus-C7Slq-0I.js +1 -0
- package/build/assets/profiles-service.api-ChoKrL0l.js +1 -0
- package/build/assets/providers-BhMcY5nv.js +1 -0
- package/build/assets/proxy-9Fe1v5na.js +1 -0
- package/build/assets/{puzzle-A9pGxxai.js → puzzle-JM_QaRm0.js} +1 -1
- package/build/assets/recommended-automations-launcher-6ABrI9Cy.js +1 -0
- package/build/assets/{refresh-cw-Bh69DyYO.js → refresh-cw-3q3Frrii.js} +1 -1
- package/build/assets/root-Dc8YmC9F.js +2 -0
- package/build/assets/root-VDaypvK4.css +1 -0
- package/build/assets/root-layout-CXkhSPYh.js +2 -0
- package/build/assets/schema-field-D-y9-LDb.js +1 -0
- package/build/assets/{sdk-section-page-HTffvm7Q.js → sdk-section-page-BlFiizlG.js} +1 -1
- package/build/assets/{secret-form-HTUbYw5o.js → secret-form-BB7the8W.js} +1 -1
- package/build/assets/secrets-service-ByZVENbp.js +1 -0
- package/build/assets/{secrets-settings-BizaTEr1.js → secrets-settings-B_GpxKW2.js} +1 -1
- package/build/assets/{settings-BlmrkwRi.js → settings-C0EWuBtA.js} +1 -1
- package/build/assets/settings-CKqk8ZnH.js +1 -0
- package/build/assets/{settings-dropdown-input-tM0A0ipy.js → settings-dropdown-input-BcwylHs2.js} +1 -1
- package/build/assets/{settings-index-CKq0b0Vg.js → settings-index-5w5UW2K3.js} +1 -1
- package/build/assets/{settings-input-C03KUoSC.js → settings-input-Db-1g8Ql.js} +1 -1
- package/build/assets/{settings-list-classes-BJ0g8rWj.js → settings-list-classes-BzeSZbF2.js} +1 -1
- package/build/assets/{settings-modal-AzEF1QPP.js → settings-modal-DfJ3tcJQ.js} +1 -1
- package/build/assets/settings-service.api-DJ1r62Zr.js +1 -0
- package/build/assets/{settings-switch-CQE0EGC-.js → settings-switch-CS-dJDmA.js} +1 -1
- package/build/assets/{settings-utils-ClYOkbbI.js → settings-utils-UYpEdPuD.js} +1 -1
- package/build/assets/shared-conversation-CA5ISEDy.js +1 -0
- package/build/assets/{shield-check-CFDViW82.js → shield-check-D2aCRd16.js} +1 -1
- package/build/assets/{sidebar-layout-D3hE08wK.js → sidebar-layout-D6fS8-Gl.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-BOtyJHwE.js → sidebar-mobile-menu-toggle-C_fb0Jki.js} +1 -1
- package/build/assets/sidebar-nav-link-DQQcMf1A.js +1 -0
- package/build/assets/{sidebar-onboarding-checklist-storage-3qYflszY.js → sidebar-onboarding-checklist-storage-BBkeI6Bp.js} +1 -1
- package/build/assets/sidebar-store-DGqHkVLw.js +1 -0
- package/build/assets/{skill-card-pill-row-CFxjoqxn.js → skill-card-pill-row-B27-xyig.js} +1 -1
- package/build/assets/skill-enablement-DXeaImBz.js +1 -0
- package/build/assets/skill-filter-w__3UCEE.js +2 -0
- package/build/assets/{skill-icon-badge-CPQJ6A-I.js → skill-icon-badge-RQkq8wvl.js} +1 -1
- package/build/assets/skill-scope-B42H-XOc.js +1 -0
- package/build/assets/skills-plugins-tgF8EiXC.js +1 -0
- package/build/assets/skills-settings-BgJ9PaOe.js +1 -0
- package/build/assets/{styled-tooltip-Dl06rkpY.js → styled-tooltip-C4jf5Fv9.js} +1 -1
- package/build/assets/{task-list-tab-04GNQuii.js → task-list-tab-C5zcaktH.js} +1 -1
- package/build/assets/{terminal-Cj0iHIW7.js → terminal-CNElN42a.js} +2 -2
- package/build/assets/{toggle-switch-Fd_QGz0r.js → toggle-switch-ChOLXv2n.js} +1 -1
- package/build/assets/{trash-2-Dl8_RGz0.js → trash-2-D7K26eDO.js} +1 -1
- package/build/assets/{trash-_RMt7Ayc.js → trash-D-HYiVYM.js} +1 -1
- package/build/assets/{triangle-alert-SM-q4NU_.js → triangle-alert-CtdXWHUI.js} +1 -1
- package/build/assets/{typography-SgFy466J.js → typography-v1KN0tzi.js} +1 -1
- package/build/assets/usage-tab-CVDffLPt.js +1 -0
- package/build/assets/use-acp-credential-form-XIQmpX6M.js +1 -0
- package/build/assets/{use-activate-agent-profile-B2NS8nA5.js → use-activate-agent-profile-BLfmvDiG.js} +1 -1
- package/build/assets/use-agent-profiles-Bd9Bvvp1.js +1 -0
- package/build/assets/{use-automation-health-BxXdzZMP.js → use-automation-health-E6NZi9rb.js} +1 -1
- package/build/assets/{use-automations-zYb0dUny.js → use-automations-xijQKIl9.js} +1 -1
- package/build/assets/{use-can-manage-org-profiles-BWMahtUh.js → use-can-manage-org-profiles-CrJP5262.js} +1 -1
- package/build/assets/use-canvas-extensions-Bi693ujJ.js +1 -0
- package/build/assets/{use-cloud-current-user-id-CPHMDG-C.js → use-cloud-current-user-id-CDfAHpPX.js} +1 -1
- package/build/assets/use-config-A9QovgXO.js +1 -0
- package/build/assets/{use-create-conversation-DwN5vv2f.js → use-create-conversation-Dx3l7mFZ.js} +1 -1
- package/build/assets/use-create-secret-B9cUFWRG.js +1 -0
- package/build/assets/{use-get-secrets-BT4ihRwj.js → use-get-secrets-K3jmk-LH.js} +1 -1
- package/build/assets/use-is-authed-nTBcM7dE.js +1 -0
- package/build/assets/use-llm-configured-BV9nZ1_j.js +1 -0
- package/build/assets/use-llm-profiles-BO-P4Oyo.js +1 -0
- package/build/assets/use-manifest-capabilities-Cw_flwEz.js +1 -0
- package/build/assets/use-onboarding-completion-D8U7k4Qb.js +1 -0
- package/build/assets/use-pinned-home-route-CckOZrmb.js +1 -0
- package/build/assets/use-plugins-marketplace-7i94Zu3Z.js +1 -0
- package/build/assets/use-save-agent-profile-BUjSsDXK.js +1 -0
- package/build/assets/{use-save-settings-CUZW6yXP.js → use-save-settings-DYqkKv7T.js} +1 -1
- package/build/assets/{use-settings-C5VhGpqd.js → use-settings-DSXLbvBl.js} +1 -1
- package/build/assets/{use-settings-nav-items-DHaUu1Dg.js → use-settings-nav-items-CwRw-CmX.js} +1 -1
- package/build/assets/use-tracking-D53y3TH9.js +3 -0
- package/build/assets/{use-user-conversation-DT0_QCnL.js → use-user-conversation-B9Gebw_g.js} +1 -1
- package/build/assets/{useInfiniteQuery-CgeUQPfs.js → useInfiniteQuery-C926xzY4.js} +1 -1
- package/build/assets/{useMutation-DFnzkf6f.js → useMutation-B-qc391N.js} +1 -1
- package/build/assets/{useQueries-BhbrGEf1.js → useQueries-DlbhlH9I.js} +1 -1
- package/build/assets/{useQuery-BXWbZBZl.js → useQuery-BSTgq1rl.js} +1 -1
- package/build/assets/utils-CN5ZfZy1.js +1 -0
- package/build/assets/{vendor~conversation-panel~conversation-CTvDDiXg.js → vendor~conversation-panel~conversation-C8Fn4XOf.js} +1 -1
- package/build/assets/{vendor~entry.client-BFE7Llz9.js → vendor~entry.client-CoCfUXUF.js} +1 -1
- package/build/assets/{vendor~entry.client-BaKt_PIp.js → vendor~entry.client-DA2izTjq.js} +1 -1
- package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kepq2zme-ZixYGy6E.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-DqZDXfg2.js} +1 -1
- package/build/assets/{vendor~index-home~home~conversation-panel~conversation-BTyukeM-.js → vendor~index-home~home~conversation-panel~conversation-hWywRBaR.js} +1 -1
- package/build/assets/{vendor~root-layout-BlUaZ18v.js → vendor~root-layout-C9Ju9DQg.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-BYAWJwQX.js → vendor~root-layout~conversation-panel~conversation-BMbMgaGu.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-CHaLEBVR.js → vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-BWir3rJs.js} +1 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-j5MFqfSy.js +1 -0
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-cDuKr-WD.js +1 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iw7io29p-Dz-MAyNb.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-Chf7vmKB.js} +1 -1
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hjcjabwg-Dtu7BpYk.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~nj1hli3r-DP9wmsjo.js} +2 -2
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-DonTKfQD.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-CUmIwQCN.js} +117 -13
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-BgxDvUcf.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-C7HiY4Ae.js} +42 -3
- package/build/assets/{verification-settings-Bj6bo097.js → verification-settings-gw_q6vkL.js} +1 -1
- package/build/assets/{wrench-hi7Q13dF.js → wrench-CUEI1krB.js} +1 -1
- package/build/assets/{x-DkgltWa0.js → x-DJdhbdmt.js} +1 -1
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +32 -16
- package/build/locales/ca/openhands.json +32 -16
- package/build/locales/de/openhands.json +32 -16
- package/build/locales/en/openhands.json +32 -16
- package/build/locales/es/openhands.json +32 -16
- package/build/locales/fr/openhands.json +32 -16
- package/build/locales/it/openhands.json +32 -16
- package/build/locales/ja/openhands.json +32 -16
- package/build/locales/ko-KR/openhands.json +32 -16
- package/build/locales/no/openhands.json +32 -16
- package/build/locales/pt/openhands.json +32 -16
- package/build/locales/tr/openhands.json +32 -16
- package/build/locales/uk/openhands.json +32 -16
- package/build/locales/zh-CN/openhands.json +32 -16
- package/build/locales/zh-TW/openhands.json +32 -16
- package/config/defaults.json +9 -5
- package/dist/api/agent-profiles-service/profile-field-support.d.ts +26 -0
- package/dist/api/agent-server-adapter.cjs +3 -3
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.js +118 -116
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/agent-server-compatibility.cjs +1 -1
- package/dist/api/agent-server-compatibility.cjs.map +1 -1
- package/dist/api/agent-server-compatibility.d.ts +21 -0
- package/dist/api/agent-server-compatibility.js +52 -38
- package/dist/api/agent-server-compatibility.js.map +1 -1
- package/dist/api/agent-server-config.cjs +1 -1
- package/dist/api/agent-server-config.cjs.map +1 -1
- package/dist/api/agent-server-config.d.ts +26 -0
- package/dist/api/agent-server-config.js +18 -5
- package/dist/api/agent-server-config.js.map +1 -1
- package/dist/api/canvas-extensions-service.cjs +1 -0
- package/dist/api/canvas-extensions-service.d.ts +22 -0
- package/dist/api/canvas-extensions-service.js +4 -0
- package/dist/api/cloud/conversation-service.api.cjs +1 -1
- package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
- package/dist/api/cloud/conversation-service.api.d.ts +6 -0
- package/dist/api/cloud/conversation-service.api.js +14 -6
- package/dist/api/cloud/conversation-service.api.js.map +1 -1
- package/dist/api/conversation-file-upload.api.cjs +1 -1
- package/dist/api/conversation-file-upload.api.js +10 -10
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +11 -0
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +129 -118
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/event-service/event-service.api.cjs +1 -1
- package/dist/api/event-service/event-service.api.js +12 -12
- package/dist/api/git-service/agent-server-git-service.api.cjs +1 -1
- package/dist/api/git-service/agent-server-git-service.api.js +8 -8
- package/dist/api/runtime-service/agent-server-runtime-service.cjs +1 -1
- package/dist/api/runtime-service/agent-server-runtime-service.js +8 -8
- package/dist/api/settings-service/settings-service.api.cjs +1 -1
- package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
- package/dist/api/settings-service/settings-service.api.d.ts +3 -2
- package/dist/api/settings-service/settings-service.api.js +2 -1
- package/dist/api/settings-service/settings-service.api.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/event-group.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message-components/event-group.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/event-group.js +40 -36
- package/dist/components/conversation-events/chat/event-message-components/event-group.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 +114 -104
- package/dist/components/features/automations/automation-card.js.map +1 -1
- package/dist/components/features/automations/detail/run-phase.cjs +2 -0
- package/dist/components/features/automations/detail/run-phase.cjs.map +1 -0
- package/dist/components/features/automations/detail/run-phase.d.ts +89 -0
- package/dist/components/features/automations/detail/run-phase.js +72 -0
- package/dist/components/features/automations/detail/run-phase.js.map +1 -0
- package/dist/components/features/backends/backend-form-modal.cjs +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
- package/dist/components/features/backends/backend-form-modal.js +5 -11
- package/dist/components/features/backends/backend-form-modal.js.map +1 -1
- package/dist/components/features/canvas-extensions/add-canvas-extension-modal.d.ts +6 -0
- package/dist/components/features/canvas-extensions/canvas-extension-card.d.ts +9 -0
- package/dist/components/features/canvas-extensions/canvas-extensions-runtime.cjs +2 -0
- package/dist/components/features/canvas-extensions/canvas-extensions-runtime.cjs.map +1 -0
- package/dist/components/features/canvas-extensions/canvas-extensions-runtime.d.ts +23 -0
- package/dist/components/features/canvas-extensions/canvas-extensions-runtime.js +19 -0
- package/dist/components/features/canvas-extensions/canvas-extensions-runtime.js.map +1 -0
- package/dist/components/features/chat/chat-interface.cjs +2 -2
- package/dist/components/features/chat/chat-interface.cjs.map +1 -1
- package/dist/components/features/chat/chat-interface.js +171 -168
- package/dist/components/features/chat/chat-interface.js.map +1 -1
- package/dist/components/features/chat/chat-markdown-path-code.cjs +3 -0
- package/dist/components/features/chat/chat-markdown-path-code.cjs.map +1 -0
- package/dist/components/features/chat/chat-markdown-path-code.d.ts +27 -0
- package/dist/components/features/chat/chat-markdown-path-code.js +72 -0
- package/dist/components/features/chat/chat-markdown-path-code.js.map +1 -0
- package/dist/components/features/chat/path-component.cjs +1 -1
- package/dist/components/features/chat/path-component.cjs.map +1 -1
- package/dist/components/features/chat/path-component.d.ts +8 -2
- package/dist/components/features/chat/path-component.js +33 -21
- package/dist/components/features/chat/path-component.js.map +1 -1
- package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.cjs +1 -1
- package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.cjs.map +1 -1
- package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.js +38 -43
- package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.js.map +1 -1
- package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.cjs +1 -1
- package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.cjs.map +1 -1
- package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.d.ts +8 -5
- package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.js +22 -16
- package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.js.map +1 -1
- package/dist/components/features/chat/user-message-body.cjs +1 -1
- package/dist/components/features/chat/user-message-body.cjs.map +1 -1
- package/dist/components/features/chat/user-message-body.d.ts +4 -0
- package/dist/components/features/chat/user-message-body.js +30 -24
- package/dist/components/features/chat/user-message-body.js.map +1 -1
- package/dist/components/features/conversation/conversation-overview-skills-panel.cjs +1 -1
- package/dist/components/features/conversation/conversation-overview-skills-panel.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-overview-skills-panel.js +63 -81
- package/dist/components/features/conversation/conversation-overview-skills-panel.js.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +50 -50
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.cjs +1 -1
- package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.d.ts +1 -1
- package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.js +3 -3
- package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.js.map +1 -1
- package/dist/components/features/conversation-panel/skills-modal.cjs +1 -1
- package/dist/components/features/conversation-panel/skills-modal.cjs.map +1 -1
- package/dist/components/features/conversation-panel/skills-modal.js +29 -28
- package/dist/components/features/conversation-panel/skills-modal.js.map +1 -1
- package/dist/components/features/files-tab/file-content-viewer.cjs +1 -1
- package/dist/components/features/files-tab/file-content-viewer.js +5 -5
- 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 +51 -29
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
- package/dist/components/features/onboarding/onboarding-host.d.ts +3 -4
- package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +5 -9
- package/dist/components/features/settings/acp-auth-status-banner.d.ts +23 -6
- 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 +1 -0
- package/dist/components/features/settings/llm-profiles/provider-connection-modal.cjs +1 -1
- package/dist/components/features/settings/llm-profiles/provider-connection-modal.js +3 -0
- package/dist/components/features/settings/sdk-settings/field-help.cjs +1 -1
- package/dist/components/features/settings/sdk-settings/field-help.cjs.map +1 -1
- package/dist/components/features/settings/sdk-settings/field-help.d.ts +1 -1
- package/dist/components/features/settings/sdk-settings/field-help.js +1 -1
- package/dist/components/features/settings/sdk-settings/field-help.js.map +1 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.js +6 -6
- package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
- package/dist/components/features/sidebar/sidebar-nav-link.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-nav-link.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-nav-link.d.ts +10 -1
- package/dist/components/features/sidebar/sidebar-nav-link.js +54 -36
- package/dist/components/features/sidebar/sidebar-nav-link.js.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.js +143 -120
- 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 +1 -1
- package/dist/components/features/sidebar/sidebar.js.map +1 -1
- package/dist/components/features/skills/build-skill-pills.cjs +1 -1
- package/dist/components/features/skills/build-skill-pills.cjs.map +1 -1
- package/dist/components/features/skills/build-skill-pills.js +60 -52
- package/dist/components/features/skills/build-skill-pills.js.map +1 -1
- package/dist/components/features/skills/extensions-navigation.cjs +1 -1
- package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
- package/dist/components/features/skills/extensions-navigation.js +54 -43
- package/dist/components/features/skills/extensions-navigation.js.map +1 -1
- package/dist/components/features/skills/skill-filter.cjs +1 -1
- package/dist/components/features/skills/skill-filter.cjs.map +1 -1
- package/dist/components/features/skills/skill-filter.d.ts +8 -3
- package/dist/components/features/skills/skill-filter.js +69 -52
- package/dist/components/features/skills/skill-filter.js.map +1 -1
- package/dist/components/shared/modals/settings/settings-form.cjs +1 -1
- package/dist/components/shared/modals/settings/settings-form.js +8 -8
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +9 -5
- package/dist/config/defaults.js.map +1 -1
- package/dist/contexts/conversation-websocket-context.cjs +3 -3
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js +5 -5
- package/dist/extensions/canvas-extension-module-loader.d.ts +11 -0
- package/dist/hooks/mutation/use-manage-canvas-extensions.d.ts +12 -0
- package/dist/hooks/query/concurrency-limiter.cjs +2 -0
- package/dist/hooks/query/concurrency-limiter.cjs.map +1 -0
- package/dist/hooks/query/concurrency-limiter.d.ts +22 -0
- package/dist/hooks/query/concurrency-limiter.js +29 -0
- package/dist/hooks/query/concurrency-limiter.js.map +1 -0
- package/dist/hooks/query/query-keys.cjs.map +1 -1
- package/dist/hooks/query/query-keys.d.ts +4 -0
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-active-conversation.cjs +1 -1
- package/dist/hooks/query/use-active-conversation.js +4 -4
- package/dist/hooks/query/use-automations.cjs.map +1 -1
- package/dist/hooks/query/use-automations.js.map +1 -1
- package/dist/hooks/query/use-backends-health.cjs +1 -1
- package/dist/hooks/query/use-backends-health.cjs.map +1 -1
- package/dist/hooks/query/use-backends-health.d.ts +1 -1
- package/dist/hooks/query/use-backends-health.js +50 -64
- package/dist/hooks/query/use-backends-health.js.map +1 -1
- package/dist/hooks/query/use-canvas-extensions.cjs +1 -0
- package/dist/hooks/query/use-canvas-extensions.d.ts +5 -0
- package/dist/hooks/query/use-canvas-extensions.js +3 -0
- package/dist/hooks/query/use-commit-changes.cjs +1 -1
- package/dist/hooks/query/use-commit-changes.js +4 -4
- package/dist/hooks/query/use-latest-automation-runs.cjs +1 -1
- package/dist/hooks/query/use-latest-automation-runs.js +1 -0
- package/dist/hooks/query/use-paginated-conversations.cjs +1 -1
- package/dist/hooks/query/use-paginated-conversations.cjs.map +1 -1
- package/dist/hooks/query/use-paginated-conversations.js +19 -16
- package/dist/hooks/query/use-paginated-conversations.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 +17 -10
- package/dist/hooks/query/use-search-providers.js.map +1 -1
- package/dist/hooks/query/use-unified-get-git-changes.cjs +1 -1
- package/dist/hooks/query/use-unified-get-git-changes.js +4 -4
- package/dist/hooks/query/use-unified-git-commits.cjs +1 -1
- package/dist/hooks/query/use-unified-git-commits.js +4 -4
- package/dist/hooks/query/use-unified-git-diff.cjs +1 -1
- package/dist/hooks/query/use-unified-git-diff.js +4 -4
- package/dist/hooks/query/use-unified-vscode-url.cjs +1 -1
- package/dist/hooks/query/use-unified-vscode-url.cjs.map +1 -1
- package/dist/hooks/query/use-unified-vscode-url.d.ts +1 -0
- package/dist/hooks/query/use-unified-vscode-url.js +40 -26
- package/dist/hooks/query/use-unified-vscode-url.js.map +1 -1
- package/dist/hooks/query/use-workspace-file-content.cjs +1 -1
- package/dist/hooks/query/use-workspace-file-content.js +5 -5
- package/dist/hooks/query/use-workspace-files.cjs +1 -1
- package/dist/hooks/query/use-workspace-files.js +6 -6
- package/dist/hooks/use-acp-credential-form.d.ts +6 -0
- package/dist/hooks/use-conversation-overview-git-diff-stats.cjs +1 -1
- package/dist/hooks/use-conversation-overview-git-diff-stats.js +4 -4
- package/dist/hooks/use-pinned-home-route.cjs +2 -0
- package/dist/hooks/use-pinned-home-route.cjs.map +1 -0
- package/dist/hooks/use-pinned-home-route.d.ts +33 -0
- package/dist/hooks/use-pinned-home-route.js +34 -0
- package/dist/hooks/use-pinned-home-route.js.map +1 -0
- package/dist/hooks/use-skill-enablement.cjs +2 -0
- package/dist/hooks/use-skill-enablement.cjs.map +1 -0
- package/dist/hooks/use-skill-enablement.d.ts +14 -0
- package/dist/hooks/use-skill-enablement.js +80 -0
- package/dist/hooks/use-skill-enablement.js.map +1 -0
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +29 -13
- 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 +538 -266
- package/dist/i18n/translation.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +15 -14
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/locales/ar/openhands.json +32 -16
- package/dist/locales/ca/openhands.json +32 -16
- package/dist/locales/de/openhands.json +32 -16
- package/dist/locales/en/openhands.json +32 -16
- package/dist/locales/es/openhands.json +32 -16
- package/dist/locales/fr/openhands.json +32 -16
- package/dist/locales/it/openhands.json +32 -16
- package/dist/locales/ja/openhands.json +32 -16
- package/dist/locales/ko-KR/openhands.json +32 -16
- package/dist/locales/no/openhands.json +32 -16
- package/dist/locales/pt/openhands.json +32 -16
- package/dist/locales/tr/openhands.json +32 -16
- package/dist/locales/uk/openhands.json +32 -16
- package/dist/locales/zh-CN/openhands.json +32 -16
- package/dist/locales/zh-TW/openhands.json +32 -16
- package/dist/manifests/automation-interface.cjs +1 -1
- package/dist/manifests/automation-interface.cjs.map +1 -1
- package/dist/manifests/automation-interface.d.ts +6 -0
- package/dist/manifests/automation-interface.js +11 -8
- package/dist/manifests/automation-interface.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs +45 -4
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.js +1 -1
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js +5 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +5 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +5 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +5 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.js +21 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.js +21 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.js +21 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.js +21 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.cjs +9 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.js +21 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.js +5 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs +30 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js +65 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +21 -9
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +2 -2
- package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js +40 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +74 -72
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.cjs +42 -3
- package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.js +22 -3
- package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-conversation.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-conversation.js +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.js +8 -7
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/index.js +2 -2
- package/dist/node_modules/lucide-react/dist/esm/icons/blocks.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/blocks.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/blocks.js +16 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/blocks.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.js +23 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/agent-settings.d.ts +10 -0
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.cjs.map +1 -1
- package/dist/routes/app-settings.js +7 -7
- package/dist/routes/files-tab.cjs +1 -1
- package/dist/routes/files-tab.cjs.map +1 -1
- package/dist/routes/files-tab.js +14 -14
- package/dist/routes/files-tab.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 +122 -114
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/services/canvas-ui.cjs +1 -1
- package/dist/services/canvas-ui.cjs.map +1 -1
- package/dist/services/canvas-ui.d.ts +5 -0
- package/dist/services/canvas-ui.js +24 -10
- package/dist/services/canvas-ui.js.map +1 -1
- package/dist/services/settings.cjs +1 -1
- package/dist/services/settings.cjs.map +1 -1
- package/dist/services/settings.js +3 -2
- package/dist/services/settings.js.map +1 -1
- package/dist/types/automation.cjs.map +1 -1
- package/dist/types/automation.d.ts +20 -0
- package/dist/types/automation.js.map +1 -1
- package/dist/types/canvas-extension.cjs +2 -0
- package/dist/types/canvas-extension.cjs.map +1 -0
- package/dist/types/canvas-extension.d.ts +77 -0
- package/dist/types/canvas-extension.js +6 -0
- package/dist/types/canvas-extension.js.map +1 -0
- package/dist/types/settings.d.ts +7 -0
- package/dist/ui/help-link.cjs +1 -1
- package/dist/ui/help-link.cjs.map +1 -1
- package/dist/ui/help-link.d.ts +6 -1
- package/dist/ui/help-link.js +32 -18
- package/dist/ui/help-link.js.map +1 -1
- package/dist/utils/acp-auth-display.d.ts +35 -0
- package/dist/utils/cache-utils.cjs +1 -1
- package/dist/utils/cache-utils.js +5 -5
- 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 +7 -3
- package/dist/utils/format-model-name.js +6 -11
- package/dist/utils/format-model-name.js.map +1 -1
- package/dist/utils/format-relative-time.cjs +1 -1
- package/dist/utils/format-relative-time.cjs.map +1 -1
- package/dist/utils/format-relative-time.d.ts +7 -0
- package/dist/utils/format-relative-time.js +7 -2
- package/dist/utils/format-relative-time.js.map +1 -1
- package/dist/utils/path-utils.cjs +1 -1
- package/dist/utils/path-utils.cjs.map +1 -1
- package/dist/utils/path-utils.d.ts +15 -3
- package/dist/utils/path-utils.js +29 -3
- package/dist/utils/path-utils.js.map +1 -1
- package/dist/utils/skill-enablement.cjs +2 -0
- package/dist/utils/skill-enablement.cjs.map +1 -0
- package/dist/utils/skill-enablement.d.ts +51 -0
- package/dist/utils/skill-enablement.js +31 -0
- package/dist/utils/skill-enablement.js.map +1 -0
- package/dist/utils/vscode-origin.cjs +2 -0
- package/dist/utils/vscode-origin.cjs.map +1 -0
- package/dist/utils/vscode-origin.d.ts +55 -0
- package/dist/utils/vscode-origin.js +27 -0
- package/dist/utils/vscode-origin.js.map +1 -0
- package/dist/utils/workspace-mode.d.ts +4 -0
- package/package.json +3 -3
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/check-translation-completeness.cjs +1 -0
- package/scripts/dev-extra-backend.mjs +28 -9
- package/scripts/dev-safe.mjs +81 -8
- package/scripts/dev-static.mjs +35 -37
- package/scripts/dev-with-automation.mjs +82 -1
- package/scripts/ingress.mjs +27 -1
- package/scripts/static-server.mjs +74 -1
- package/tools/canvas_ui_tool.py +19 -0
- package/build/assets/active-backend-context-DKFSMbn3.js +0 -2
- package/build/assets/agent-server-conversation-service.api-DozDKIW_.js +0 -86
- package/build/assets/agent-settings-351vXWc9.js +0 -2
- package/build/assets/agent-settings-Ce7BDZ6I.js +0 -1
- package/build/assets/alert-banner-Kyy1YWZU.js +0 -1
- package/build/assets/api-key-entry-screen-INIxqAMs.js +0 -1
- package/build/assets/automation-detail-DXDhUwPq.js +0 -3
- package/build/assets/automation-setup-route-FRr05f_g.js +0 -1
- package/build/assets/automations-list-CERuQWE6.js +0 -1
- package/build/assets/backend-form-modal-DK78-jn1.js +0 -1
- package/build/assets/browser-11etCQ04.js +0 -7
- package/build/assets/check-Cf2YoT90.js +0 -1
- package/build/assets/chevron-down-C3OQ-ehx.js +0 -1
- package/build/assets/chevron-right-CN1uUiJ1.js +0 -1
- package/build/assets/circle-check-g5yeGMd-.js +0 -1
- package/build/assets/command-menu-BZQ8S3Ke.js +0 -1
- package/build/assets/conversation-CchMzpGl.js +0 -1
- package/build/assets/conversation-Dpzftz57.js +0 -93
- package/build/assets/conversation-panel-CchMzpGl.js +0 -1
- package/build/assets/conversation-state-store-a9d2fxRc.js +0 -1
- package/build/assets/empty-state-CvaVahVr.js +0 -1
- package/build/assets/extensions-hub-CFduxBnk.js +0 -1
- package/build/assets/extensions-navigation-BeC224yX.js +0 -1
- package/build/assets/files-tab-CL3J9b3p.js +0 -1
- package/build/assets/format-model-name-BNPKVsIq.js +0 -1
- package/build/assets/get-git-path-DlAJa_i6.js +0 -1
- package/build/assets/git-repo-dropdown-DGMEhz7d.js +0 -1
- package/build/assets/home-BCGlNJCA.js +0 -1
- package/build/assets/home-DB1pRqTC.js +0 -1
- package/build/assets/home-automation-run-tooltip-CooFQRIG.js +0 -1
- package/build/assets/home-store-Dl1dPE58.js +0 -1
- package/build/assets/index-home-DB1pRqTC.js +0 -1
- package/build/assets/info-uYSVzX86.js +0 -1
- package/build/assets/install-server-modal-BbJdhzet.js +0 -1
- package/build/assets/kebab-menu-item-content-BYokkRHi.js +0 -1
- package/build/assets/list-filter-OFkpRrmi.js +0 -1
- package/build/assets/llm-not-configured-banner-BqqYnJ1t.js +0 -27
- package/build/assets/llm-settings-CnDbbmVW.js +0 -1
- package/build/assets/llm-settings-S8Yjg__1.js +0 -1
- package/build/assets/llm-subscription-service-BpPfzW4x.js +0 -1
- package/build/assets/loader-circle-nvrwthvj.js +0 -1
- package/build/assets/manage-backends-modal-BCUPswyl.js +0 -1
- package/build/assets/manifest-58597dde.js +0 -1
- package/build/assets/markdown-renderer-Cb2sBWtV.js +0 -8
- package/build/assets/messages-BTN5thLe.js +0 -40
- package/build/assets/onboarding-Cx_kaiD1.js +0 -1
- package/build/assets/onboarding-modal-vMwn7ihv.js +0 -1
- package/build/assets/plugins-management-service-BjYeF0b0.js +0 -1
- package/build/assets/plus-CEKne-Yp.js +0 -1
- package/build/assets/profiles-service.api-QB-T_u-g.js +0 -1
- package/build/assets/providers-FfSZ5TXP.js +0 -1
- package/build/assets/proxy-tcFL2yTQ.js +0 -1
- package/build/assets/recommended-automations-launcher-Bw8uC4V6.js +0 -1
- package/build/assets/root-BLeQfBEq.css +0 -1
- package/build/assets/root-ZKKYPR1Z.js +0 -2
- package/build/assets/root-layout-luJoE9IG.js +0 -2
- package/build/assets/schema-field-Csw5fhtN.js +0 -1
- package/build/assets/secrets-service-BTor9uAU.js +0 -1
- package/build/assets/settings-DcNPxz0v.js +0 -1
- package/build/assets/settings-service.api-B2agVfjL.js +0 -1
- package/build/assets/shared-conversation-B55pCyBG.js +0 -1
- package/build/assets/sidebar-nav-link-CPzhyHQg.js +0 -1
- package/build/assets/sidebar-store-DtpU7zaI.js +0 -1
- package/build/assets/skill-filter-CWZ5kjcg.js +0 -2
- package/build/assets/skill-scope-CV1dkAbW.js +0 -1
- package/build/assets/skills-plugins-DGHULTq6.js +0 -1
- package/build/assets/skills-settings-CM1lFv3e.js +0 -1
- package/build/assets/usage-tab-BcfWV6db.js +0 -1
- package/build/assets/use-acp-credential-form-BsSW5NHG.js +0 -1
- package/build/assets/use-agent-profiles-DWBPC0Si.js +0 -1
- package/build/assets/use-config-Bft35DOK.js +0 -1
- package/build/assets/use-create-secret-BSxJMxHp.js +0 -1
- package/build/assets/use-is-authed-CFGkY3-Z.js +0 -1
- package/build/assets/use-llm-configured-BI6obxsc.js +0 -1
- package/build/assets/use-llm-profiles-djGAhTWL.js +0 -1
- package/build/assets/use-manifest-capabilities-3z0-1G59.js +0 -1
- package/build/assets/use-onboarding-completion-BXpyUSsJ.js +0 -1
- package/build/assets/use-plugins-marketplace-DI4_pK56.js +0 -1
- package/build/assets/use-save-agent-profile-DdBSTdpN.js +0 -1
- package/build/assets/use-tracking-D5t9otIF.js +0 -3
- package/build/assets/utils-DaCIEEQP.js +0 -1
- package/build/assets/vendor~index-home~home~conversation-panel~conversation~alert-banner-B3qC_oj8.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-B2OLKL7N.js +0 -1
- package/dist/components/features/tips/random-tip.d.ts +0 -2
- package/dist/utils/tips.d.ts +0 -7
- package/dist/utils/workspace-relative-path.cjs +0 -2
- package/dist/utils/workspace-relative-path.cjs.map +0 -1
- package/dist/utils/workspace-relative-path.d.ts +0 -10
- package/dist/utils/workspace-relative-path.js +0 -22
- package/dist/utils/workspace-relative-path.js.map +0 -1
- /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew3u153i-rfV8mQ9m.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-rfV8mQ9m.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ox0jfsa0-cHFhpUBq.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~i58xkef6-cHFhpUBq.js} +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../i18n/declaration.cjs"),t=require("../../../utils/skill-
|
|
1
|
+
require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../i18n/declaration.cjs"),t=require("../../../utils/skill-enablement.cjs"),n=require("../../../utils/skill-scope.cjs"),r=require("./get-skill-card-description.cjs"),i=require("../../../utils/skill-category.cjs");var a=`source`,o=`category`,s=`type`,c=`state`,l=`recommendation`,u=[`enabled`,`disabled`],d=[`recommended`,`other`],f=[`agentskills`,`knowledge`,`repo`],p={query:``,sources:new Set,categories:new Set,types:new Set,states:new Set,recommendations:new Set};function m(e,t){return e.map(e=>({value:e,labelKey:t[e]}))}function h(e,t){return new Set(e.filter(e=>t.has(e)))}var g={project:e.I18nKey.SETTINGS$SKILLS_SOURCE_PROJECT,personal:e.I18nKey.SETTINGS$SKILLS_SOURCE_PERSONAL,public:e.I18nKey.SETTINGS$SKILLS_SOURCE_PUBLIC},_={agentskills:e.I18nKey.SETTINGS$SKILLS_TYPE_AGENTSKILLS,knowledge:e.I18nKey.SETTINGS$SKILLS_TYPE_KNOWLEDGE,repo:e.I18nKey.SETTINGS$SKILLS_TYPE_REPO},v={enabled:e.I18nKey.SETTINGS$SKILLS_ENABLED,disabled:e.I18nKey.SETTINGS$SKILLS_DISABLED},y={recommended:e.I18nKey.SETTINGS$SKILLS_RECOMMENDED,other:e.I18nKey.SETTINGS$SKILLS_RECOMMENDATION_OTHER},b=[{id:`state`,labelKey:e.I18nKey.SETTINGS$SKILLS_FACET_STATE,param:c,values:m(u,v),valueOf:(e,t)=>t(e)?`enabled`:`disabled`,selected:e=>e.states,withSelected:(e,t)=>({...e,states:h(u,t)})},{id:`recommendation`,labelKey:e.I18nKey.SETTINGS$SKILLS_FACET_RECOMMENDATION,param:l,values:m(d,y),valueOf:e=>t.isRecommendedSkill(e.name)?`recommended`:`other`,selected:e=>e.recommendations,withSelected:(e,t)=>({...e,recommendations:h(d,t)})},{id:`source`,labelKey:e.I18nKey.SETTINGS$SKILLS_FACET_SOURCE,param:a,values:m(n.SKILL_SCOPE_ORDER,g),valueOf:e=>n.getSkillScope(e),selected:e=>e.sources,withSelected:(e,t)=>({...e,sources:h(n.SKILL_SCOPE_ORDER,t)})},{id:`category`,labelKey:e.I18nKey.SETTINGS$SKILLS_FACET_CATEGORY,param:o,values:m(i.SKILL_CATEGORY_ORDER,i.SKILL_CATEGORY_LABEL_KEYS),valueOf:e=>i.getSkillCategory(e),selected:e=>e.categories,withSelected:(e,t)=>({...e,categories:h(i.SKILL_CATEGORY_ORDER,t)})},{id:`type`,labelKey:e.I18nKey.SETTINGS$SKILLS_FACET_TYPE,param:s,values:m(f,_),valueOf:e=>e.type,selected:e=>e.types,withSelected:(e,t)=>({...e,types:h(f,t)})}];function x(e){let t=b.find(t=>t.id===e);if(!t)throw Error(`Unknown skill facet group: ${e}`);return t}function S(e,t){let n=t.trim();if(!n)return!0;let i=[e.name,r.getSkillCardDescription(e),e.description??``,e.content??``,e.license??``,e.compatibility??``,...e.triggers??[],...e.allowed_tools??[]],a=n.toLowerCase();return i.some(e=>e.toLowerCase().includes(a))}function C(e,t,n,r){return b.every(i=>{if(i.id===r)return!0;let a=i.selected(n);return a.size===0?!0:a.has(i.valueOf(e,t))})}function w(e,t,n){return e.filter(e=>S(e,n.query)&&C(e,t,n))}function T(e,t,n){let r={};for(let i of e){let e=t.valueOf(i,n);r[e]=(r[e]??0)+1}return r}function E(e,t,n,r,i){let a=T(t,e,r),o=e.values.filter(({value:e})=>(a[e]??0)>0),s=e.selected(i);if(o.length<2&&s.size===0)return null;let c=e.values.filter(({value:e})=>(a[e]??0)>0||s.has(e)),l=T(n.filter(t=>C(t,r,i,e.id)),e,r);return{id:e.id,labelKey:e.labelKey,rows:c.map(({value:e,labelKey:t})=>{let n=l[e]??0,r=s.has(e);return{value:e,labelKey:t,count:n,checked:r,disabled:n===0&&!r}})}}function D(e,t,n){let r=e.filter(e=>S(e,n.query));return b.map(i=>E(i,e,r,t,n)).filter(e=>e!==null)}function O(e,t,n){let r=x(t);if(!r.values.some(e=>e.value===n))return e;let i=new Set(r.selected(e));return i.has(n)?i.delete(n):i.add(n),r.withSelected(e,i)}function k(e){return{...p,query:e.query}}function A(e){return b.reduce((t,n)=>t+n.selected(e).size,0)}exports.EMPTY_SKILL_FILTER_STATE=p,exports.applySkillFilters=w,exports.buildSkillFacetGroups=D,exports.clearSkillFilterFacets=k,exports.countActiveFilters=A,exports.toggleSkillFilterValue=O;
|
|
2
2
|
//# sourceMappingURL=skill-filter.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-filter.cjs","names":[],"sources":["../../../../src/components/features/skills/skill-filter.ts"],"sourcesContent":["import type { SkillCategoryId } from \"@openhands/extensions/skills\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { SkillInfo, SkillType } from \"#/types/settings\";\nimport {\n getSkillCategory,\n SKILL_CATEGORY_LABEL_KEYS,\n SKILL_CATEGORY_ORDER,\n} from \"#/utils/skill-category\";\nimport {\n getSkillScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { getSkillCardDescription } from \"./get-skill-card-description\";\n\nexport const SKILL_FILTER_QUERY_PARAM = \"q\";\nconst SOURCE_PARAM = \"source\";\nconst CATEGORY_PARAM = \"category\";\nconst TYPE_PARAM = \"type\";\nconst STATE_PARAM = \"state\";\n\nexport type SkillEnabledState = \"enabled\" | \"disabled\";\nexport type SkillFacetGroupId = \"state\" | \"source\" | \"category\" | \"type\";\n\nconst SKILL_ENABLED_STATE_ORDER: readonly SkillEnabledState[] = [\n \"enabled\",\n \"disabled\",\n];\nconst SKILL_TYPE_ORDER: readonly SkillType[] = [\n \"agentskills\",\n \"knowledge\",\n \"repo\",\n];\n\nexport interface SkillFilterState {\n query: string;\n sources: Set<SkillScope>;\n categories: Set<SkillCategoryId>;\n types: Set<SkillType>;\n states: Set<SkillEnabledState>;\n}\n\nexport interface SkillFacetRowModel {\n value: string;\n labelKey: I18nKey;\n count: number;\n checked: boolean;\n disabled: boolean;\n}\n\nexport interface SkillFacetGroup {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n rows: SkillFacetRowModel[];\n}\n\nexport const EMPTY_SKILL_FILTER_STATE: SkillFilterState = {\n query: \"\",\n sources: new Set(),\n categories: new Set(),\n types: new Set(),\n states: new Set(),\n};\n\n/** Carrying `labelKey`s rather than translated strings keeps this module pure, so its tests need no i18n. */\ninterface GroupValue {\n value: string;\n labelKey: I18nKey;\n}\n\nfunction labelledValues<TValue extends string>(\n order: readonly TValue[],\n labelKeys: Record<TValue, I18nKey>,\n): readonly GroupValue[] {\n return order.map((value) => ({ value, labelKey: labelKeys[value] }));\n}\n\n/** A new facet group is declared here and nowhere else: `selected` / `withSelected` are what keep every operation below driven by this table alone. */\ninterface GroupDef {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n param: string;\n values: readonly GroupValue[];\n valueOf: (skill: SkillInfo, disabledSet: Set<string>) => string;\n selected: (state: SkillFilterState) => Set<string>;\n withSelected: (\n state: SkillFilterState,\n next: Set<string>,\n ) => SkillFilterState;\n}\n\n/** Rebuilding rather than casting keeps every writer below cast-free: a value the group does not declare cannot survive. */\nfunction narrowSet<TValue extends string>(\n order: readonly TValue[],\n next: Set<string>,\n): Set<TValue> {\n return new Set(order.filter((value) => next.has(value)));\n}\n\nconst SOURCE_LABEL_KEYS: Record<SkillScope, I18nKey> = {\n project: I18nKey.SETTINGS$SKILLS_SOURCE_PROJECT,\n personal: I18nKey.SETTINGS$SKILLS_SOURCE_PERSONAL,\n public: I18nKey.SETTINGS$SKILLS_SOURCE_PUBLIC,\n};\n\nconst TYPE_LABEL_KEYS: Record<SkillType, I18nKey> = {\n agentskills: I18nKey.SETTINGS$SKILLS_TYPE_AGENTSKILLS,\n knowledge: I18nKey.SETTINGS$SKILLS_TYPE_KNOWLEDGE,\n repo: I18nKey.SETTINGS$SKILLS_TYPE_REPO,\n};\n\nconst STATE_LABEL_KEYS: Record<SkillEnabledState, I18nKey> = {\n enabled: I18nKey.SETTINGS$SKILLS_ENABLED,\n disabled: I18nKey.SETTINGS$SKILLS_DISABLED,\n};\n\nconst GROUP_DEFS: readonly GroupDef[] = [\n {\n id: \"state\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_STATE,\n param: STATE_PARAM,\n values: labelledValues(SKILL_ENABLED_STATE_ORDER, STATE_LABEL_KEYS),\n valueOf: (skill, disabledSet) =>\n disabledSet.has(skill.name) ? \"disabled\" : \"enabled\",\n selected: (state) => state.states,\n withSelected: (state, next) => ({\n ...state,\n states: narrowSet(SKILL_ENABLED_STATE_ORDER, next),\n }),\n },\n {\n id: \"source\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_SOURCE,\n param: SOURCE_PARAM,\n values: labelledValues(SKILL_SCOPE_ORDER, SOURCE_LABEL_KEYS),\n valueOf: (skill) => getSkillScope(skill),\n selected: (state) => state.sources,\n withSelected: (state, next) => ({\n ...state,\n sources: narrowSet(SKILL_SCOPE_ORDER, next),\n }),\n },\n {\n id: \"category\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_CATEGORY,\n param: CATEGORY_PARAM,\n values: labelledValues(SKILL_CATEGORY_ORDER, SKILL_CATEGORY_LABEL_KEYS),\n valueOf: (skill) => getSkillCategory(skill),\n selected: (state) => state.categories,\n withSelected: (state, next) => ({\n ...state,\n categories: narrowSet(SKILL_CATEGORY_ORDER, next),\n }),\n },\n {\n id: \"type\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_TYPE,\n param: TYPE_PARAM,\n values: labelledValues(SKILL_TYPE_ORDER, TYPE_LABEL_KEYS),\n valueOf: (skill) => skill.type,\n selected: (state) => state.types,\n withSelected: (state, next) => ({\n ...state,\n types: narrowSet(SKILL_TYPE_ORDER, next),\n }),\n },\n];\n\nfunction groupDef(id: SkillFacetGroupId): GroupDef {\n const def = GROUP_DEFS.find((candidate) => candidate.id === id);\n if (!def) throw new Error(`Unknown skill facet group: ${id}`);\n return def;\n}\n\n/** Unknown values are dropped, so a hand-edited URL cannot smuggle one in. */\nfunction parseSet(raw: string[], def: GroupDef): Set<string> {\n const legal = new Set(def.values.map(({ value }) => value));\n return new Set(\n raw.map((value) => value.trim()).filter((value) => legal.has(value)),\n );\n}\n\nexport function parseSkillFilterState(\n params: URLSearchParams,\n): SkillFilterState {\n return GROUP_DEFS.reduce<SkillFilterState>(\n (state, def) =>\n def.withSelected(state, parseSet(params.getAll(def.param), def)),\n {\n ...EMPTY_SKILL_FILTER_STATE,\n query: params.get(SKILL_FILTER_QUERY_PARAM) ?? \"\",\n },\n );\n}\n\nexport function toSkillFilterSearchParams(\n state: SkillFilterState,\n): URLSearchParams {\n const params = new URLSearchParams();\n if (state.query) params.set(SKILL_FILTER_QUERY_PARAM, state.query);\n\n // Canonical order keeps URLs deterministic regardless of click order.\n for (const def of GROUP_DEFS) {\n const selected = def.selected(state);\n for (const { value } of def.values) {\n if (selected.has(value)) params.append(def.param, value);\n }\n }\n\n return params;\n}\n\nfunction matchesQuery(skill: SkillInfo, query: string): boolean {\n const trimmed = query.trim();\n if (!trimmed) return true;\n\n const haystacks = [\n skill.name,\n getSkillCardDescription(skill),\n skill.description ?? \"\",\n skill.content ?? \"\",\n skill.license ?? \"\",\n skill.compatibility ?? \"\",\n ...(skill.triggers ?? []),\n ...(skill.allowed_tools ?? []),\n ];\n\n const lowered = trimmed.toLowerCase();\n return haystacks.some((value) => value.toLowerCase().includes(lowered));\n}\n\n/**\n * `exclude` omits one group's own selection so its rows stay counted against the other groups alone.\n * A row therefore reads \"this many skills carry this value, under your other filters\" — the usual disjunctive facet count — and not \"your result set will be this big\": the group ORs its values together, so on a group that already has a selection the two differ.\n */\nfunction matchesFacets(\n skill: SkillInfo,\n disabledSet: Set<string>,\n state: SkillFilterState,\n exclude?: SkillFacetGroupId,\n): boolean {\n return GROUP_DEFS.every((def) => {\n if (def.id === exclude) return true;\n const selected = def.selected(state);\n if (selected.size === 0) return true;\n return selected.has(def.valueOf(skill, disabledSet));\n });\n}\n\nexport function applySkillFilters(\n skills: SkillInfo[],\n disabledSet: Set<string>,\n state: SkillFilterState,\n): SkillInfo[] {\n return skills.filter(\n (skill) =>\n matchesQuery(skill, state.query) &&\n matchesFacets(skill, disabledSet, state),\n );\n}\n\nfunction countByValue(\n skills: SkillInfo[],\n def: GroupDef,\n disabledSet: Set<string>,\n): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const skill of skills) {\n const value = def.valueOf(skill, disabledSet);\n counts[value] = (counts[value] ?? 0) + 1;\n }\n return counts;\n}\n\nfunction buildGroup(\n def: GroupDef,\n allSkills: SkillInfo[],\n searched: SkillInfo[],\n disabledSet: Set<string>,\n state: SkillFilterState,\n): SkillFacetGroup | null {\n // Visibility and the row set come from the raw list so the rail's shape\n // depends only on what the user has, never on the active filters. If they\n // tracked filtered counts, narrowing could make a group vanish mid-click.\n const rawCounts = countByValue(allSkills, def, disabledSet);\n const discriminating = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0,\n );\n const selected = def.selected(state);\n // A group with only one (or zero) discriminating values is normally hidden,\n // but a selection can still be carried in from the URL for a value that has\n // no matches for this user. Hiding the group then would enforce the filter\n // invisibly, with no row left to explain or undo it.\n if (discriminating.length < 2 && selected.size === 0) return null;\n\n const visibleValues = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0 || selected.has(value),\n );\n\n const candidates = searched.filter((skill) =>\n matchesFacets(skill, disabledSet, state, def.id),\n );\n const counts = countByValue(candidates, def, disabledSet);\n\n return {\n id: def.id,\n labelKey: def.labelKey,\n rows: visibleValues.map(({ value, labelKey }) => {\n const count = counts[value] ?? 0;\n const checked = selected.has(value);\n return {\n value,\n labelKey,\n count,\n checked,\n disabled: count === 0 && !checked,\n };\n }),\n };\n}\n\nexport function buildSkillFacetGroups(\n skills: SkillInfo[],\n disabledSet: Set<string>,\n state: SkillFilterState,\n): SkillFacetGroup[] {\n const searched = skills.filter((skill) => matchesQuery(skill, state.query));\n\n return GROUP_DEFS.map((def) =>\n buildGroup(def, skills, searched, disabledSet, state),\n ).filter((group): group is SkillFacetGroup => group !== null);\n}\n\nexport function toggleSkillFilterValue(\n state: SkillFilterState,\n groupId: SkillFacetGroupId,\n value: string,\n): SkillFilterState {\n const def = groupDef(groupId);\n // `withSelected` would drop an unknown value anyway; returning the same\n // state object keeps a no-op toggle from re-rendering or rewriting the URL.\n if (!def.values.some((candidate) => candidate.value === value)) return state;\n\n const next = new Set(def.selected(state));\n if (next.has(value)) {\n next.delete(value);\n } else {\n next.add(value);\n }\n\n return def.withSelected(state, next);\n}\n\nexport function clearSkillFilterFacets(\n state: SkillFilterState,\n): SkillFilterState {\n return { ...EMPTY_SKILL_FILTER_STATE, query: state.query };\n}\n\nexport function countActiveFilters(state: SkillFilterState): number {\n // The query is excluded: it is already visible in its own input, so counting\n // it would double-report in both the Filters badge and the summary row.\n return GROUP_DEFS.reduce((total, def) => total + def.selected(state).size, 0);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"skill-filter.cjs","names":[],"sources":["../../../../src/components/features/skills/skill-filter.ts"],"sourcesContent":["import type { SkillCategoryId } from \"@openhands/extensions/skills\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { SkillInfo, SkillType } from \"#/types/settings\";\nimport {\n getSkillCategory,\n SKILL_CATEGORY_LABEL_KEYS,\n SKILL_CATEGORY_ORDER,\n} from \"#/utils/skill-category\";\nimport {\n getSkillScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { isRecommendedSkill } from \"#/utils/skill-enablement\";\nimport { getSkillCardDescription } from \"./get-skill-card-description\";\n\nexport const SKILL_FILTER_QUERY_PARAM = \"q\";\nconst SOURCE_PARAM = \"source\";\nconst CATEGORY_PARAM = \"category\";\nconst TYPE_PARAM = \"type\";\nconst STATE_PARAM = \"state\";\nconst RECOMMENDATION_PARAM = \"recommendation\";\n\nexport type SkillEnabledState = \"enabled\" | \"disabled\";\nexport type SkillRecommendation = \"recommended\" | \"other\";\nexport type SkillFacetGroupId =\n | \"state\"\n | \"recommendation\"\n | \"source\"\n | \"category\"\n | \"type\";\n\nconst SKILL_ENABLED_STATE_ORDER: readonly SkillEnabledState[] = [\n \"enabled\",\n \"disabled\",\n];\nconst SKILL_RECOMMENDATION_ORDER: readonly SkillRecommendation[] = [\n \"recommended\",\n \"other\",\n];\nconst SKILL_TYPE_ORDER: readonly SkillType[] = [\n \"agentskills\",\n \"knowledge\",\n \"repo\",\n];\n\nexport interface SkillFilterState {\n query: string;\n sources: Set<SkillScope>;\n categories: Set<SkillCategoryId>;\n types: Set<SkillType>;\n states: Set<SkillEnabledState>;\n recommendations: Set<SkillRecommendation>;\n}\n\nexport interface SkillFacetRowModel {\n value: string;\n labelKey: I18nKey;\n count: number;\n checked: boolean;\n disabled: boolean;\n}\n\nexport interface SkillFacetGroup {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n rows: SkillFacetRowModel[];\n}\n\nexport const EMPTY_SKILL_FILTER_STATE: SkillFilterState = {\n query: \"\",\n sources: new Set(),\n categories: new Set(),\n types: new Set(),\n states: new Set(),\n recommendations: new Set(),\n};\n\n/** Carrying `labelKey`s rather than translated strings keeps this module pure, so its tests need no i18n. */\ninterface GroupValue {\n value: string;\n labelKey: I18nKey;\n}\n\nfunction labelledValues<TValue extends string>(\n order: readonly TValue[],\n labelKeys: Record<TValue, I18nKey>,\n): readonly GroupValue[] {\n return order.map((value) => ({ value, labelKey: labelKeys[value] }));\n}\n\n/** Resolving the two lists behind enablement is the caller's job, not this module's. */\ntype SkillEnabledPredicate = (skill: SkillInfo) => boolean;\n\n/** A new facet group is declared here and nowhere else: `selected` / `withSelected` are what keep every operation below driven by this table alone. */\ninterface GroupDef {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n param: string;\n values: readonly GroupValue[];\n valueOf: (skill: SkillInfo, isEnabled: SkillEnabledPredicate) => string;\n selected: (state: SkillFilterState) => Set<string>;\n withSelected: (\n state: SkillFilterState,\n next: Set<string>,\n ) => SkillFilterState;\n}\n\n/** Rebuilding rather than casting keeps every writer below cast-free: a value the group does not declare cannot survive. */\nfunction narrowSet<TValue extends string>(\n order: readonly TValue[],\n next: Set<string>,\n): Set<TValue> {\n return new Set(order.filter((value) => next.has(value)));\n}\n\nconst SOURCE_LABEL_KEYS: Record<SkillScope, I18nKey> = {\n project: I18nKey.SETTINGS$SKILLS_SOURCE_PROJECT,\n personal: I18nKey.SETTINGS$SKILLS_SOURCE_PERSONAL,\n public: I18nKey.SETTINGS$SKILLS_SOURCE_PUBLIC,\n};\n\nconst TYPE_LABEL_KEYS: Record<SkillType, I18nKey> = {\n agentskills: I18nKey.SETTINGS$SKILLS_TYPE_AGENTSKILLS,\n knowledge: I18nKey.SETTINGS$SKILLS_TYPE_KNOWLEDGE,\n repo: I18nKey.SETTINGS$SKILLS_TYPE_REPO,\n};\n\nconst STATE_LABEL_KEYS: Record<SkillEnabledState, I18nKey> = {\n enabled: I18nKey.SETTINGS$SKILLS_ENABLED,\n disabled: I18nKey.SETTINGS$SKILLS_DISABLED,\n};\n\nconst RECOMMENDATION_LABEL_KEYS: Record<SkillRecommendation, I18nKey> = {\n recommended: I18nKey.SETTINGS$SKILLS_RECOMMENDED,\n other: I18nKey.SETTINGS$SKILLS_RECOMMENDATION_OTHER,\n};\n\nconst GROUP_DEFS: readonly GroupDef[] = [\n {\n id: \"state\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_STATE,\n param: STATE_PARAM,\n values: labelledValues(SKILL_ENABLED_STATE_ORDER, STATE_LABEL_KEYS),\n valueOf: (skill, isEnabled) => (isEnabled(skill) ? \"enabled\" : \"disabled\"),\n selected: (state) => state.states,\n withSelected: (state, next) => ({\n ...state,\n states: narrowSet(SKILL_ENABLED_STATE_ORDER, next),\n }),\n },\n {\n id: \"recommendation\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_RECOMMENDATION,\n param: RECOMMENDATION_PARAM,\n values: labelledValues(\n SKILL_RECOMMENDATION_ORDER,\n RECOMMENDATION_LABEL_KEYS,\n ),\n valueOf: (skill) =>\n isRecommendedSkill(skill.name) ? \"recommended\" : \"other\",\n selected: (state) => state.recommendations,\n withSelected: (state, next) => ({\n ...state,\n recommendations: narrowSet(SKILL_RECOMMENDATION_ORDER, next),\n }),\n },\n {\n id: \"source\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_SOURCE,\n param: SOURCE_PARAM,\n values: labelledValues(SKILL_SCOPE_ORDER, SOURCE_LABEL_KEYS),\n valueOf: (skill) => getSkillScope(skill),\n selected: (state) => state.sources,\n withSelected: (state, next) => ({\n ...state,\n sources: narrowSet(SKILL_SCOPE_ORDER, next),\n }),\n },\n {\n id: \"category\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_CATEGORY,\n param: CATEGORY_PARAM,\n values: labelledValues(SKILL_CATEGORY_ORDER, SKILL_CATEGORY_LABEL_KEYS),\n valueOf: (skill) => getSkillCategory(skill),\n selected: (state) => state.categories,\n withSelected: (state, next) => ({\n ...state,\n categories: narrowSet(SKILL_CATEGORY_ORDER, next),\n }),\n },\n {\n id: \"type\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_TYPE,\n param: TYPE_PARAM,\n values: labelledValues(SKILL_TYPE_ORDER, TYPE_LABEL_KEYS),\n valueOf: (skill) => skill.type,\n selected: (state) => state.types,\n withSelected: (state, next) => ({\n ...state,\n types: narrowSet(SKILL_TYPE_ORDER, next),\n }),\n },\n];\n\nfunction groupDef(id: SkillFacetGroupId): GroupDef {\n const def = GROUP_DEFS.find((candidate) => candidate.id === id);\n if (!def) throw new Error(`Unknown skill facet group: ${id}`);\n return def;\n}\n\n/** Unknown values are dropped, so a hand-edited URL cannot smuggle one in. */\nfunction parseSet(raw: string[], def: GroupDef): Set<string> {\n const legal = new Set(def.values.map(({ value }) => value));\n return new Set(\n raw.map((value) => value.trim()).filter((value) => legal.has(value)),\n );\n}\n\nexport function parseSkillFilterState(\n params: URLSearchParams,\n): SkillFilterState {\n return GROUP_DEFS.reduce<SkillFilterState>(\n (state, def) =>\n def.withSelected(state, parseSet(params.getAll(def.param), def)),\n {\n ...EMPTY_SKILL_FILTER_STATE,\n query: params.get(SKILL_FILTER_QUERY_PARAM) ?? \"\",\n },\n );\n}\n\nexport function toSkillFilterSearchParams(\n state: SkillFilterState,\n): URLSearchParams {\n const params = new URLSearchParams();\n if (state.query) params.set(SKILL_FILTER_QUERY_PARAM, state.query);\n\n // Canonical order keeps URLs deterministic regardless of click order.\n for (const def of GROUP_DEFS) {\n const selected = def.selected(state);\n for (const { value } of def.values) {\n if (selected.has(value)) params.append(def.param, value);\n }\n }\n\n return params;\n}\n\nfunction matchesQuery(skill: SkillInfo, query: string): boolean {\n const trimmed = query.trim();\n if (!trimmed) return true;\n\n const haystacks = [\n skill.name,\n getSkillCardDescription(skill),\n skill.description ?? \"\",\n skill.content ?? \"\",\n skill.license ?? \"\",\n skill.compatibility ?? \"\",\n ...(skill.triggers ?? []),\n ...(skill.allowed_tools ?? []),\n ];\n\n const lowered = trimmed.toLowerCase();\n return haystacks.some((value) => value.toLowerCase().includes(lowered));\n}\n\n/**\n * `exclude` omits one group's own selection so its rows stay counted against the other groups alone.\n * A row therefore reads \"this many skills carry this value, under your other filters\" — the usual disjunctive facet count — and not \"your result set will be this big\": the group ORs its values together, so on a group that already has a selection the two differ.\n */\nfunction matchesFacets(\n skill: SkillInfo,\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n exclude?: SkillFacetGroupId,\n): boolean {\n return GROUP_DEFS.every((def) => {\n if (def.id === exclude) return true;\n const selected = def.selected(state);\n if (selected.size === 0) return true;\n return selected.has(def.valueOf(skill, isEnabled));\n });\n}\n\nexport function applySkillFilters(\n skills: SkillInfo[],\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n): SkillInfo[] {\n return skills.filter(\n (skill) =>\n matchesQuery(skill, state.query) &&\n matchesFacets(skill, isEnabled, state),\n );\n}\n\nfunction countByValue(\n skills: SkillInfo[],\n def: GroupDef,\n isEnabled: SkillEnabledPredicate,\n): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const skill of skills) {\n const value = def.valueOf(skill, isEnabled);\n counts[value] = (counts[value] ?? 0) + 1;\n }\n return counts;\n}\n\nfunction buildGroup(\n def: GroupDef,\n allSkills: SkillInfo[],\n searched: SkillInfo[],\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n): SkillFacetGroup | null {\n // Visibility and the row set come from the raw list so the rail's shape\n // depends only on what the user has, never on the active filters. If they\n // tracked filtered counts, narrowing could make a group vanish mid-click.\n const rawCounts = countByValue(allSkills, def, isEnabled);\n const discriminating = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0,\n );\n const selected = def.selected(state);\n // A group with only one (or zero) discriminating values is normally hidden,\n // but a selection can still be carried in from the URL for a value that has\n // no matches for this user. Hiding the group then would enforce the filter\n // invisibly, with no row left to explain or undo it.\n if (discriminating.length < 2 && selected.size === 0) return null;\n\n const visibleValues = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0 || selected.has(value),\n );\n\n const candidates = searched.filter((skill) =>\n matchesFacets(skill, isEnabled, state, def.id),\n );\n const counts = countByValue(candidates, def, isEnabled);\n\n return {\n id: def.id,\n labelKey: def.labelKey,\n rows: visibleValues.map(({ value, labelKey }) => {\n const count = counts[value] ?? 0;\n const checked = selected.has(value);\n return {\n value,\n labelKey,\n count,\n checked,\n disabled: count === 0 && !checked,\n };\n }),\n };\n}\n\nexport function buildSkillFacetGroups(\n skills: SkillInfo[],\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n): SkillFacetGroup[] {\n const searched = skills.filter((skill) => matchesQuery(skill, state.query));\n\n return GROUP_DEFS.map((def) =>\n buildGroup(def, skills, searched, isEnabled, state),\n ).filter((group): group is SkillFacetGroup => group !== null);\n}\n\nexport function toggleSkillFilterValue(\n state: SkillFilterState,\n groupId: SkillFacetGroupId,\n value: string,\n): SkillFilterState {\n const def = groupDef(groupId);\n // `withSelected` would drop an unknown value anyway; returning the same\n // state object keeps a no-op toggle from re-rendering or rewriting the URL.\n if (!def.values.some((candidate) => candidate.value === value)) return state;\n\n const next = new Set(def.selected(state));\n if (next.has(value)) {\n next.delete(value);\n } else {\n next.add(value);\n }\n\n return def.withSelected(state, next);\n}\n\nexport function clearSkillFilterFacets(\n state: SkillFilterState,\n): SkillFilterState {\n return { ...EMPTY_SKILL_FILTER_STATE, query: state.query };\n}\n\nexport function countActiveFilters(state: SkillFilterState): number {\n // The query is excluded: it is already visible in its own input, so counting\n // it would double-report in both the Filters badge and the summary row.\n return GROUP_DEFS.reduce((total, def) => total + def.selected(state).size, 0);\n}\n"],"mappings":"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"}
|
|
@@ -4,13 +4,15 @@ import type { SkillInfo, SkillType } from "#/types/settings";
|
|
|
4
4
|
import { type SkillScope } from "#/utils/skill-scope";
|
|
5
5
|
export declare const SKILL_FILTER_QUERY_PARAM = "q";
|
|
6
6
|
export type SkillEnabledState = "enabled" | "disabled";
|
|
7
|
-
export type
|
|
7
|
+
export type SkillRecommendation = "recommended" | "other";
|
|
8
|
+
export type SkillFacetGroupId = "state" | "recommendation" | "source" | "category" | "type";
|
|
8
9
|
export interface SkillFilterState {
|
|
9
10
|
query: string;
|
|
10
11
|
sources: Set<SkillScope>;
|
|
11
12
|
categories: Set<SkillCategoryId>;
|
|
12
13
|
types: Set<SkillType>;
|
|
13
14
|
states: Set<SkillEnabledState>;
|
|
15
|
+
recommendations: Set<SkillRecommendation>;
|
|
14
16
|
}
|
|
15
17
|
export interface SkillFacetRowModel {
|
|
16
18
|
value: string;
|
|
@@ -25,10 +27,13 @@ export interface SkillFacetGroup {
|
|
|
25
27
|
rows: SkillFacetRowModel[];
|
|
26
28
|
}
|
|
27
29
|
export declare const EMPTY_SKILL_FILTER_STATE: SkillFilterState;
|
|
30
|
+
/** Resolving the two lists behind enablement is the caller's job, not this module's. */
|
|
31
|
+
type SkillEnabledPredicate = (skill: SkillInfo) => boolean;
|
|
28
32
|
export declare function parseSkillFilterState(params: URLSearchParams): SkillFilterState;
|
|
29
33
|
export declare function toSkillFilterSearchParams(state: SkillFilterState): URLSearchParams;
|
|
30
|
-
export declare function applySkillFilters(skills: SkillInfo[],
|
|
31
|
-
export declare function buildSkillFacetGroups(skills: SkillInfo[],
|
|
34
|
+
export declare function applySkillFilters(skills: SkillInfo[], isEnabled: SkillEnabledPredicate, state: SkillFilterState): SkillInfo[];
|
|
35
|
+
export declare function buildSkillFacetGroups(skills: SkillInfo[], isEnabled: SkillEnabledPredicate, state: SkillFilterState): SkillFacetGroup[];
|
|
32
36
|
export declare function toggleSkillFilterValue(state: SkillFilterState, groupId: SkillFacetGroupId, value: string): SkillFilterState;
|
|
33
37
|
export declare function clearSkillFilterFacets(state: SkillFilterState): SkillFilterState;
|
|
34
38
|
export declare function countActiveFilters(state: SkillFilterState): number;
|
|
39
|
+
export {};
|
|
@@ -1,100 +1,117 @@
|
|
|
1
1
|
import { I18nKey as e } from "../../../i18n/declaration.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { isRecommendedSkill as t } from "../../../utils/skill-enablement.js";
|
|
3
|
+
import { SKILL_SCOPE_ORDER as n, getSkillScope as r } from "../../../utils/skill-scope.js";
|
|
4
|
+
import { getSkillCardDescription as i } from "./get-skill-card-description.js";
|
|
5
|
+
import { SKILL_CATEGORY_LABEL_KEYS as a, SKILL_CATEGORY_ORDER as o, getSkillCategory as s } from "../../../utils/skill-category.js";
|
|
5
6
|
//#region src/components/features/skills/skill-filter.ts
|
|
6
|
-
var
|
|
7
|
+
var c = "source", l = "category", u = "type", d = "state", f = "recommendation", p = ["enabled", "disabled"], m = ["recommended", "other"], h = [
|
|
7
8
|
"agentskills",
|
|
8
9
|
"knowledge",
|
|
9
10
|
"repo"
|
|
10
|
-
],
|
|
11
|
+
], g = {
|
|
11
12
|
query: "",
|
|
12
13
|
sources: /* @__PURE__ */ new Set(),
|
|
13
14
|
categories: /* @__PURE__ */ new Set(),
|
|
14
15
|
types: /* @__PURE__ */ new Set(),
|
|
15
|
-
states: /* @__PURE__ */ new Set()
|
|
16
|
+
states: /* @__PURE__ */ new Set(),
|
|
17
|
+
recommendations: /* @__PURE__ */ new Set()
|
|
16
18
|
};
|
|
17
|
-
function
|
|
19
|
+
function _(e, t) {
|
|
18
20
|
return e.map((e) => ({
|
|
19
21
|
value: e,
|
|
20
22
|
labelKey: t[e]
|
|
21
23
|
}));
|
|
22
24
|
}
|
|
23
|
-
function
|
|
25
|
+
function v(e, t) {
|
|
24
26
|
return new Set(e.filter((e) => t.has(e)));
|
|
25
27
|
}
|
|
26
|
-
var
|
|
28
|
+
var y = {
|
|
27
29
|
project: e.SETTINGS$SKILLS_SOURCE_PROJECT,
|
|
28
30
|
personal: e.SETTINGS$SKILLS_SOURCE_PERSONAL,
|
|
29
31
|
public: e.SETTINGS$SKILLS_SOURCE_PUBLIC
|
|
30
|
-
},
|
|
32
|
+
}, b = {
|
|
31
33
|
agentskills: e.SETTINGS$SKILLS_TYPE_AGENTSKILLS,
|
|
32
34
|
knowledge: e.SETTINGS$SKILLS_TYPE_KNOWLEDGE,
|
|
33
35
|
repo: e.SETTINGS$SKILLS_TYPE_REPO
|
|
34
|
-
},
|
|
36
|
+
}, x = {
|
|
35
37
|
enabled: e.SETTINGS$SKILLS_ENABLED,
|
|
36
38
|
disabled: e.SETTINGS$SKILLS_DISABLED
|
|
37
|
-
},
|
|
39
|
+
}, S = {
|
|
40
|
+
recommended: e.SETTINGS$SKILLS_RECOMMENDED,
|
|
41
|
+
other: e.SETTINGS$SKILLS_RECOMMENDATION_OTHER
|
|
42
|
+
}, C = [
|
|
38
43
|
{
|
|
39
44
|
id: "state",
|
|
40
45
|
labelKey: e.SETTINGS$SKILLS_FACET_STATE,
|
|
41
|
-
param:
|
|
42
|
-
values:
|
|
43
|
-
valueOf: (e, t) => t
|
|
46
|
+
param: d,
|
|
47
|
+
values: _(p, x),
|
|
48
|
+
valueOf: (e, t) => t(e) ? "enabled" : "disabled",
|
|
44
49
|
selected: (e) => e.states,
|
|
45
50
|
withSelected: (e, t) => ({
|
|
46
51
|
...e,
|
|
47
|
-
states:
|
|
52
|
+
states: v(p, t)
|
|
53
|
+
})
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "recommendation",
|
|
57
|
+
labelKey: e.SETTINGS$SKILLS_FACET_RECOMMENDATION,
|
|
58
|
+
param: f,
|
|
59
|
+
values: _(m, S),
|
|
60
|
+
valueOf: (e) => t(e.name) ? "recommended" : "other",
|
|
61
|
+
selected: (e) => e.recommendations,
|
|
62
|
+
withSelected: (e, t) => ({
|
|
63
|
+
...e,
|
|
64
|
+
recommendations: v(m, t)
|
|
48
65
|
})
|
|
49
66
|
},
|
|
50
67
|
{
|
|
51
68
|
id: "source",
|
|
52
69
|
labelKey: e.SETTINGS$SKILLS_FACET_SOURCE,
|
|
53
|
-
param:
|
|
54
|
-
values:
|
|
55
|
-
valueOf: (e) =>
|
|
70
|
+
param: c,
|
|
71
|
+
values: _(n, y),
|
|
72
|
+
valueOf: (e) => r(e),
|
|
56
73
|
selected: (e) => e.sources,
|
|
57
|
-
withSelected: (e,
|
|
74
|
+
withSelected: (e, t) => ({
|
|
58
75
|
...e,
|
|
59
|
-
sources:
|
|
76
|
+
sources: v(n, t)
|
|
60
77
|
})
|
|
61
78
|
},
|
|
62
79
|
{
|
|
63
80
|
id: "category",
|
|
64
81
|
labelKey: e.SETTINGS$SKILLS_FACET_CATEGORY,
|
|
65
|
-
param:
|
|
66
|
-
values:
|
|
67
|
-
valueOf: (e) =>
|
|
82
|
+
param: l,
|
|
83
|
+
values: _(o, a),
|
|
84
|
+
valueOf: (e) => s(e),
|
|
68
85
|
selected: (e) => e.categories,
|
|
69
86
|
withSelected: (e, t) => ({
|
|
70
87
|
...e,
|
|
71
|
-
categories:
|
|
88
|
+
categories: v(o, t)
|
|
72
89
|
})
|
|
73
90
|
},
|
|
74
91
|
{
|
|
75
92
|
id: "type",
|
|
76
93
|
labelKey: e.SETTINGS$SKILLS_FACET_TYPE,
|
|
77
|
-
param:
|
|
78
|
-
values:
|
|
94
|
+
param: u,
|
|
95
|
+
values: _(h, b),
|
|
79
96
|
valueOf: (e) => e.type,
|
|
80
97
|
selected: (e) => e.types,
|
|
81
98
|
withSelected: (e, t) => ({
|
|
82
99
|
...e,
|
|
83
|
-
types: h
|
|
100
|
+
types: v(h, t)
|
|
84
101
|
})
|
|
85
102
|
}
|
|
86
103
|
];
|
|
87
|
-
function
|
|
88
|
-
let t =
|
|
104
|
+
function w(e) {
|
|
105
|
+
let t = C.find((t) => t.id === e);
|
|
89
106
|
if (!t) throw Error(`Unknown skill facet group: ${e}`);
|
|
90
107
|
return t;
|
|
91
108
|
}
|
|
92
|
-
function
|
|
109
|
+
function T(e, t) {
|
|
93
110
|
let n = t.trim();
|
|
94
111
|
if (!n) return !0;
|
|
95
|
-
let
|
|
112
|
+
let r = [
|
|
96
113
|
e.name,
|
|
97
|
-
|
|
114
|
+
i(e),
|
|
98
115
|
e.description ?? "",
|
|
99
116
|
e.content ?? "",
|
|
100
117
|
e.license ?? "",
|
|
@@ -102,19 +119,19 @@ function x(e, t) {
|
|
|
102
119
|
...e.triggers ?? [],
|
|
103
120
|
...e.allowed_tools ?? []
|
|
104
121
|
], a = n.toLowerCase();
|
|
105
|
-
return
|
|
122
|
+
return r.some((e) => e.toLowerCase().includes(a));
|
|
106
123
|
}
|
|
107
|
-
function
|
|
108
|
-
return
|
|
124
|
+
function E(e, t, n, r) {
|
|
125
|
+
return C.every((i) => {
|
|
109
126
|
if (i.id === r) return !0;
|
|
110
127
|
let a = i.selected(n);
|
|
111
128
|
return a.size === 0 ? !0 : a.has(i.valueOf(e, t));
|
|
112
129
|
});
|
|
113
130
|
}
|
|
114
|
-
function
|
|
115
|
-
return e.filter((e) =>
|
|
131
|
+
function D(e, t, n) {
|
|
132
|
+
return e.filter((e) => T(e, n.query) && E(e, t, n));
|
|
116
133
|
}
|
|
117
|
-
function
|
|
134
|
+
function O(e, t, n) {
|
|
118
135
|
let r = {};
|
|
119
136
|
for (let i of e) {
|
|
120
137
|
let e = t.valueOf(i, n);
|
|
@@ -122,10 +139,10 @@ function w(e, t, n) {
|
|
|
122
139
|
}
|
|
123
140
|
return r;
|
|
124
141
|
}
|
|
125
|
-
function
|
|
126
|
-
let a =
|
|
142
|
+
function k(e, t, n, r, i) {
|
|
143
|
+
let a = O(t, e, r), o = e.values.filter(({ value: e }) => (a[e] ?? 0) > 0), s = e.selected(i);
|
|
127
144
|
if (o.length < 2 && s.size === 0) return null;
|
|
128
|
-
let c = e.values.filter(({ value: e }) => (a[e] ?? 0) > 0 || s.has(e)), l =
|
|
145
|
+
let c = e.values.filter(({ value: e }) => (a[e] ?? 0) > 0 || s.has(e)), l = O(n.filter((t) => E(t, r, i, e.id)), e, r);
|
|
129
146
|
return {
|
|
130
147
|
id: e.id,
|
|
131
148
|
labelKey: e.labelKey,
|
|
@@ -141,26 +158,26 @@ function T(e, t, n, r, i) {
|
|
|
141
158
|
})
|
|
142
159
|
};
|
|
143
160
|
}
|
|
144
|
-
function
|
|
145
|
-
let r = e.filter((e) =>
|
|
146
|
-
return
|
|
161
|
+
function A(e, t, n) {
|
|
162
|
+
let r = e.filter((e) => T(e, n.query));
|
|
163
|
+
return C.map((i) => k(i, e, r, t, n)).filter((e) => e !== null);
|
|
147
164
|
}
|
|
148
|
-
function
|
|
149
|
-
let r =
|
|
165
|
+
function j(e, t, n) {
|
|
166
|
+
let r = w(t);
|
|
150
167
|
if (!r.values.some((e) => e.value === n)) return e;
|
|
151
168
|
let i = new Set(r.selected(e));
|
|
152
169
|
return i.has(n) ? i.delete(n) : i.add(n), r.withSelected(e, i);
|
|
153
170
|
}
|
|
154
|
-
function
|
|
171
|
+
function M(e) {
|
|
155
172
|
return {
|
|
156
|
-
...
|
|
173
|
+
...g,
|
|
157
174
|
query: e.query
|
|
158
175
|
};
|
|
159
176
|
}
|
|
160
|
-
function
|
|
161
|
-
return
|
|
177
|
+
function N(e) {
|
|
178
|
+
return C.reduce((t, n) => t + n.selected(e).size, 0);
|
|
162
179
|
}
|
|
163
180
|
//#endregion
|
|
164
|
-
export {
|
|
181
|
+
export { g as EMPTY_SKILL_FILTER_STATE, D as applySkillFilters, A as buildSkillFacetGroups, M as clearSkillFilterFacets, N as countActiveFilters, j as toggleSkillFilterValue };
|
|
165
182
|
|
|
166
183
|
//# sourceMappingURL=skill-filter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-filter.js","names":[],"sources":["../../../../src/components/features/skills/skill-filter.ts"],"sourcesContent":["import type { SkillCategoryId } from \"@openhands/extensions/skills\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { SkillInfo, SkillType } from \"#/types/settings\";\nimport {\n getSkillCategory,\n SKILL_CATEGORY_LABEL_KEYS,\n SKILL_CATEGORY_ORDER,\n} from \"#/utils/skill-category\";\nimport {\n getSkillScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { getSkillCardDescription } from \"./get-skill-card-description\";\n\nexport const SKILL_FILTER_QUERY_PARAM = \"q\";\nconst SOURCE_PARAM = \"source\";\nconst CATEGORY_PARAM = \"category\";\nconst TYPE_PARAM = \"type\";\nconst STATE_PARAM = \"state\";\n\nexport type SkillEnabledState = \"enabled\" | \"disabled\";\nexport type SkillFacetGroupId = \"state\" | \"source\" | \"category\" | \"type\";\n\nconst SKILL_ENABLED_STATE_ORDER: readonly SkillEnabledState[] = [\n \"enabled\",\n \"disabled\",\n];\nconst SKILL_TYPE_ORDER: readonly SkillType[] = [\n \"agentskills\",\n \"knowledge\",\n \"repo\",\n];\n\nexport interface SkillFilterState {\n query: string;\n sources: Set<SkillScope>;\n categories: Set<SkillCategoryId>;\n types: Set<SkillType>;\n states: Set<SkillEnabledState>;\n}\n\nexport interface SkillFacetRowModel {\n value: string;\n labelKey: I18nKey;\n count: number;\n checked: boolean;\n disabled: boolean;\n}\n\nexport interface SkillFacetGroup {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n rows: SkillFacetRowModel[];\n}\n\nexport const EMPTY_SKILL_FILTER_STATE: SkillFilterState = {\n query: \"\",\n sources: new Set(),\n categories: new Set(),\n types: new Set(),\n states: new Set(),\n};\n\n/** Carrying `labelKey`s rather than translated strings keeps this module pure, so its tests need no i18n. */\ninterface GroupValue {\n value: string;\n labelKey: I18nKey;\n}\n\nfunction labelledValues<TValue extends string>(\n order: readonly TValue[],\n labelKeys: Record<TValue, I18nKey>,\n): readonly GroupValue[] {\n return order.map((value) => ({ value, labelKey: labelKeys[value] }));\n}\n\n/** A new facet group is declared here and nowhere else: `selected` / `withSelected` are what keep every operation below driven by this table alone. */\ninterface GroupDef {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n param: string;\n values: readonly GroupValue[];\n valueOf: (skill: SkillInfo, disabledSet: Set<string>) => string;\n selected: (state: SkillFilterState) => Set<string>;\n withSelected: (\n state: SkillFilterState,\n next: Set<string>,\n ) => SkillFilterState;\n}\n\n/** Rebuilding rather than casting keeps every writer below cast-free: a value the group does not declare cannot survive. */\nfunction narrowSet<TValue extends string>(\n order: readonly TValue[],\n next: Set<string>,\n): Set<TValue> {\n return new Set(order.filter((value) => next.has(value)));\n}\n\nconst SOURCE_LABEL_KEYS: Record<SkillScope, I18nKey> = {\n project: I18nKey.SETTINGS$SKILLS_SOURCE_PROJECT,\n personal: I18nKey.SETTINGS$SKILLS_SOURCE_PERSONAL,\n public: I18nKey.SETTINGS$SKILLS_SOURCE_PUBLIC,\n};\n\nconst TYPE_LABEL_KEYS: Record<SkillType, I18nKey> = {\n agentskills: I18nKey.SETTINGS$SKILLS_TYPE_AGENTSKILLS,\n knowledge: I18nKey.SETTINGS$SKILLS_TYPE_KNOWLEDGE,\n repo: I18nKey.SETTINGS$SKILLS_TYPE_REPO,\n};\n\nconst STATE_LABEL_KEYS: Record<SkillEnabledState, I18nKey> = {\n enabled: I18nKey.SETTINGS$SKILLS_ENABLED,\n disabled: I18nKey.SETTINGS$SKILLS_DISABLED,\n};\n\nconst GROUP_DEFS: readonly GroupDef[] = [\n {\n id: \"state\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_STATE,\n param: STATE_PARAM,\n values: labelledValues(SKILL_ENABLED_STATE_ORDER, STATE_LABEL_KEYS),\n valueOf: (skill, disabledSet) =>\n disabledSet.has(skill.name) ? \"disabled\" : \"enabled\",\n selected: (state) => state.states,\n withSelected: (state, next) => ({\n ...state,\n states: narrowSet(SKILL_ENABLED_STATE_ORDER, next),\n }),\n },\n {\n id: \"source\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_SOURCE,\n param: SOURCE_PARAM,\n values: labelledValues(SKILL_SCOPE_ORDER, SOURCE_LABEL_KEYS),\n valueOf: (skill) => getSkillScope(skill),\n selected: (state) => state.sources,\n withSelected: (state, next) => ({\n ...state,\n sources: narrowSet(SKILL_SCOPE_ORDER, next),\n }),\n },\n {\n id: \"category\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_CATEGORY,\n param: CATEGORY_PARAM,\n values: labelledValues(SKILL_CATEGORY_ORDER, SKILL_CATEGORY_LABEL_KEYS),\n valueOf: (skill) => getSkillCategory(skill),\n selected: (state) => state.categories,\n withSelected: (state, next) => ({\n ...state,\n categories: narrowSet(SKILL_CATEGORY_ORDER, next),\n }),\n },\n {\n id: \"type\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_TYPE,\n param: TYPE_PARAM,\n values: labelledValues(SKILL_TYPE_ORDER, TYPE_LABEL_KEYS),\n valueOf: (skill) => skill.type,\n selected: (state) => state.types,\n withSelected: (state, next) => ({\n ...state,\n types: narrowSet(SKILL_TYPE_ORDER, next),\n }),\n },\n];\n\nfunction groupDef(id: SkillFacetGroupId): GroupDef {\n const def = GROUP_DEFS.find((candidate) => candidate.id === id);\n if (!def) throw new Error(`Unknown skill facet group: ${id}`);\n return def;\n}\n\n/** Unknown values are dropped, so a hand-edited URL cannot smuggle one in. */\nfunction parseSet(raw: string[], def: GroupDef): Set<string> {\n const legal = new Set(def.values.map(({ value }) => value));\n return new Set(\n raw.map((value) => value.trim()).filter((value) => legal.has(value)),\n );\n}\n\nexport function parseSkillFilterState(\n params: URLSearchParams,\n): SkillFilterState {\n return GROUP_DEFS.reduce<SkillFilterState>(\n (state, def) =>\n def.withSelected(state, parseSet(params.getAll(def.param), def)),\n {\n ...EMPTY_SKILL_FILTER_STATE,\n query: params.get(SKILL_FILTER_QUERY_PARAM) ?? \"\",\n },\n );\n}\n\nexport function toSkillFilterSearchParams(\n state: SkillFilterState,\n): URLSearchParams {\n const params = new URLSearchParams();\n if (state.query) params.set(SKILL_FILTER_QUERY_PARAM, state.query);\n\n // Canonical order keeps URLs deterministic regardless of click order.\n for (const def of GROUP_DEFS) {\n const selected = def.selected(state);\n for (const { value } of def.values) {\n if (selected.has(value)) params.append(def.param, value);\n }\n }\n\n return params;\n}\n\nfunction matchesQuery(skill: SkillInfo, query: string): boolean {\n const trimmed = query.trim();\n if (!trimmed) return true;\n\n const haystacks = [\n skill.name,\n getSkillCardDescription(skill),\n skill.description ?? \"\",\n skill.content ?? \"\",\n skill.license ?? \"\",\n skill.compatibility ?? \"\",\n ...(skill.triggers ?? []),\n ...(skill.allowed_tools ?? []),\n ];\n\n const lowered = trimmed.toLowerCase();\n return haystacks.some((value) => value.toLowerCase().includes(lowered));\n}\n\n/**\n * `exclude` omits one group's own selection so its rows stay counted against the other groups alone.\n * A row therefore reads \"this many skills carry this value, under your other filters\" — the usual disjunctive facet count — and not \"your result set will be this big\": the group ORs its values together, so on a group that already has a selection the two differ.\n */\nfunction matchesFacets(\n skill: SkillInfo,\n disabledSet: Set<string>,\n state: SkillFilterState,\n exclude?: SkillFacetGroupId,\n): boolean {\n return GROUP_DEFS.every((def) => {\n if (def.id === exclude) return true;\n const selected = def.selected(state);\n if (selected.size === 0) return true;\n return selected.has(def.valueOf(skill, disabledSet));\n });\n}\n\nexport function applySkillFilters(\n skills: SkillInfo[],\n disabledSet: Set<string>,\n state: SkillFilterState,\n): SkillInfo[] {\n return skills.filter(\n (skill) =>\n matchesQuery(skill, state.query) &&\n matchesFacets(skill, disabledSet, state),\n );\n}\n\nfunction countByValue(\n skills: SkillInfo[],\n def: GroupDef,\n disabledSet: Set<string>,\n): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const skill of skills) {\n const value = def.valueOf(skill, disabledSet);\n counts[value] = (counts[value] ?? 0) + 1;\n }\n return counts;\n}\n\nfunction buildGroup(\n def: GroupDef,\n allSkills: SkillInfo[],\n searched: SkillInfo[],\n disabledSet: Set<string>,\n state: SkillFilterState,\n): SkillFacetGroup | null {\n // Visibility and the row set come from the raw list so the rail's shape\n // depends only on what the user has, never on the active filters. If they\n // tracked filtered counts, narrowing could make a group vanish mid-click.\n const rawCounts = countByValue(allSkills, def, disabledSet);\n const discriminating = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0,\n );\n const selected = def.selected(state);\n // A group with only one (or zero) discriminating values is normally hidden,\n // but a selection can still be carried in from the URL for a value that has\n // no matches for this user. Hiding the group then would enforce the filter\n // invisibly, with no row left to explain or undo it.\n if (discriminating.length < 2 && selected.size === 0) return null;\n\n const visibleValues = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0 || selected.has(value),\n );\n\n const candidates = searched.filter((skill) =>\n matchesFacets(skill, disabledSet, state, def.id),\n );\n const counts = countByValue(candidates, def, disabledSet);\n\n return {\n id: def.id,\n labelKey: def.labelKey,\n rows: visibleValues.map(({ value, labelKey }) => {\n const count = counts[value] ?? 0;\n const checked = selected.has(value);\n return {\n value,\n labelKey,\n count,\n checked,\n disabled: count === 0 && !checked,\n };\n }),\n };\n}\n\nexport function buildSkillFacetGroups(\n skills: SkillInfo[],\n disabledSet: Set<string>,\n state: SkillFilterState,\n): SkillFacetGroup[] {\n const searched = skills.filter((skill) => matchesQuery(skill, state.query));\n\n return GROUP_DEFS.map((def) =>\n buildGroup(def, skills, searched, disabledSet, state),\n ).filter((group): group is SkillFacetGroup => group !== null);\n}\n\nexport function toggleSkillFilterValue(\n state: SkillFilterState,\n groupId: SkillFacetGroupId,\n value: string,\n): SkillFilterState {\n const def = groupDef(groupId);\n // `withSelected` would drop an unknown value anyway; returning the same\n // state object keeps a no-op toggle from re-rendering or rewriting the URL.\n if (!def.values.some((candidate) => candidate.value === value)) return state;\n\n const next = new Set(def.selected(state));\n if (next.has(value)) {\n next.delete(value);\n } else {\n next.add(value);\n }\n\n return def.withSelected(state, next);\n}\n\nexport function clearSkillFilterFacets(\n state: SkillFilterState,\n): SkillFilterState {\n return { ...EMPTY_SKILL_FILTER_STATE, query: state.query };\n}\n\nexport function countActiveFilters(state: SkillFilterState): number {\n // The query is excluded: it is already visible in its own input, so counting\n // it would double-report in both the Filters badge and the summary row.\n return GROUP_DEFS.reduce((total, def) => total + def.selected(state).size, 0);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"skill-filter.js","names":[],"sources":["../../../../src/components/features/skills/skill-filter.ts"],"sourcesContent":["import type { SkillCategoryId } from \"@openhands/extensions/skills\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { SkillInfo, SkillType } from \"#/types/settings\";\nimport {\n getSkillCategory,\n SKILL_CATEGORY_LABEL_KEYS,\n SKILL_CATEGORY_ORDER,\n} from \"#/utils/skill-category\";\nimport {\n getSkillScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { isRecommendedSkill } from \"#/utils/skill-enablement\";\nimport { getSkillCardDescription } from \"./get-skill-card-description\";\n\nexport const SKILL_FILTER_QUERY_PARAM = \"q\";\nconst SOURCE_PARAM = \"source\";\nconst CATEGORY_PARAM = \"category\";\nconst TYPE_PARAM = \"type\";\nconst STATE_PARAM = \"state\";\nconst RECOMMENDATION_PARAM = \"recommendation\";\n\nexport type SkillEnabledState = \"enabled\" | \"disabled\";\nexport type SkillRecommendation = \"recommended\" | \"other\";\nexport type SkillFacetGroupId =\n | \"state\"\n | \"recommendation\"\n | \"source\"\n | \"category\"\n | \"type\";\n\nconst SKILL_ENABLED_STATE_ORDER: readonly SkillEnabledState[] = [\n \"enabled\",\n \"disabled\",\n];\nconst SKILL_RECOMMENDATION_ORDER: readonly SkillRecommendation[] = [\n \"recommended\",\n \"other\",\n];\nconst SKILL_TYPE_ORDER: readonly SkillType[] = [\n \"agentskills\",\n \"knowledge\",\n \"repo\",\n];\n\nexport interface SkillFilterState {\n query: string;\n sources: Set<SkillScope>;\n categories: Set<SkillCategoryId>;\n types: Set<SkillType>;\n states: Set<SkillEnabledState>;\n recommendations: Set<SkillRecommendation>;\n}\n\nexport interface SkillFacetRowModel {\n value: string;\n labelKey: I18nKey;\n count: number;\n checked: boolean;\n disabled: boolean;\n}\n\nexport interface SkillFacetGroup {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n rows: SkillFacetRowModel[];\n}\n\nexport const EMPTY_SKILL_FILTER_STATE: SkillFilterState = {\n query: \"\",\n sources: new Set(),\n categories: new Set(),\n types: new Set(),\n states: new Set(),\n recommendations: new Set(),\n};\n\n/** Carrying `labelKey`s rather than translated strings keeps this module pure, so its tests need no i18n. */\ninterface GroupValue {\n value: string;\n labelKey: I18nKey;\n}\n\nfunction labelledValues<TValue extends string>(\n order: readonly TValue[],\n labelKeys: Record<TValue, I18nKey>,\n): readonly GroupValue[] {\n return order.map((value) => ({ value, labelKey: labelKeys[value] }));\n}\n\n/** Resolving the two lists behind enablement is the caller's job, not this module's. */\ntype SkillEnabledPredicate = (skill: SkillInfo) => boolean;\n\n/** A new facet group is declared here and nowhere else: `selected` / `withSelected` are what keep every operation below driven by this table alone. */\ninterface GroupDef {\n id: SkillFacetGroupId;\n labelKey: I18nKey;\n param: string;\n values: readonly GroupValue[];\n valueOf: (skill: SkillInfo, isEnabled: SkillEnabledPredicate) => string;\n selected: (state: SkillFilterState) => Set<string>;\n withSelected: (\n state: SkillFilterState,\n next: Set<string>,\n ) => SkillFilterState;\n}\n\n/** Rebuilding rather than casting keeps every writer below cast-free: a value the group does not declare cannot survive. */\nfunction narrowSet<TValue extends string>(\n order: readonly TValue[],\n next: Set<string>,\n): Set<TValue> {\n return new Set(order.filter((value) => next.has(value)));\n}\n\nconst SOURCE_LABEL_KEYS: Record<SkillScope, I18nKey> = {\n project: I18nKey.SETTINGS$SKILLS_SOURCE_PROJECT,\n personal: I18nKey.SETTINGS$SKILLS_SOURCE_PERSONAL,\n public: I18nKey.SETTINGS$SKILLS_SOURCE_PUBLIC,\n};\n\nconst TYPE_LABEL_KEYS: Record<SkillType, I18nKey> = {\n agentskills: I18nKey.SETTINGS$SKILLS_TYPE_AGENTSKILLS,\n knowledge: I18nKey.SETTINGS$SKILLS_TYPE_KNOWLEDGE,\n repo: I18nKey.SETTINGS$SKILLS_TYPE_REPO,\n};\n\nconst STATE_LABEL_KEYS: Record<SkillEnabledState, I18nKey> = {\n enabled: I18nKey.SETTINGS$SKILLS_ENABLED,\n disabled: I18nKey.SETTINGS$SKILLS_DISABLED,\n};\n\nconst RECOMMENDATION_LABEL_KEYS: Record<SkillRecommendation, I18nKey> = {\n recommended: I18nKey.SETTINGS$SKILLS_RECOMMENDED,\n other: I18nKey.SETTINGS$SKILLS_RECOMMENDATION_OTHER,\n};\n\nconst GROUP_DEFS: readonly GroupDef[] = [\n {\n id: \"state\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_STATE,\n param: STATE_PARAM,\n values: labelledValues(SKILL_ENABLED_STATE_ORDER, STATE_LABEL_KEYS),\n valueOf: (skill, isEnabled) => (isEnabled(skill) ? \"enabled\" : \"disabled\"),\n selected: (state) => state.states,\n withSelected: (state, next) => ({\n ...state,\n states: narrowSet(SKILL_ENABLED_STATE_ORDER, next),\n }),\n },\n {\n id: \"recommendation\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_RECOMMENDATION,\n param: RECOMMENDATION_PARAM,\n values: labelledValues(\n SKILL_RECOMMENDATION_ORDER,\n RECOMMENDATION_LABEL_KEYS,\n ),\n valueOf: (skill) =>\n isRecommendedSkill(skill.name) ? \"recommended\" : \"other\",\n selected: (state) => state.recommendations,\n withSelected: (state, next) => ({\n ...state,\n recommendations: narrowSet(SKILL_RECOMMENDATION_ORDER, next),\n }),\n },\n {\n id: \"source\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_SOURCE,\n param: SOURCE_PARAM,\n values: labelledValues(SKILL_SCOPE_ORDER, SOURCE_LABEL_KEYS),\n valueOf: (skill) => getSkillScope(skill),\n selected: (state) => state.sources,\n withSelected: (state, next) => ({\n ...state,\n sources: narrowSet(SKILL_SCOPE_ORDER, next),\n }),\n },\n {\n id: \"category\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_CATEGORY,\n param: CATEGORY_PARAM,\n values: labelledValues(SKILL_CATEGORY_ORDER, SKILL_CATEGORY_LABEL_KEYS),\n valueOf: (skill) => getSkillCategory(skill),\n selected: (state) => state.categories,\n withSelected: (state, next) => ({\n ...state,\n categories: narrowSet(SKILL_CATEGORY_ORDER, next),\n }),\n },\n {\n id: \"type\",\n labelKey: I18nKey.SETTINGS$SKILLS_FACET_TYPE,\n param: TYPE_PARAM,\n values: labelledValues(SKILL_TYPE_ORDER, TYPE_LABEL_KEYS),\n valueOf: (skill) => skill.type,\n selected: (state) => state.types,\n withSelected: (state, next) => ({\n ...state,\n types: narrowSet(SKILL_TYPE_ORDER, next),\n }),\n },\n];\n\nfunction groupDef(id: SkillFacetGroupId): GroupDef {\n const def = GROUP_DEFS.find((candidate) => candidate.id === id);\n if (!def) throw new Error(`Unknown skill facet group: ${id}`);\n return def;\n}\n\n/** Unknown values are dropped, so a hand-edited URL cannot smuggle one in. */\nfunction parseSet(raw: string[], def: GroupDef): Set<string> {\n const legal = new Set(def.values.map(({ value }) => value));\n return new Set(\n raw.map((value) => value.trim()).filter((value) => legal.has(value)),\n );\n}\n\nexport function parseSkillFilterState(\n params: URLSearchParams,\n): SkillFilterState {\n return GROUP_DEFS.reduce<SkillFilterState>(\n (state, def) =>\n def.withSelected(state, parseSet(params.getAll(def.param), def)),\n {\n ...EMPTY_SKILL_FILTER_STATE,\n query: params.get(SKILL_FILTER_QUERY_PARAM) ?? \"\",\n },\n );\n}\n\nexport function toSkillFilterSearchParams(\n state: SkillFilterState,\n): URLSearchParams {\n const params = new URLSearchParams();\n if (state.query) params.set(SKILL_FILTER_QUERY_PARAM, state.query);\n\n // Canonical order keeps URLs deterministic regardless of click order.\n for (const def of GROUP_DEFS) {\n const selected = def.selected(state);\n for (const { value } of def.values) {\n if (selected.has(value)) params.append(def.param, value);\n }\n }\n\n return params;\n}\n\nfunction matchesQuery(skill: SkillInfo, query: string): boolean {\n const trimmed = query.trim();\n if (!trimmed) return true;\n\n const haystacks = [\n skill.name,\n getSkillCardDescription(skill),\n skill.description ?? \"\",\n skill.content ?? \"\",\n skill.license ?? \"\",\n skill.compatibility ?? \"\",\n ...(skill.triggers ?? []),\n ...(skill.allowed_tools ?? []),\n ];\n\n const lowered = trimmed.toLowerCase();\n return haystacks.some((value) => value.toLowerCase().includes(lowered));\n}\n\n/**\n * `exclude` omits one group's own selection so its rows stay counted against the other groups alone.\n * A row therefore reads \"this many skills carry this value, under your other filters\" — the usual disjunctive facet count — and not \"your result set will be this big\": the group ORs its values together, so on a group that already has a selection the two differ.\n */\nfunction matchesFacets(\n skill: SkillInfo,\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n exclude?: SkillFacetGroupId,\n): boolean {\n return GROUP_DEFS.every((def) => {\n if (def.id === exclude) return true;\n const selected = def.selected(state);\n if (selected.size === 0) return true;\n return selected.has(def.valueOf(skill, isEnabled));\n });\n}\n\nexport function applySkillFilters(\n skills: SkillInfo[],\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n): SkillInfo[] {\n return skills.filter(\n (skill) =>\n matchesQuery(skill, state.query) &&\n matchesFacets(skill, isEnabled, state),\n );\n}\n\nfunction countByValue(\n skills: SkillInfo[],\n def: GroupDef,\n isEnabled: SkillEnabledPredicate,\n): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const skill of skills) {\n const value = def.valueOf(skill, isEnabled);\n counts[value] = (counts[value] ?? 0) + 1;\n }\n return counts;\n}\n\nfunction buildGroup(\n def: GroupDef,\n allSkills: SkillInfo[],\n searched: SkillInfo[],\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n): SkillFacetGroup | null {\n // Visibility and the row set come from the raw list so the rail's shape\n // depends only on what the user has, never on the active filters. If they\n // tracked filtered counts, narrowing could make a group vanish mid-click.\n const rawCounts = countByValue(allSkills, def, isEnabled);\n const discriminating = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0,\n );\n const selected = def.selected(state);\n // A group with only one (or zero) discriminating values is normally hidden,\n // but a selection can still be carried in from the URL for a value that has\n // no matches for this user. Hiding the group then would enforce the filter\n // invisibly, with no row left to explain or undo it.\n if (discriminating.length < 2 && selected.size === 0) return null;\n\n const visibleValues = def.values.filter(\n ({ value }) => (rawCounts[value] ?? 0) > 0 || selected.has(value),\n );\n\n const candidates = searched.filter((skill) =>\n matchesFacets(skill, isEnabled, state, def.id),\n );\n const counts = countByValue(candidates, def, isEnabled);\n\n return {\n id: def.id,\n labelKey: def.labelKey,\n rows: visibleValues.map(({ value, labelKey }) => {\n const count = counts[value] ?? 0;\n const checked = selected.has(value);\n return {\n value,\n labelKey,\n count,\n checked,\n disabled: count === 0 && !checked,\n };\n }),\n };\n}\n\nexport function buildSkillFacetGroups(\n skills: SkillInfo[],\n isEnabled: SkillEnabledPredicate,\n state: SkillFilterState,\n): SkillFacetGroup[] {\n const searched = skills.filter((skill) => matchesQuery(skill, state.query));\n\n return GROUP_DEFS.map((def) =>\n buildGroup(def, skills, searched, isEnabled, state),\n ).filter((group): group is SkillFacetGroup => group !== null);\n}\n\nexport function toggleSkillFilterValue(\n state: SkillFilterState,\n groupId: SkillFacetGroupId,\n value: string,\n): SkillFilterState {\n const def = groupDef(groupId);\n // `withSelected` would drop an unknown value anyway; returning the same\n // state object keeps a no-op toggle from re-rendering or rewriting the URL.\n if (!def.values.some((candidate) => candidate.value === value)) return state;\n\n const next = new Set(def.selected(state));\n if (next.has(value)) {\n next.delete(value);\n } else {\n next.add(value);\n }\n\n return def.withSelected(state, next);\n}\n\nexport function clearSkillFilterFacets(\n state: SkillFilterState,\n): SkillFilterState {\n return { ...EMPTY_SKILL_FILTER_STATE, query: state.query };\n}\n\nexport function countActiveFilters(state: SkillFilterState): number {\n // The query is excluded: it is already visible in its own input, so counting\n // it would double-report in both the Filters badge and the summary row.\n return GROUP_DEFS.reduce((total, def) => total + def.selected(state).size, 0);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../../i18n/declaration.cjs"),r=require("../../../../utils/constants.cjs"),i=require("../../../../context/navigation-context.cjs"),a=require("../../../../hooks/use-tracking.cjs"),o=require("../modal-backdrop.cjs"),s=require("
|
|
1
|
+
const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../../i18n/declaration.cjs"),r=require("../../../../utils/constants.cjs"),i=require("../../../../context/navigation-context.cjs"),a=require("../../../../hooks/use-tracking.cjs"),o=require("../modal-backdrop.cjs"),s=require("../../../../hooks/mutation/use-save-settings.cjs"),c=require("../../../features/settings/brand-button.cjs"),l=require("../../../../utils/settings-utils.cjs"),u=require("../../../features/settings/settings-input.cjs"),d=require("../../../../ui/help-link.cjs"),f=require("./model-selector.cjs"),p=require("../../../../utils/sdk-settings-schema.cjs"),m=require("../confirmation-modals/danger-modal.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime");function _({settings:e,onClose:_}){let{trackSettingsSaved:v}=a.useTracking(),{mutate:y}=s.useSaveSettings(),{currentPath:b}=i.useNavigation(),{t:x}=t.useTranslation(`openhands`),S=h.default.useRef(null),[C,w]=h.default.useState(!1),T=async e=>{let t=l.extractSettings(e);await y(t,{onSuccess:()=>{_();let e=t.agent_settings_diff?.llm??{};v({llmModel:e.model,llmApiKeySet:e.api_key?`SET`:`UNSET`,searchApiKeySet:t.search_api_key?`SET`:`UNSET`,remoteRuntimeResourceFactor:t.remote_runtime_resource_factor})}})},E=()=>{T(new FormData(S.current??void 0))},D=e=>{e.preventDefault();let t=new FormData(e.currentTarget);b.startsWith(`/conversations/`)?w(!0):T(t)},O=e.llm_api_key_set,k=p.getAgentSettingValue(e,`llm.model`);return(0,g.jsxs)(`div`,{children:[(0,g.jsxs)(`form`,{ref:S,"data-testid":`settings-form`,className:`flex flex-col gap-6`,onSubmit:D,children:[(0,g.jsxs)(`div`,{className:`flex flex-col gap-[17px]`,children:[(0,g.jsx)(f.ModelSelector,{currentModel:typeof k==`string`?k:void 0,wrapperClassName:`!flex-col !gap-[17px]`,labelClassName:r.SETTINGS_FORM.LABEL_CLASSNAME}),(0,g.jsx)(u.SettingsInput,{testId:`llm-api-key-input`,name:`llm-api-key-input`,label:x(n.I18nKey.SETTINGS_FORM$API_KEY),type:`password`,className:`w-full`,placeholder:O?`<hidden>`:``,labelClassName:r.SETTINGS_FORM.LABEL_CLASSNAME}),(0,g.jsx)(d.HelpLink,{testId:`llm-api-key-help-anchor`,text:x(n.I18nKey.SETTINGS$DONT_KNOW_API_KEY),linkText:x(n.I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS),href:`https://docs.openhands.dev/usage/local-setup#getting-an-api-key`,size:`settings`,linkColor:`white`})]}),(0,g.jsx)(`div`,{className:`flex flex-col gap-2`,children:(0,g.jsx)(c.BrandButton,{testId:`save-settings-button`,type:`submit`,variant:`primary`,className:`w-full`,children:x(n.I18nKey.BUTTON$SAVE)})})]}),C&&(0,g.jsx)(o.ModalBackdrop,{children:(0,g.jsx)(m.DangerModal,{title:x(n.I18nKey.MODAL$END_SESSION_TITLE),description:x(n.I18nKey.MODAL$END_SESSION_MESSAGE),buttons:{danger:{text:x(n.I18nKey.BUTTON$END_SESSION),onClick:E},cancel:{text:x(n.I18nKey.BUTTON$CANCEL),onClick:()=>w(!1)}}})})]})}exports.SettingsForm=_;
|
|
2
2
|
//# sourceMappingURL=settings-form.cjs.map
|
|
@@ -4,10 +4,10 @@ import { SETTINGS_FORM as n } from "../../../../utils/constants.js";
|
|
|
4
4
|
import { useNavigation as r } from "../../../../context/navigation-context.js";
|
|
5
5
|
import { useTracking as i } from "../../../../hooks/use-tracking.js";
|
|
6
6
|
import { ModalBackdrop as a } from "../modal-backdrop.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { useSaveSettings as o } from "../../../../hooks/mutation/use-save-settings.js";
|
|
8
|
+
import { BrandButton as s } from "../../../features/settings/brand-button.js";
|
|
9
|
+
import { extractSettings as c } from "../../../../utils/settings-utils.js";
|
|
10
|
+
import { SettingsInput as l } from "../../../features/settings/settings-input.js";
|
|
11
11
|
import { HelpLink as u } from "../../../../ui/help-link.js";
|
|
12
12
|
import { ModelSelector as d } from "./model-selector.js";
|
|
13
13
|
import { getAgentSettingValue as f } from "../../../../utils/sdk-settings-schema.js";
|
|
@@ -16,8 +16,8 @@ import m from "react";
|
|
|
16
16
|
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
17
17
|
//#region src/components/shared/modals/settings/settings-form.tsx
|
|
18
18
|
function _({ settings: _, onClose: v }) {
|
|
19
|
-
let { trackSettingsSaved: y } = i(), { mutate: b } =
|
|
20
|
-
let t =
|
|
19
|
+
let { trackSettingsSaved: y } = i(), { mutate: b } = o(), { currentPath: x } = r(), { t: S } = e("openhands"), C = m.useRef(null), [w, T] = m.useState(!1), E = async (e) => {
|
|
20
|
+
let t = c(e);
|
|
21
21
|
await b(t, { onSuccess: () => {
|
|
22
22
|
v();
|
|
23
23
|
let e = t.agent_settings_diff?.llm ?? {};
|
|
@@ -48,7 +48,7 @@ function _({ settings: _, onClose: v }) {
|
|
|
48
48
|
wrapperClassName: "!flex-col !gap-[17px]",
|
|
49
49
|
labelClassName: n.LABEL_CLASSNAME
|
|
50
50
|
}),
|
|
51
|
-
/* @__PURE__ */ h(
|
|
51
|
+
/* @__PURE__ */ h(l, {
|
|
52
52
|
testId: "llm-api-key-input",
|
|
53
53
|
name: "llm-api-key-input",
|
|
54
54
|
label: S(t.SETTINGS_FORM$API_KEY),
|
|
@@ -68,7 +68,7 @@ function _({ settings: _, onClose: v }) {
|
|
|
68
68
|
]
|
|
69
69
|
}), /* @__PURE__ */ h("div", {
|
|
70
70
|
className: "flex flex-col gap-2",
|
|
71
|
-
children: /* @__PURE__ */ h(
|
|
71
|
+
children: /* @__PURE__ */ h(s, {
|
|
72
72
|
testId: "save-settings-button",
|
|
73
73
|
type: "submit",
|
|
74
74
|
variant: "primary",
|
package/dist/config/defaults.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../_virtual/_rolldown/runtime.cjs");var e={_comment:`Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.`,versions:{agentServer:`1.
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");var e={_comment:`Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.`,versions:{agentServer:`1.44.0`,agentCanvas:`1.16.0`,automation:`1.9.0`},compatibility:{minimumAgentServer:`1.28.0`},constraints:{_comment:`Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).`,agentClientProtocol:`agent-client-protocol<0.11`},images:{agentServer:`ghcr.io/openhands/agent-server`,agentCanvas:`ghcr.io/openhands/agent-canvas`},ports:{agentServer:18e3,automation:18001,proxy:8e3,_vscodeComment:`Port the bundled editor binds to inside the container; agent-server's own default. Only the Docker entrypoint reads this — the npm launchers derive the editor port from the agent-server port so several stacks can run side by side. It is never published: the editor is reached through paths.vscodeBasePath on the proxy port.`,vscode:8001},paths:{stateSubdir:`agent-canvas`,conversations:`agent-canvas/conversations`,bashEvents:`agent-canvas/bash_events`,automationDb:`automation/automations.db`,canvasBasePath:`/canvas`,_vscodeBasePathComment:`Path prefix the bundled editor is served under, on the same origin as the canvas. Passed to agent-server as OH_VSCODE_BASE_PATH (it launches openvscode-server with --server-base-path and advertises the prefix in /api/vscode/url), and registered as an ingress route to the VSCode port. Keeping one value on both sides is what lets a single-origin deployment reach the editor without publishing a second port. Tradeoff: a path prefix routes but does not isolate, so the editor shares the canvas's browser origin and therefore its localStorage — see docs/SELF_HOSTING.md and OpenHands/OpenHands#16492.`,vscodeBasePath:`/vscode`},packages:{agentServer:`openhands-agent-server`,automation:`openhands-automation`,tools:`openhands-tools`,workspace:`openhands-workspace`},telemetry:{posthogApiKey:`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,posthogHost:`https://us.i.posthog.com`}};exports.default=e;
|
|
2
2
|
//# sourceMappingURL=defaults.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.cjs","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.
|
|
1
|
+
{"version":3,"file":"defaults.cjs","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.44.0\",\n \"agentCanvas\": \"1.16.0\",\n \"automation\": \"1.9.0\"\n },\n \"compatibility\": {\n \"minimumAgentServer\": \"1.28.0\"\n },\n \"constraints\": {\n \"_comment\": \"Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).\",\n \"agentClientProtocol\": \"agent-client-protocol<0.11\"\n },\n \"images\": {\n \"agentServer\": \"ghcr.io/openhands/agent-server\",\n \"agentCanvas\": \"ghcr.io/openhands/agent-canvas\"\n },\n \"ports\": {\n \"agentServer\": 18000,\n \"automation\": 18001,\n \"proxy\": 8000,\n \"_vscodeComment\": \"Port the bundled editor binds to inside the container; agent-server's own default. Only the Docker entrypoint reads this — the npm launchers derive the editor port from the agent-server port so several stacks can run side by side. It is never published: the editor is reached through paths.vscodeBasePath on the proxy port.\",\n \"vscode\": 8001\n },\n \"paths\": {\n \"stateSubdir\": \"agent-canvas\",\n \"conversations\": \"agent-canvas/conversations\",\n \"bashEvents\": \"agent-canvas/bash_events\",\n \"automationDb\": \"automation/automations.db\",\n \"canvasBasePath\": \"/canvas\",\n \"_vscodeBasePathComment\": \"Path prefix the bundled editor is served under, on the same origin as the canvas. Passed to agent-server as OH_VSCODE_BASE_PATH (it launches openvscode-server with --server-base-path and advertises the prefix in /api/vscode/url), and registered as an ingress route to the VSCode port. Keeping one value on both sides is what lets a single-origin deployment reach the editor without publishing a second port. Tradeoff: a path prefix routes but does not isolate, so the editor shares the canvas's browser origin and therefore its localStorage — see docs/SELF_HOSTING.md and OpenHands/OpenHands#16492.\",\n \"vscodeBasePath\": \"/vscode\"\n },\n \"packages\": {\n \"agentServer\": \"openhands-agent-server\",\n \"automation\": \"openhands-automation\",\n \"tools\": \"openhands-tools\",\n \"workspace\": \"openhands-workspace\"\n },\n \"telemetry\": {\n \"posthogApiKey\": \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\",\n \"posthogHost\": \"https://us.i.posthog.com\"\n }\n}\n"],"mappings":""}
|
package/dist/config/defaults.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var e = {
|
|
2
2
|
_comment: "Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.",
|
|
3
3
|
versions: {
|
|
4
|
-
agentServer: "1.
|
|
5
|
-
agentCanvas: "1.
|
|
6
|
-
automation: "1.
|
|
4
|
+
agentServer: "1.44.0",
|
|
5
|
+
agentCanvas: "1.16.0",
|
|
6
|
+
automation: "1.9.0"
|
|
7
7
|
},
|
|
8
8
|
compatibility: { minimumAgentServer: "1.28.0" },
|
|
9
9
|
constraints: {
|
|
@@ -17,14 +17,18 @@ var e = {
|
|
|
17
17
|
ports: {
|
|
18
18
|
agentServer: 18e3,
|
|
19
19
|
automation: 18001,
|
|
20
|
-
proxy: 8e3
|
|
20
|
+
proxy: 8e3,
|
|
21
|
+
_vscodeComment: "Port the bundled editor binds to inside the container; agent-server's own default. Only the Docker entrypoint reads this — the npm launchers derive the editor port from the agent-server port so several stacks can run side by side. It is never published: the editor is reached through paths.vscodeBasePath on the proxy port.",
|
|
22
|
+
vscode: 8001
|
|
21
23
|
},
|
|
22
24
|
paths: {
|
|
23
25
|
stateSubdir: "agent-canvas",
|
|
24
26
|
conversations: "agent-canvas/conversations",
|
|
25
27
|
bashEvents: "agent-canvas/bash_events",
|
|
26
28
|
automationDb: "automation/automations.db",
|
|
27
|
-
canvasBasePath: "/canvas"
|
|
29
|
+
canvasBasePath: "/canvas",
|
|
30
|
+
_vscodeBasePathComment: "Path prefix the bundled editor is served under, on the same origin as the canvas. Passed to agent-server as OH_VSCODE_BASE_PATH (it launches openvscode-server with --server-base-path and advertises the prefix in /api/vscode/url), and registered as an ingress route to the VSCode port. Keeping one value on both sides is what lets a single-origin deployment reach the editor without publishing a second port. Tradeoff: a path prefix routes but does not isolate, so the editor shares the canvas's browser origin and therefore its localStorage — see docs/SELF_HOSTING.md and OpenHands/OpenHands#16492.",
|
|
31
|
+
vscodeBasePath: "/vscode"
|
|
28
32
|
},
|
|
29
33
|
packages: {
|
|
30
34
|
agentServer: "openhands-agent-server",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.
|
|
1
|
+
{"version":3,"file":"defaults.js","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.44.0\",\n \"agentCanvas\": \"1.16.0\",\n \"automation\": \"1.9.0\"\n },\n \"compatibility\": {\n \"minimumAgentServer\": \"1.28.0\"\n },\n \"constraints\": {\n \"_comment\": \"Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).\",\n \"agentClientProtocol\": \"agent-client-protocol<0.11\"\n },\n \"images\": {\n \"agentServer\": \"ghcr.io/openhands/agent-server\",\n \"agentCanvas\": \"ghcr.io/openhands/agent-canvas\"\n },\n \"ports\": {\n \"agentServer\": 18000,\n \"automation\": 18001,\n \"proxy\": 8000,\n \"_vscodeComment\": \"Port the bundled editor binds to inside the container; agent-server's own default. Only the Docker entrypoint reads this — the npm launchers derive the editor port from the agent-server port so several stacks can run side by side. It is never published: the editor is reached through paths.vscodeBasePath on the proxy port.\",\n \"vscode\": 8001\n },\n \"paths\": {\n \"stateSubdir\": \"agent-canvas\",\n \"conversations\": \"agent-canvas/conversations\",\n \"bashEvents\": \"agent-canvas/bash_events\",\n \"automationDb\": \"automation/automations.db\",\n \"canvasBasePath\": \"/canvas\",\n \"_vscodeBasePathComment\": \"Path prefix the bundled editor is served under, on the same origin as the canvas. Passed to agent-server as OH_VSCODE_BASE_PATH (it launches openvscode-server with --server-base-path and advertises the prefix in /api/vscode/url), and registered as an ingress route to the VSCode port. Keeping one value on both sides is what lets a single-origin deployment reach the editor without publishing a second port. Tradeoff: a path prefix routes but does not isolate, so the editor shares the canvas's browser origin and therefore its localStorage — see docs/SELF_HOSTING.md and OpenHands/OpenHands#16492.\",\n \"vscodeBasePath\": \"/vscode\"\n },\n \"packages\": {\n \"agentServer\": \"openhands-agent-server\",\n \"automation\": \"openhands-automation\",\n \"tools\": \"openhands-tools\",\n \"workspace\": \"openhands-workspace\"\n },\n \"telemetry\": {\n \"posthogApiKey\": \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\",\n \"posthogHost\": \"https://us.i.posthog.com\"\n }\n}\n"],"mappings":""}
|