@openhands/agent-canvas 1.7.2 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (599) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{Trans-DP5rcauH.js → Trans-Bwpzk1wT.js} +1 -1
  4. package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-C921BlYB.js} +1 -1
  5. package/build/assets/active-backend-context-BiwzkzDy.js +2 -0
  6. package/build/assets/agent-context-settings-DXNT_dcw.js +1 -0
  7. package/build/assets/agent-profiles-settings-BymJf3EP.js +1 -0
  8. package/build/assets/agent-server-conversation-service.api-CYSWw-2g.js +41 -0
  9. package/build/assets/agent-settings-BjgQQe-_.js +1 -0
  10. package/build/assets/{agent-settings-BIOsUglV.js → agent-settings-WzqXk6B4.js} +2 -2
  11. package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-DR8EVyZM.js} +1 -1
  12. package/build/assets/api-error-message-e16L1kwH.js +1 -0
  13. package/build/assets/api-key-entry-screen-DI0I04O3.js +1 -0
  14. package/build/assets/app-settings-DGistSFV.js +1 -0
  15. package/build/assets/automation-C_eCrGyP.js +1 -0
  16. package/build/assets/automation-detail-DY6x2FW1.js +2 -0
  17. package/build/assets/automation-export-C09f-Lua.js +2 -0
  18. package/build/assets/automation-setup-route-CqKp0717.js +1 -0
  19. package/build/assets/automations-list-CqWJ7qXW.js +1 -0
  20. package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-D4ngzpSh.js} +1 -1
  21. package/build/assets/backend-form-modal-B8D5hBzK.js +1 -0
  22. package/build/assets/{backend-synced-settings-badge-BNpEylNP.js → backend-synced-settings-badge-BnzI8Ysj.js} +1 -1
  23. package/build/assets/{badge-DwgrwohM.js → badge-1Mf1iPcX.js} +1 -1
  24. package/build/assets/{base-modal-CSHhJTSr.js → base-modal-BBuy0WQQ.js} +1 -1
  25. package/build/assets/{brand-button-CQO8oqVo.js → brand-button-DGN6Y9o6.js} +1 -1
  26. package/build/assets/browser-D_ekTlTS.js +6 -0
  27. package/build/assets/{browser-tab-CEApjoEV.js → browser-tab-D4a4Ou_w.js} +1 -1
  28. package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-CgbcjD97.js} +1 -1
  29. package/build/assets/check-CPLXgluF.js +1 -0
  30. package/build/assets/chevron-down-CP4QHvyc.js +1 -0
  31. package/build/assets/circle-check-Dpy2_xSI.js +1 -0
  32. package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-yTAS-nX3.js} +1 -1
  33. package/build/assets/cloud-funnel-analytics-CEOl5Gxr.js +1 -0
  34. package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Bd2yySnF.js} +1 -1
  35. package/build/assets/command-menu-Bj6X4ckE.js +1 -0
  36. package/build/assets/condenser-settings-EAXQNR2E.js +1 -0
  37. package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-NCUPr2-O.js} +1 -1
  38. package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-CrCrYuPF.js} +1 -1
  39. package/build/assets/conversation-BzyIcSwr.js +1 -0
  40. package/build/assets/conversation-CUJ0Vo8g.js +90 -0
  41. package/build/assets/conversation-panel-BzyIcSwr.js +1 -0
  42. package/build/assets/conversation-state-store-F62HvuI1.js +1 -0
  43. package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-BCZ7rUMH.js} +1 -1
  44. package/build/assets/{copy-B8Y5ufoR.js → copy-DCmZtz6n.js} +1 -1
  45. package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-D_Lp6-Fl.js} +1 -1
  46. package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-DLmolX8Q.js} +1 -1
  47. package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-BB8rzqXL.js} +1 -1
  48. package/build/assets/{entry.client-DETaouwO.js → entry.client-BbIYOsIg.js} +2 -2
  49. package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-C08-srev.js} +1 -1
  50. package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-BepBBX66.js} +1 -1
  51. package/build/assets/extensions-hub-R3KNv-5V.js +1 -0
  52. package/build/assets/extensions-navigation-CfWFmI1I.js +1 -0
  53. package/build/assets/{external-link-Cnnd6ikC.js → external-link-BdBSg8rk.js} +1 -1
  54. package/build/assets/files-tab-DEq8MbHu.js +1 -0
  55. package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-DAfsCJTe.js} +1 -1
  56. package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-CxfPJpzC.js} +1 -1
  57. package/build/assets/git-provider-icon-BZqqUPlm.js +1 -0
  58. package/build/assets/git-repo-dropdown-9WKINV6J.js +1 -0
  59. package/build/assets/git-repo-dropdown-DEpOwUez.js +1 -0
  60. package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-CX9oIoVT.js} +1 -1
  61. package/build/assets/home-CY0JaxiY.js +1 -0
  62. package/build/assets/home-CaNWlVvB.js +1 -0
  63. package/build/assets/home-store-Ch1ErdBc.js +1 -0
  64. package/build/assets/index-home-CaNWlVvB.js +1 -0
  65. package/build/assets/info-CmWQXtRQ.js +1 -0
  66. package/build/assets/install-server-modal-BWrudmZU.js +1 -0
  67. package/build/assets/{launch-Ccnhte5b.js → launch-B1POpHuP.js} +1 -1
  68. package/build/assets/{list-todo-_BXQzOiB.js → list-todo-DtiL3lTp.js} +1 -1
  69. package/build/assets/llm-not-configured-banner-3tMsM4K6.js +27 -0
  70. package/build/assets/llm-settings-CXo8iPNW.js +1 -0
  71. package/build/assets/llm-settings-D0W8mJDk.js +1 -0
  72. package/build/assets/{llm-subscription-service-W5BprsNA.js → llm-subscription-service-DBJbfd8Z.js} +1 -1
  73. package/build/assets/loader-circle-B4QDBARx.js +1 -0
  74. package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DfZ_bhV7.js} +1 -1
  75. package/build/assets/manage-backends-modal-CwyWsiag.js +1 -0
  76. package/build/assets/manifest-39f4789d.js +1 -0
  77. package/build/assets/{markdown-renderer-CvOO0YIr.js → markdown-renderer-DgiLLhW6.js} +6 -6
  78. package/build/assets/mcp-DXG9LWrI.js +9 -0
  79. package/build/assets/mcp-marketplace-utils-DFmhKc5s.js +1 -0
  80. package/build/assets/messages-kBjKaAeA.js +40 -0
  81. package/build/assets/{modal-body-DQhiw-AR.js → modal-body-CMsDpalT.js} +1 -1
  82. package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-B6PDrxXo.js} +1 -1
  83. package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-DyxBZaAb.js} +1 -1
  84. package/build/assets/{onboarding-BegDrOKn.js → onboarding-47hh2IHA.js} +1 -1
  85. package/build/assets/onboarding-modal-9BuvvROo.js +1 -0
  86. package/build/assets/organization-service.api-UDy63-oC.js +1 -0
  87. package/build/assets/{pencil-8_lvWDoZ.js → pencil-BjgtZmWp.js} +1 -1
  88. package/build/assets/{planner-tab-w6HT0N_A.js → planner-tab-BWk8885v.js} +1 -1
  89. package/build/assets/plugins-management-service-CjkgF2dd.js +1 -0
  90. package/build/assets/plus-DrKuuvMe.js +1 -0
  91. package/build/assets/profiles-service.api-CukSFLzz.js +1 -0
  92. package/build/assets/providers-CqUWC85T.js +1 -0
  93. package/build/assets/proxy-BBUG3sd2.js +1 -0
  94. package/build/assets/{puzzle-DXWdfaa7.js → puzzle-BoNc6zZ8.js} +1 -1
  95. package/build/assets/recommended-automations-launcher-ejxy1P27.js +1 -0
  96. package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-BrM5ZAZD.js} +1 -1
  97. package/build/assets/root-5S-M8SYa.js +2 -0
  98. package/build/assets/root-DZ39lS5f.css +1 -0
  99. package/build/assets/root-layout-BPqoa0gv.js +3 -0
  100. package/build/assets/schema-field-nImDoY6-.js +1 -0
  101. package/build/assets/{sdk-section-page-BW-i45yr.js → sdk-section-page-BxMrtUNV.js} +1 -1
  102. package/build/assets/search-Dc2qR4O2.js +1 -0
  103. package/build/assets/secrets-service-Dhjh3HhH.js +1 -0
  104. package/build/assets/{secrets-settings-D7U1ErCH.js → secrets-settings-CPdxceT_.js} +1 -1
  105. package/build/assets/segmented-toggle-Do6oyepX.js +1 -0
  106. package/build/assets/settings-BRbnfKEm.js +1 -0
  107. package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-DYCULKpp.js} +1 -1
  108. package/build/assets/{settings-index-COAdxm2Q.js → settings-index-C9o2NBO0.js} +1 -1
  109. package/build/assets/settings-input-B-q2gkVy.js +1 -0
  110. package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-WpQi0q1L.js} +1 -1
  111. package/build/assets/{settings-modal-CFnbQ8_4.js → settings-modal-CEK0AIx6.js} +1 -1
  112. package/build/assets/settings-service.api-CZiPD8__.js +1 -0
  113. package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-LqKdGxHL.js} +1 -1
  114. package/build/assets/shared-conversation-Bu-dQlgp.js +1 -0
  115. package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-oHBGQmLh.js} +1 -1
  116. package/build/assets/{sidebar-mobile-menu-toggle-U78hQRJ1.js → sidebar-mobile-menu-toggle-ND-hgygu.js} +1 -1
  117. package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-CrujNA09.js} +1 -1
  118. package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-Bui-WNEr.js} +1 -1
  119. package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-CZBI7OqH.js} +1 -1
  120. package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-BOov_phZ.js} +1 -1
  121. package/build/assets/{skills-plugins-BPhaNpfx.js → skills-plugins-D0PiHWAD.js} +1 -1
  122. package/build/assets/{skills-settings-CcwMtnnJ.js → skills-settings-B43KArIz.js} +2 -2
  123. package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-C7grwnOX.js} +1 -1
  124. package/build/assets/{task-list-tab-BmaTwjaS.js → task-list-tab-R3ac6m7O.js} +1 -1
  125. package/build/assets/{terminal-BRcoba5B.js → terminal-yqkNdEAx.js} +1 -1
  126. package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-BeSrbgCg.js} +1 -1
  127. package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-wW5TWcdN.js} +1 -1
  128. package/build/assets/{typography-C6fuRTTT.js → typography-iYhzLlHO.js} +1 -1
  129. package/build/assets/{use-acp-credential-form-B0_pZ_uS.js → use-acp-credential-form-DUxbxmbq.js} +1 -1
  130. package/build/assets/use-activate-agent-profile-CDHA52tC.js +1 -0
  131. package/build/assets/use-agent-profiles-TsOdIyw5.js +1 -0
  132. package/build/assets/{use-can-manage-org-profiles-CrG1km7R.js → use-can-manage-org-profiles-Bt1M71u5.js} +1 -1
  133. package/build/assets/use-cloud-current-user-id-DWt7HCgf.js +1 -0
  134. package/build/assets/{use-config-Csy8EAP9.js → use-config-CxlEdf_v.js} +1 -1
  135. package/build/assets/{use-create-conversation-Dsa4nzU9.js → use-create-conversation-nOJ6Um5h.js} +1 -1
  136. package/build/assets/{use-create-secret-BnxuAjDt.js → use-create-secret-Dj5ang9x.js} +1 -1
  137. package/build/assets/use-is-authed-BT7Iud4U.js +1 -0
  138. package/build/assets/{use-is-creating-conversation-CIAcnd8M.js → use-is-creating-conversation-CAggrM75.js} +1 -1
  139. package/build/assets/use-llm-profiles-2Wc2db8u.js +1 -0
  140. package/build/assets/use-onboarding-completion-gxQlcEy2.js +1 -0
  141. package/build/assets/use-plugins-marketplace-CVO7sXYR.js +1 -0
  142. package/build/assets/use-save-agent-profile-D0wC5ExW.js +1 -0
  143. package/build/assets/{use-save-settings-BRh9p_fv.js → use-save-settings-L3aMaDeS.js} +1 -1
  144. package/build/assets/use-settings-8nt3DGxW.js +1 -0
  145. package/build/assets/use-settings-nav-items-DHAAD-zk.js +16 -0
  146. package/build/assets/use-skills-CE6miQ3r.js +1 -0
  147. package/build/assets/use-tracking-BGboadaZ.js +68 -0
  148. package/build/assets/{use-user-conversation-GnGhs_Ob.js → use-user-conversation-BIIpGUgM.js} +1 -1
  149. package/build/assets/useInfiniteQuery-BLRVmVPU.js +1 -0
  150. package/build/assets/{useMutation-DyQXZFEF.js → useMutation-CaSHLnX0.js} +1 -1
  151. package/build/assets/{useQueries-B3T1a7qt.js → useQueries--d_WWAzc.js} +1 -1
  152. package/build/assets/{useQuery-B38jBavx.js → useQuery-DiPh8LRJ.js} +1 -1
  153. package/build/assets/utils-BgGG1znF.js +1 -0
  154. package/build/assets/{vendor~browser-CIoZCqGs.js → vendor~browser-IVYgIgG1.js} +1 -1
  155. package/build/assets/{vendor~entry.client-Di4qO77Y.js → vendor~entry.client-BcYIVQvB.js} +1 -1
  156. package/build/assets/{vendor~entry.client-BfviqoVc.js → vendor~entry.client-CXM9oiAk.js} +1 -1
  157. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0bpqexo-CbTboogo.js} +2 -2
  158. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f9xdmd0z-DLMP7bZx.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~d4by102p-C2f0ZhS-.js} +1 -1
  159. package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-C7RmQJwN.js} +1 -1
  160. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-Bqp1ZqJM.js} +1 -1
  161. package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-BCn8lzeG.js} +1 -1
  162. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~automation-setup-route-B_L-gcOG.js +1 -0
  163. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-sjx0x5ac.js +1 -0
  164. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~automation-setup-route~onboarding-modal-D7IDevqN.js +1 -0
  165. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~bi2r7bko-Bw4AuHN1.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~dfc8ddxy-tTyxnjXT.js} +1 -1
  166. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hakxo2tj-ClV0p9g3.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gy8zbn65-CGt6bWRT.js} +1 -1
  167. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~eywn6ulz-BKxxr74w.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~dufan6ng-Dtdw8H0q.js} +17 -4
  168. package/build/assets/{verification-settings-CaCzojbc.js → verification-settings-DBsnSXC3.js} +1 -1
  169. package/build/assets/x-omAzpXkl.js +1 -0
  170. package/build/favicon-16x16.png +0 -0
  171. package/build/favicon-32x32.png +0 -0
  172. package/build/favicon.ico +0 -0
  173. package/build/index.html +4 -4
  174. package/build/locales/ar/openhands.json +39 -2
  175. package/build/locales/ca/openhands.json +39 -2
  176. package/build/locales/de/openhands.json +39 -2
  177. package/build/locales/en/openhands.json +40 -3
  178. package/build/locales/es/openhands.json +39 -2
  179. package/build/locales/fr/openhands.json +39 -2
  180. package/build/locales/it/openhands.json +39 -2
  181. package/build/locales/ja/openhands.json +39 -2
  182. package/build/locales/ko-KR/openhands.json +39 -2
  183. package/build/locales/no/openhands.json +39 -2
  184. package/build/locales/pt/openhands.json +39 -2
  185. package/build/locales/tr/openhands.json +39 -2
  186. package/build/locales/uk/openhands.json +39 -2
  187. package/build/locales/zh-CN/openhands.json +39 -2
  188. package/build/locales/zh-TW/openhands.json +39 -2
  189. package/config/defaults.json +4 -4
  190. package/dist/api/agent-server-adapter.cjs +3 -3
  191. package/dist/api/agent-server-adapter.cjs.map +1 -1
  192. package/dist/api/agent-server-adapter.d.ts +46 -6
  193. package/dist/api/agent-server-adapter.js +187 -168
  194. package/dist/api/agent-server-adapter.js.map +1 -1
  195. package/dist/api/agent-server-compatibility.cjs +1 -1
  196. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  197. package/dist/api/agent-server-compatibility.d.ts +4 -0
  198. package/dist/api/agent-server-compatibility.js +41 -38
  199. package/dist/api/agent-server-compatibility.js.map +1 -1
  200. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  201. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  202. package/dist/api/automation-service/automation-service.api.d.ts +20 -0
  203. package/dist/api/automation-service/automation-service.api.js +136 -99
  204. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  205. package/dist/api/backend-registry/storage.cjs +1 -1
  206. package/dist/api/backend-registry/storage.cjs.map +1 -1
  207. package/dist/api/backend-registry/storage.js +1 -1
  208. package/dist/api/backend-registry/storage.js.map +1 -1
  209. package/dist/api/backend-registry/types.d.ts +2 -0
  210. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  211. package/dist/api/cloud/conversation-service.api.js +22 -22
  212. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  213. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  214. package/dist/api/mcp-service/mcp-service.api.js +19 -19
  215. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  216. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  217. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  218. package/dist/api/settings-service/settings-service.api.js +26 -12
  219. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  220. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +2 -0
  221. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -0
  222. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.d.ts +12 -0
  223. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +94 -0
  224. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -0
  225. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
  226. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
  227. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +31 -90
  228. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
  229. package/dist/components/features/automations/recommended-automations-launcher.d.ts +0 -7
  230. package/dist/components/features/automations/recommended-automations-section.d.ts +0 -6
  231. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  232. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  233. package/dist/components/features/backends/backend-form-modal.js +568 -358
  234. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  235. package/dist/components/features/backends/device-flow-auth.cjs +1 -1
  236. package/dist/components/features/backends/device-flow-auth.cjs.map +1 -1
  237. package/dist/components/features/backends/device-flow-auth.d.ts +9 -1
  238. package/dist/components/features/backends/device-flow-auth.js +56 -55
  239. package/dist/components/features/backends/device-flow-auth.js.map +1 -1
  240. package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
  241. package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
  242. package/dist/components/features/backends/manage-backends-modal.js +1 -1
  243. package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
  244. package/dist/components/features/chat/chat-interface.cjs +1 -1
  245. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  246. package/dist/components/features/chat/chat-interface.js +105 -105
  247. package/dist/components/features/chat/chat-interface.js.map +1 -1
  248. package/dist/components/features/chat/chat-message.cjs +1 -1
  249. package/dist/components/features/chat/chat-message.cjs.map +1 -1
  250. package/dist/components/features/chat/chat-message.d.ts +2 -1
  251. package/dist/components/features/chat/chat-message.js +59 -49
  252. package/dist/components/features/chat/chat-message.js.map +1 -1
  253. package/dist/components/features/chat/pending-user-messages.cjs +1 -1
  254. package/dist/components/features/chat/pending-user-messages.cjs.map +1 -1
  255. package/dist/components/features/chat/pending-user-messages.js +4 -1
  256. package/dist/components/features/chat/pending-user-messages.js.map +1 -1
  257. package/dist/components/features/chat/typing-indicator.cjs +1 -1
  258. package/dist/components/features/chat/typing-indicator.cjs.map +1 -1
  259. package/dist/components/features/chat/typing-indicator.d.ts +8 -1
  260. package/dist/components/features/chat/typing-indicator.js +94 -10
  261. package/dist/components/features/chat/typing-indicator.js.map +1 -1
  262. package/dist/components/features/command-menu/command-menu-items.d.ts +5 -1
  263. package/dist/components/features/files-tab/segmented-toggle.cjs +1 -1
  264. package/dist/components/features/files-tab/segmented-toggle.cjs.map +1 -1
  265. package/dist/components/features/files-tab/segmented-toggle.d.ts +2 -0
  266. package/dist/components/features/files-tab/segmented-toggle.js +17 -14
  267. package/dist/components/features/files-tab/segmented-toggle.js.map +1 -1
  268. package/dist/components/features/manifest/manifest-form-field.d.ts +27 -0
  269. package/dist/components/features/manifest/manifest-prerequisites-step.d.ts +11 -0
  270. package/dist/components/features/manifest/manifest-review-step.d.ts +14 -0
  271. package/dist/components/features/manifest/manifest-setup-dialog.d.ts +14 -0
  272. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  273. package/dist/components/features/mcp-page/custom-server-editor.js +16 -16
  274. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  275. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  276. package/dist/components/features/mcp-page/installed-server-card.d.ts +2 -2
  277. package/dist/components/features/mcp-page/installed-server-card.js +6 -7
  278. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  279. package/dist/components/features/mcp-page/installed-servers-section.cjs +1 -1
  280. package/dist/components/features/mcp-page/installed-servers-section.cjs.map +1 -1
  281. package/dist/components/features/mcp-page/installed-servers-section.d.ts +2 -2
  282. package/dist/components/features/mcp-page/installed-servers-section.js +2 -2
  283. package/dist/components/features/mcp-page/installed-servers-section.js.map +1 -1
  284. package/dist/components/features/mcp-page/mcp-server-health.cjs +1 -1
  285. package/dist/components/features/mcp-page/mcp-server-health.js +4 -4
  286. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +1 -1
  287. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
  288. package/dist/components/features/settings/mcp-settings/mcp-server-form.js +2 -1
  289. package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
  290. package/dist/components/features/settings/settings-input.cjs +1 -1
  291. package/dist/components/features/settings/settings-input.cjs.map +1 -1
  292. package/dist/components/features/settings/settings-input.d.ts +6 -0
  293. package/dist/components/features/settings/settings-input.js +13 -8
  294. package/dist/components/features/settings/settings-input.js.map +1 -1
  295. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  296. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  297. package/dist/components/features/sidebar/sidebar-rail-body.js +124 -123
  298. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  299. package/dist/config/defaults.cjs +1 -1
  300. package/dist/config/defaults.cjs.map +1 -1
  301. package/dist/config/defaults.js +3 -3
  302. package/dist/config/defaults.js.map +1 -1
  303. package/dist/contexts/active-backend-context.cjs +1 -1
  304. package/dist/contexts/active-backend-context.cjs.map +1 -1
  305. package/dist/contexts/active-backend-context.d.ts +3 -2
  306. package/dist/contexts/active-backend-context.js +55 -42
  307. package/dist/contexts/active-backend-context.js.map +1 -1
  308. package/dist/favicon-16x16.png +0 -0
  309. package/dist/favicon-32x32.png +0 -0
  310. package/dist/favicon.ico +0 -0
  311. package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
  312. package/dist/hooks/mutation/use-update-mcp-server.js +5 -5
  313. package/dist/hooks/query/query-keys.cjs.map +1 -1
  314. package/dist/hooks/query/query-keys.d.ts +4 -0
  315. package/dist/hooks/query/query-keys.js.map +1 -1
  316. package/dist/hooks/query/use-cloud-current-user-id.cjs +1 -1
  317. package/dist/hooks/query/use-cloud-current-user-id.cjs.map +1 -1
  318. package/dist/hooks/query/use-cloud-current-user-id.js +7 -5
  319. package/dist/hooks/query/use-cloud-current-user-id.js.map +1 -1
  320. package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
  321. package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
  322. package/dist/hooks/query/use-cloud-organizations.js +5 -1
  323. package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
  324. package/dist/hooks/query/use-manifest-capabilities.d.ts +21 -0
  325. package/dist/hooks/query/use-manifest-prerequisites.d.ts +24 -0
  326. package/dist/hooks/use-can-manage-org-profiles.cjs +1 -1
  327. package/dist/hooks/use-can-manage-org-profiles.cjs.map +1 -1
  328. package/dist/hooks/use-can-manage-org-profiles.js +2 -1
  329. package/dist/hooks/use-can-manage-org-profiles.js.map +1 -1
  330. package/dist/hooks/use-llm-configured.cjs +1 -1
  331. package/dist/hooks/use-llm-configured.cjs.map +1 -1
  332. package/dist/hooks/use-llm-configured.js +2 -1
  333. package/dist/hooks/use-llm-configured.js.map +1 -1
  334. package/dist/hooks/use-manifest-preflight.d.ts +18 -0
  335. package/dist/hooks/use-tracking.cjs +1 -1
  336. package/dist/hooks/use-tracking.cjs.map +1 -1
  337. package/dist/hooks/use-tracking.d.ts +14 -0
  338. package/dist/hooks/use-tracking.js +28 -10
  339. package/dist/hooks/use-tracking.js.map +1 -1
  340. package/dist/i18n/declaration.cjs +1 -1
  341. package/dist/i18n/declaration.cjs.map +1 -1
  342. package/dist/i18n/declaration.d.ts +38 -1
  343. package/dist/i18n/declaration.js +1 -1
  344. package/dist/i18n/declaration.js.map +1 -1
  345. package/dist/i18n/translation.cjs +2 -2
  346. package/dist/i18n/translation.cjs.map +1 -1
  347. package/dist/i18n/translation.js +645 -16
  348. package/dist/i18n/translation.js.map +1 -1
  349. package/dist/icons/external-link.cjs +2 -0
  350. package/dist/icons/external-link.cjs.map +1 -0
  351. package/dist/icons/external-link.js +22 -0
  352. package/dist/icons/external-link.js.map +1 -0
  353. package/dist/icons/server.cjs +2 -0
  354. package/dist/icons/server.cjs.map +1 -0
  355. package/dist/icons/server.js +17 -0
  356. package/dist/icons/server.js.map +1 -0
  357. package/dist/locales/ar/openhands.json +39 -2
  358. package/dist/locales/ca/openhands.json +39 -2
  359. package/dist/locales/de/openhands.json +39 -2
  360. package/dist/locales/en/openhands.json +40 -3
  361. package/dist/locales/es/openhands.json +39 -2
  362. package/dist/locales/fr/openhands.json +39 -2
  363. package/dist/locales/it/openhands.json +39 -2
  364. package/dist/locales/ja/openhands.json +39 -2
  365. package/dist/locales/ko-KR/openhands.json +39 -2
  366. package/dist/locales/no/openhands.json +39 -2
  367. package/dist/locales/pt/openhands.json +39 -2
  368. package/dist/locales/tr/openhands.json +39 -2
  369. package/dist/locales/uk/openhands.json +39 -2
  370. package/dist/locales/zh-CN/openhands.json +39 -2
  371. package/dist/locales/zh-TW/openhands.json +39 -2
  372. package/dist/manifests/automation-interface.cjs +2 -0
  373. package/dist/manifests/automation-interface.cjs.map +1 -0
  374. package/dist/manifests/automation-interface.d.ts +44 -0
  375. package/dist/manifests/automation-interface.js +81 -0
  376. package/dist/manifests/automation-interface.js.map +1 -0
  377. package/dist/manifests/automation-setup.cjs +2 -0
  378. package/dist/manifests/automation-setup.cjs.map +1 -0
  379. package/dist/manifests/automation-setup.d.ts +52 -0
  380. package/dist/manifests/automation-setup.js +8 -0
  381. package/dist/manifests/automation-setup.js.map +1 -0
  382. package/dist/manifests/interface-validation.cjs +2 -0
  383. package/dist/manifests/interface-validation.cjs.map +1 -0
  384. package/dist/manifests/interface-validation.d.ts +27 -0
  385. package/dist/manifests/interface-validation.js +182 -0
  386. package/dist/manifests/interface-validation.js.map +1 -0
  387. package/dist/manifests/manifest-actions.d.ts +15 -0
  388. package/dist/manifests/manifest-capabilities.d.ts +25 -0
  389. package/dist/manifests/manifest-error-map.d.ts +40 -0
  390. package/dist/manifests/manifest-local-validation.d.ts +56 -0
  391. package/dist/manifests/manifest-registry.cjs +2 -0
  392. package/dist/manifests/manifest-registry.cjs.map +1 -0
  393. package/dist/manifests/manifest-registry.d.ts +15 -0
  394. package/dist/manifests/manifest-registry.js +26 -0
  395. package/dist/manifests/manifest-registry.js.map +1 -0
  396. package/dist/manifests/manifest-sources.cjs +2 -0
  397. package/dist/manifests/manifest-sources.cjs.map +1 -0
  398. package/dist/manifests/manifest-sources.d.ts +15 -0
  399. package/dist/manifests/manifest-sources.js +8 -0
  400. package/dist/manifests/manifest-sources.js.map +1 -0
  401. package/dist/manifests/manifest-template.d.ts +18 -0
  402. package/dist/manifests/manifest-validation.cjs +2 -0
  403. package/dist/manifests/manifest-validation.cjs.map +1 -0
  404. package/dist/manifests/manifest-validation.d.ts +30 -0
  405. package/dist/manifests/manifest-validation.js +145 -0
  406. package/dist/manifests/manifest-validation.js.map +1 -0
  407. package/dist/manifests/types.cjs +2 -0
  408. package/dist/manifests/types.cjs.map +1 -0
  409. package/dist/manifests/types.d.ts +227 -0
  410. package/dist/manifests/types.js +6 -0
  411. package/dist/manifests/types.js.map +1 -0
  412. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +9 -0
  413. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -0
  414. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +75 -0
  415. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -0
  416. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +9 -0
  417. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -0
  418. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +78 -0
  419. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -0
  420. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs +17 -0
  421. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs.map +1 -0
  422. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js +89 -0
  423. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js.map +1 -0
  424. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs +10 -0
  425. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs.map +1 -0
  426. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js +17 -0
  427. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js.map +1 -0
  428. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs +9 -0
  429. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs.map +1 -0
  430. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js +15 -0
  431. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js.map +1 -0
  432. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs +9 -0
  433. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs.map +1 -0
  434. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js +18 -0
  435. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js.map +1 -0
  436. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs +9 -0
  437. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs.map +1 -0
  438. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js +14 -0
  439. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js.map +1 -0
  440. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs +9 -0
  441. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs.map +1 -0
  442. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js +14 -0
  443. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js.map +1 -0
  444. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +2 -0
  445. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -0
  446. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +23 -0
  447. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -0
  448. package/dist/node_modules/@openhands/extensions/automations/index.cjs +2 -0
  449. package/dist/node_modules/@openhands/extensions/automations/index.cjs.map +1 -0
  450. package/dist/node_modules/@openhands/extensions/automations/index.js +18 -0
  451. package/dist/node_modules/@openhands/extensions/automations/index.js.map +1 -0
  452. package/dist/node_modules/@openhands/extensions/automations/interface.cjs +2 -0
  453. package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -0
  454. package/dist/node_modules/@openhands/extensions/automations/interface.js +89 -0
  455. package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -0
  456. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
  457. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
  458. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +3 -3
  459. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
  460. package/dist/node_modules/@openhands/extensions/skills/index.cjs +17 -4
  461. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  462. package/dist/node_modules/@openhands/extensions/skills/index.js +5 -5
  463. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  464. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
  465. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
  466. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +9 -0
  467. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
  468. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs +2 -0
  469. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs.map +1 -0
  470. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js +29 -0
  471. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js.map +1 -0
  472. package/dist/package.cjs +1 -1
  473. package/dist/package.cjs.map +1 -1
  474. package/dist/package.js +3 -3
  475. package/dist/package.js.map +1 -1
  476. package/dist/routes/app-settings.cjs +1 -1
  477. package/dist/routes/app-settings.js +5 -5
  478. package/dist/routes/mcp.cjs +1 -1
  479. package/dist/routes/mcp.cjs.map +1 -1
  480. package/dist/routes/mcp.js +73 -82
  481. package/dist/routes/mcp.js.map +1 -1
  482. package/dist/services/telemetry.cjs +1 -1
  483. package/dist/services/telemetry.cjs.map +1 -1
  484. package/dist/services/telemetry.d.ts +8 -0
  485. package/dist/services/telemetry.js +163 -116
  486. package/dist/services/telemetry.js.map +1 -1
  487. package/dist/types/agent-server/core/events/conversation-state-event.d.ts +2 -19
  488. package/dist/types/agent-server/core/events/observation-event.d.ts +2 -18
  489. package/dist/types/automation.d.ts +7 -3
  490. package/dist/types/mcp-server.d.ts +5 -0
  491. package/dist/types/settings.d.ts +3 -0
  492. package/dist/utils/api-error-message.d.ts +6 -2
  493. package/dist/utils/automation-catalog.cjs +2 -0
  494. package/dist/utils/automation-catalog.cjs.map +1 -0
  495. package/dist/utils/automation-catalog.d.ts +28 -0
  496. package/dist/utils/automation-catalog.js +5 -0
  497. package/dist/utils/automation-catalog.js.map +1 -0
  498. package/dist/utils/automation-timeout.d.ts +3 -2
  499. package/dist/utils/mcp-config.cjs +1 -1
  500. package/dist/utils/mcp-config.cjs.map +1 -1
  501. package/dist/utils/mcp-config.d.ts +8 -0
  502. package/dist/utils/mcp-config.js +25 -20
  503. package/dist/utils/mcp-config.js.map +1 -1
  504. package/dist/utils/mcp-installed-servers.cjs +1 -1
  505. package/dist/utils/mcp-installed-servers.cjs.map +1 -1
  506. package/dist/utils/mcp-installed-servers.js +6 -3
  507. package/dist/utils/mcp-installed-servers.js.map +1 -1
  508. package/dist/utils/responder-deployment.d.ts +5 -1
  509. package/dist/utils/transcript-export/index.cjs +5 -5
  510. package/dist/utils/transcript-export/index.js +12 -12
  511. package/package.json +3 -3
  512. package/scripts/check-sdk-version-sync.mjs +6 -6
  513. package/scripts/check-translation-completeness.cjs +1 -0
  514. package/scripts/dev-safe.mjs +17 -12
  515. package/scripts/dev-static.mjs +17 -0
  516. package/scripts/dev-with-automation.mjs +12 -14
  517. package/scripts/ingress.mjs +22 -0
  518. package/scripts/proxy-utils.mjs +157 -2
  519. package/scripts/runtime-services-info.mjs +6 -6
  520. package/scripts/static-build.mjs +0 -7
  521. package/scripts/static-server.mjs +10 -0
  522. package/build/assets/active-backend-context-BlZPzZNU.js +0 -1
  523. package/build/assets/agent-context-settings-CTaN-Iw9.js +0 -1
  524. package/build/assets/agent-profiles-settings-CR4VTqv_.js +0 -1
  525. package/build/assets/agent-server-conversation-service.api-Btmi4q6d.js +0 -41
  526. package/build/assets/agent-settings-KQs-occT.js +0 -1
  527. package/build/assets/api-key-entry-screen-BhR24gkM.js +0 -1
  528. package/build/assets/app-settings-Bs4sY8WP.js +0 -1
  529. package/build/assets/automation-BGP_I1RR.js +0 -1
  530. package/build/assets/automation-detail-CwDnJbYR.js +0 -2
  531. package/build/assets/automation-export-Bu-r-EzL.js +0 -2
  532. package/build/assets/automations-list-CYw7_6FR.js +0 -1
  533. package/build/assets/backend-form-modal-Ce-KRHOJ.js +0 -1
  534. package/build/assets/browser-BUDJnBg4.js +0 -6
  535. package/build/assets/check-BMOG005H.js +0 -1
  536. package/build/assets/chevron-down-CV1zZP_K.js +0 -1
  537. package/build/assets/circle-check-lvN_jFN5.js +0 -1
  538. package/build/assets/client-source-1v-kWLNU.js +0 -1
  539. package/build/assets/cloud-funnel-analytics-CasMM7EO.js +0 -1
  540. package/build/assets/command-menu-N_BriUy8.js +0 -1
  541. package/build/assets/condenser-settings-Czi8cKxV.js +0 -1
  542. package/build/assets/conversation-C25pc2dT.js +0 -1
  543. package/build/assets/conversation-CObLYSJd.js +0 -90
  544. package/build/assets/conversation-panel-C25pc2dT.js +0 -1
  545. package/build/assets/conversation-state-store-DTq4hFoP.js +0 -1
  546. package/build/assets/extensions-hub-BKftOQ-X.js +0 -1
  547. package/build/assets/extensions-navigation-DF24q1H1.js +0 -1
  548. package/build/assets/files-tab-SAiFCnS5.js +0 -1
  549. package/build/assets/git-provider-icon-BREx-yUX.js +0 -1
  550. package/build/assets/home-EPNFgzUh.js +0 -1
  551. package/build/assets/home-sN90Xcxp.js +0 -1
  552. package/build/assets/index-home-EPNFgzUh.js +0 -1
  553. package/build/assets/install-server-modal-BI8yUfmr.js +0 -1
  554. package/build/assets/llm-not-configured-banner-DTWzISnk.js +0 -27
  555. package/build/assets/llm-settings-BXk5_Pac.js +0 -1
  556. package/build/assets/llm-settings-C1vpgWam.js +0 -1
  557. package/build/assets/loader-circle-6zlEYCJw.js +0 -1
  558. package/build/assets/manage-backends-modal-DhflyGTf.js +0 -1
  559. package/build/assets/manifest-8082e879.js +0 -1
  560. package/build/assets/mcp-CxLPda-W.js +0 -9
  561. package/build/assets/messages-DINDkPNK.js +0 -40
  562. package/build/assets/onboarding-modal-DdvE6rzw.js +0 -1
  563. package/build/assets/organization-service.api-CT2OQlLz.js +0 -1
  564. package/build/assets/plugins-management-service-DVkoM3eA.js +0 -1
  565. package/build/assets/plus-vIbGD459.js +0 -1
  566. package/build/assets/profiles-service.api-CBafmAPO.js +0 -1
  567. package/build/assets/providers-9UzRB9mT.js +0 -1
  568. package/build/assets/proxy-C79PCMjo.js +0 -1
  569. package/build/assets/recommended-automations-launcher-BF2mtAKw.js +0 -58
  570. package/build/assets/root-B5JXKp1P.css +0 -1
  571. package/build/assets/root-Sj7W28yE.js +0 -2
  572. package/build/assets/root-layout-DbhKVoc7.js +0 -3
  573. package/build/assets/schema-field-CV6bFnoL.js +0 -1
  574. package/build/assets/search-sKuYKllf.js +0 -1
  575. package/build/assets/secrets-service-BjK-bPN2.js +0 -1
  576. package/build/assets/segmented-toggle-DbbD3Tve.js +0 -1
  577. package/build/assets/settings-Bj5Oo45A.js +0 -1
  578. package/build/assets/settings-input-BjW_zyTN.js +0 -1
  579. package/build/assets/settings-service.api-DryhKdSr.js +0 -1
  580. package/build/assets/shared-conversation-CnMxy7p_.js +0 -1
  581. package/build/assets/telemetry-cmCL3o6Z.js +0 -2
  582. package/build/assets/use-activate-agent-profile-DH33MvVj.js +0 -1
  583. package/build/assets/use-agent-profiles-Dmd_4H8q.js +0 -1
  584. package/build/assets/use-cloud-current-user-id-B6DP3s47.js +0 -1
  585. package/build/assets/use-is-authed-BsS4XwSL.js +0 -1
  586. package/build/assets/use-llm-profiles-BMQoc612.js +0 -1
  587. package/build/assets/use-onboarding-completion-B-2BTS-y.js +0 -1
  588. package/build/assets/use-plugins-marketplace-PBc_XNz_.js +0 -1
  589. package/build/assets/use-save-agent-profile-2Mk9ZX37.js +0 -1
  590. package/build/assets/use-settings-DBI44RnH.js +0 -1
  591. package/build/assets/use-settings-nav-items-Cva28C-c.js +0 -16
  592. package/build/assets/use-skills-RQsCtdzN.js +0 -1
  593. package/build/assets/use-tracking-CN1nIMnY.js +0 -1
  594. package/build/assets/utils-qjs_KuS4.js +0 -1
  595. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js +0 -1
  596. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js +0 -1
  597. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js +0 -1
  598. package/build/assets/x-EjvKGawc.js +0 -1
  599. /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f1hl7voa-BrmgjeOw.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~emdr2jt4-BrmgjeOw.js} +0 -0
@@ -579,6 +579,7 @@
579
579
  "CHAT_INTERFACE$MESSAGE_SEND_FAILED": "发送失败",
580
580
  "CHAT_INTERFACE$BRANCH_FROM_HERE": "从此处分支",
581
581
  "CHAT_INTERFACE$MESSAGE_RETRY": "重试",
582
+ "CHAT_INTERFACE$MESSAGE_DISMISS": "关闭",
582
583
  "CHAT_INTERFACE$AUGMENTED_PROMPT_FILES_TITLE": "已添加新文件",
583
584
  "CHAT_INTERFACE$DISCONNECTED": "已断开连接",
584
585
  "CHAT_INTERFACE$COMMANDS": "命令",
@@ -831,6 +832,8 @@
831
832
  "AUTOMATIONS$DETAIL$FAILED": "失败",
832
833
  "AUTOMATIONS$DETAIL$PENDING": "待处理",
833
834
  "AUTOMATIONS$DETAIL$RUNNING": "运行中",
835
+ "AUTOMATIONS$DETAIL$CANCELLED": "已取消",
836
+ "AUTOMATIONS$DETAIL$SKIPPED": "已跳过",
834
837
  "AUTOMATIONS$DETAIL$INACTIVE": "非活动",
835
838
  "AUTOMATIONS$DETAIL$LAST_RUN": "上次运行",
836
839
  "AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "加载更多",
@@ -893,6 +896,8 @@
893
896
  "MCP$INSTALLED_BADGE": "已安装",
894
897
  "MCP$TOGGLE_ADD_SERVER": "安装服务器",
895
898
  "MCP$TOGGLE_REMOVE_SERVER": "移除服务器",
899
+ "MCP$TOGGLE_ENABLE_SERVER": "启用服务器",
900
+ "MCP$TOGGLE_DISABLE_SERVER": "禁用服务器",
896
901
  "MCP$INSTALL_BUTTON": "安装",
897
902
  "MCP$VIEW_DOCS": "查看文档 →",
898
903
  "MCP$INSTALL_SUCCESS": "MCP 服务器已保存。",
@@ -1704,6 +1709,22 @@
1704
1709
  "BACKEND$MANAGE_EMPTY": "尚未添加额外后端。",
1705
1710
  "BACKEND$ADD_TITLE": "添加后端",
1706
1711
  "BACKEND$ADD_SUBTITLE": "将此应用连接到另一个 agent 服务器。添加后,您可以从上方菜单中切换不同的后端。",
1712
+ "BACKEND$CHOOSER_TITLE": "选择连接方式",
1713
+ "BACKEND$CHOOSER_DESCRIPTION": "连接到您控制的 agent-server,或使用托管的 OpenHands 体验。",
1714
+ "BACKEND$CLOUD_OPTION_DESCRIPTION": "使用托管的 OpenHands 体验。",
1715
+ "BACKEND$AGENT_SERVER_TITLE": "Agent 服务器",
1716
+ "BACKEND$AGENT_SERVER_OPTION_DESCRIPTION": "连接到本地或远程 agent-server。",
1717
+ "BACKEND$AGENT_SERVER_DESCRIPTION": "连接到本地或另一台计算机上运行的 agent-server。",
1718
+ "BACKEND$AGENT_SERVER_LOCATION": "Agent 服务器位置",
1719
+ "BACKEND$BEFORE_CONNECT_TITLE": "连接之前",
1720
+ "BACKEND$LOCAL_SETUP_DESCRIPTION": "在与此前端不同的端口上运行仅后端实例,然后在下方输入该主机。例如,使用以下命令启动:",
1721
+ "BACKEND$LOCAL_SETUP_DOCS": "阅读本地后端设置指南",
1722
+ "BACKEND$REMOTE_SETUP_TITLE": "推荐设置",
1723
+ "BACKEND$REMOTE_SETUP_DESCRIPTION": "使用 --public 运行远程后端,设置一个强 LOCAL_BACKEND_API_KEY,并通过 SSH 隧道、ngrok 或 TLS 反向代理将其公开。",
1724
+ "BACKEND$REMOTE_CONNECTION_TITLE": "连接详情",
1725
+ "BACKEND$REMOTE_CONNECTION_DESCRIPTION": "对于 SSH 隧道,请使用 http://localhost:8000;对于 ngrok 设置,请使用您的 ngrok 域名;或者使用 HTTPS 反向代理 URL。",
1726
+ "BACKEND$REMOTE_SETUP_DOCS": "阅读远程后端设置指南",
1727
+ "BACKEND$DEPLOYMENT_OPTIONS": "比较云端、自托管和企业版部署选项",
1707
1728
  "BACKEND$NAME_LABEL": "主机名",
1708
1729
  "BACKEND$HOST_LABEL": "主机",
1709
1730
  "BACKEND$HOST_HELPER": "Agent Server 的 URL",
@@ -1735,7 +1756,7 @@
1735
1756
  "BACKEND$INVALID_API_KEY": "API 密钥被拒绝",
1736
1757
  "BACKEND$PERSONAL_WORKSPACE": "个人工作区",
1737
1758
  "BACKEND$SWITCHING_TO": "正在切换到 {{environment}}",
1738
- "BACKEND$LOGIN_WITH_OPENHANDS": "使用 OpenHands Cloud 登录",
1759
+ "BACKEND$LOGIN_WITH_OPENHANDS": "连接到 OpenHands",
1739
1760
  "BACKEND$LOG_BACK_IN": "重新登录",
1740
1761
  "BACKEND$LOGGED_OUT": "已退出登录",
1741
1762
  "BACKEND$LOGIN_CLOUD_HINT": "适用于 OpenHands Cloud 或您的自托管 OpenHands Cloud 部署。",
@@ -2076,5 +2097,21 @@
2076
2097
  "SETTINGS$APP_UPDATE_HOW_TO_UPDATE": "如何更新",
2077
2098
  "SETTINGS$APP_UPDATE_RUN_COMMANDS": "运行以下任一命令:",
2078
2099
  "SETTINGS$APP_UPDATE_OR": "或",
2079
- "SETTINGS$APP_UPDATE_RELEASE_NOTES": "查看发行说明"
2100
+ "SETTINGS$APP_UPDATE_RELEASE_NOTES": "查看发行说明",
2101
+ "BUTTON$CONTINUE": "继续",
2102
+ "SETUP$PREREQUISITES_TITLE": "开始之前",
2103
+ "SETUP$MANAGE_INTEGRATIONS": "管理集成",
2104
+ "SETUP$UNAVAILABLE_TITLE": "不可用",
2105
+ "SETUP$SUBMIT_FAILED": "出现问题。未创建任何内容。",
2106
+ "SETUP$VALIDATION_REQUIRED": "此字段为必填项。",
2107
+ "SETUP$VALIDATION_MIN_LENGTH": "至少需要 {{length}} 个字符。",
2108
+ "SETUP$VALIDATION_MAX_LENGTH": "最多 {{length}} 个字符。",
2109
+ "SETUP$VALIDATION_INVALID_OPTION": "请从可用选项中选择。",
2110
+ "SETUP$VALIDATION_UNSAFE_VALUE": "不允许使用引号和反斜杠。",
2111
+ "SETUP$REVIEW_TITLE": "确认",
2112
+ "SETUP$CONFIRM": "确认并创建",
2113
+ "SETUP$FALLBACK_CONVERSATION": "在对话中设置",
2114
+ "SETUP$EMPTY_VALUE": "未设置",
2115
+ "SETUP$UNSUPPORTED_MESSAGE": "此部署不支持该自动化所需的全部功能。",
2116
+ "SETUP$REPOSITORY_PLACEHOLDER": "owner/repo"
2080
2117
  }
@@ -579,6 +579,7 @@
579
579
  "CHAT_INTERFACE$MESSAGE_SEND_FAILED": "傳送失敗",
580
580
  "CHAT_INTERFACE$BRANCH_FROM_HERE": "從此處分支",
581
581
  "CHAT_INTERFACE$MESSAGE_RETRY": "重試",
582
+ "CHAT_INTERFACE$MESSAGE_DISMISS": "關閉",
582
583
  "CHAT_INTERFACE$AUGMENTED_PROMPT_FILES_TITLE": "已新增檔案",
583
584
  "CHAT_INTERFACE$DISCONNECTED": "已斷開連接",
584
585
  "CHAT_INTERFACE$COMMANDS": "命令",
@@ -831,6 +832,8 @@
831
832
  "AUTOMATIONS$DETAIL$FAILED": "失敗",
832
833
  "AUTOMATIONS$DETAIL$PENDING": "待處理",
833
834
  "AUTOMATIONS$DETAIL$RUNNING": "執行中",
835
+ "AUTOMATIONS$DETAIL$CANCELLED": "已取消",
836
+ "AUTOMATIONS$DETAIL$SKIPPED": "已略過",
834
837
  "AUTOMATIONS$DETAIL$INACTIVE": "非作用中",
835
838
  "AUTOMATIONS$DETAIL$LAST_RUN": "上次執行",
836
839
  "AUTOMATIONS$DETAIL$LOAD_MORE_RUNS": "載入更多",
@@ -893,6 +896,8 @@
893
896
  "MCP$INSTALLED_BADGE": "已安裝",
894
897
  "MCP$TOGGLE_ADD_SERVER": "安裝伺服器",
895
898
  "MCP$TOGGLE_REMOVE_SERVER": "移除伺服器",
899
+ "MCP$TOGGLE_ENABLE_SERVER": "啟用伺服器",
900
+ "MCP$TOGGLE_DISABLE_SERVER": "停用伺服器",
896
901
  "MCP$INSTALL_BUTTON": "安裝",
897
902
  "MCP$VIEW_DOCS": "檢視文件 →",
898
903
  "MCP$INSTALL_SUCCESS": "MCP 伺服器已儲存。",
@@ -1704,6 +1709,22 @@
1704
1709
  "BACKEND$MANAGE_EMPTY": "尚未新增其他後端。",
1705
1710
  "BACKEND$ADD_TITLE": "新增後端",
1706
1711
  "BACKEND$ADD_SUBTITLE": "將此應用程式連線至另一個 agent 伺服器。新增後,您可以從上方選單中切換不同的後端。",
1712
+ "BACKEND$CHOOSER_TITLE": "選擇連線方式",
1713
+ "BACKEND$CHOOSER_DESCRIPTION": "連線至您控制的 agent-server,或使用託管的 OpenHands 體驗。",
1714
+ "BACKEND$CLOUD_OPTION_DESCRIPTION": "使用託管的 OpenHands 體驗。",
1715
+ "BACKEND$AGENT_SERVER_TITLE": "Agent 伺服器",
1716
+ "BACKEND$AGENT_SERVER_OPTION_DESCRIPTION": "連線至本機或遠端 agent-server。",
1717
+ "BACKEND$AGENT_SERVER_DESCRIPTION": "連線至本機或另一台電腦上執行的 agent-server。",
1718
+ "BACKEND$AGENT_SERVER_LOCATION": "Agent 伺服器位置",
1719
+ "BACKEND$BEFORE_CONNECT_TITLE": "連線之前",
1720
+ "BACKEND$LOCAL_SETUP_DESCRIPTION": "在與此前端不同的連接埠上執行僅後端執行個體,然後在下方輸入該主機。例如,使用以下命令啟動:",
1721
+ "BACKEND$LOCAL_SETUP_DOCS": "閱讀本機後端設定指南",
1722
+ "BACKEND$REMOTE_SETUP_TITLE": "建議設定",
1723
+ "BACKEND$REMOTE_SETUP_DESCRIPTION": "使用 --public 執行遠端後端,設定強式 LOCAL_BACKEND_API_KEY,並透過 SSH 通道、ngrok 或 TLS 反向代理公開。",
1724
+ "BACKEND$REMOTE_CONNECTION_TITLE": "連線詳細資料",
1725
+ "BACKEND$REMOTE_CONNECTION_DESCRIPTION": "SSH 通道請使用 http://localhost:8000;ngrok 設定請使用您的 ngrok 網域;或使用 HTTPS 反向代理 URL。",
1726
+ "BACKEND$REMOTE_SETUP_DOCS": "閱讀遠端後端設定指南",
1727
+ "BACKEND$DEPLOYMENT_OPTIONS": "比較雲端、自託管和企業版部署選項",
1707
1728
  "BACKEND$NAME_LABEL": "主機名稱",
1708
1729
  "BACKEND$HOST_LABEL": "主機",
1709
1730
  "BACKEND$HOST_HELPER": "Agent Server 的 URL",
@@ -1735,7 +1756,7 @@
1735
1756
  "BACKEND$INVALID_API_KEY": "API 金鑰已被拒絕",
1736
1757
  "BACKEND$PERSONAL_WORKSPACE": "個人工作區",
1737
1758
  "BACKEND$SWITCHING_TO": "正在切換到 {{environment}}",
1738
- "BACKEND$LOGIN_WITH_OPENHANDS": "使用 OpenHands Cloud 登入",
1759
+ "BACKEND$LOGIN_WITH_OPENHANDS": "連線至 OpenHands",
1739
1760
  "BACKEND$LOG_BACK_IN": "重新登入",
1740
1761
  "BACKEND$LOGGED_OUT": "已登出",
1741
1762
  "BACKEND$LOGIN_CLOUD_HINT": "適用於 OpenHands Cloud 或您的自託管 OpenHands Cloud 部署。",
@@ -2076,5 +2097,21 @@
2076
2097
  "SETTINGS$APP_UPDATE_HOW_TO_UPDATE": "如何更新",
2077
2098
  "SETTINGS$APP_UPDATE_RUN_COMMANDS": "執行以下任一命令:",
2078
2099
  "SETTINGS$APP_UPDATE_OR": "或",
2079
- "SETTINGS$APP_UPDATE_RELEASE_NOTES": "檢視版本資訊"
2100
+ "SETTINGS$APP_UPDATE_RELEASE_NOTES": "檢視版本資訊",
2101
+ "BUTTON$CONTINUE": "繼續",
2102
+ "SETUP$PREREQUISITES_TITLE": "開始之前",
2103
+ "SETUP$MANAGE_INTEGRATIONS": "管理整合",
2104
+ "SETUP$UNAVAILABLE_TITLE": "無法使用",
2105
+ "SETUP$SUBMIT_FAILED": "發生問題。未建立任何項目。",
2106
+ "SETUP$VALIDATION_REQUIRED": "此欄位為必填。",
2107
+ "SETUP$VALIDATION_MIN_LENGTH": "至少需要 {{length}} 個字元。",
2108
+ "SETUP$VALIDATION_MAX_LENGTH": "最多 {{length}} 個字元。",
2109
+ "SETUP$VALIDATION_INVALID_OPTION": "請從可用選項中選擇。",
2110
+ "SETUP$VALIDATION_UNSAFE_VALUE": "不允許使用引號和反斜線。",
2111
+ "SETUP$REVIEW_TITLE": "確認",
2112
+ "SETUP$CONFIRM": "確認並建立",
2113
+ "SETUP$FALLBACK_CONVERSATION": "在對話中設定",
2114
+ "SETUP$EMPTY_VALUE": "未設定",
2115
+ "SETUP$UNSUPPORTED_MESSAGE": "此部署不支援此自動化所需的全部功能。",
2116
+ "SETUP$REPOSITORY_PLACEHOLDER": "owner/repo"
2080
2117
  }
@@ -0,0 +1,2 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");const e=require("../node_modules/@openhands/extensions/automations/index.cjs"),t=require("./interface-validation.cjs"),n=require("./manifest-sources.cjs");var r={list:`/automations`,setup:`/automations/new/:automationId`,detail:`/automations/:automationId`},i={list:`/v1`,detail:`/v1/{id}`,dispatch:`/v1/{id}/dispatch`,runs:`/v1/{id}/runs`,tarball:`/v1/{id}/tarball`,health:`/health`,capabilities:`/v1/capabilities`,validate:`/v1/validate`,createPrompt:`/v1/preset/prompt`,createPlugin:`/v1/preset/plugin`},a={fileKind:`automation`,fileVersion:1,filenameSuffix:`.automation.json`,importDefaults:{repoProvider:`github`,placeholderEventSource:`agent-canvas-import`}};function o(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function s(){return new Set(e.default.flatMap(e=>o(e)&&typeof e.id==`string`?[e.id]:[]))}function c(e){if(e===void 0)return null;let n=t.validateInterfaceManifest(e,{catalogIds:s(),mountedRoutes:r});return n.valid?e:(console.warn(`Rejected the automation interface manifest:`,n.errors.join(`; `)),null)}var l=c(n.AUTOMATION_INTERFACE_CANDIDATE);function u(){return(l?.routes??r).list}function d(e){return(l?.endpoints??i)[e]}function f(e,t){return d(e).replace(`{id}`,encodeURIComponent(t))}var p={sidebarLabel:null,commandMenuTitle:null,commandMenuDescription:null,commandMenuKeywords:null,listTitle:null,listSubtitle:null,detailBackLabel:null,editTitle:null};function m(){return l?{sidebarLabel:l.navigation.sidebar.label,commandMenuTitle:l.navigation.commandMenu.title,commandMenuDescription:l.navigation.commandMenu.description,commandMenuKeywords:l.navigation.commandMenu.keywords,listTitle:l.pages.list.title,listSubtitle:l.pages.list.subtitle,detailBackLabel:l.pages.detail.backLabel,editTitle:l.pages.edit.title}:p}function h(){return l?.importExport??a}exports.automationListPath=u,exports.getAutomationEndpoint=d,exports.getAutomationIdEndpoint=f,exports.getImportExportSpec=h,exports.getInterfaceCopy=m;
2
+ //# sourceMappingURL=automation-interface.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation-interface.cjs","names":[],"sources":["../../src/manifests/automation-interface.ts"],"sourcesContent":["/**\n * The automation interface seam.\n *\n * Every automation-specific datum the host's surfaces render — routes,\n * navigation and page copy, the settable attributes, the import/export\n * envelope, endpoint paths, the featured and responder id lists — is served\n * from here.\n * The published interface manifest supplies it when the pinned\n * `@openhands/extensions` ships one and it passes admission; otherwise the\n * host's own defaults do, which reproduce today's behavior exactly. Copy\n * defaults are null, meaning \"render the host's own translation\".\n */\n\nimport { AUTOMATION_CATALOG } from \"@openhands/extensions/automations\";\nimport { AUTOMATION_TIMEOUT_MAX_SECONDS } from \"#/utils/automation-timeout\";\nimport { validateInterfaceManifest } from \"./interface-validation\";\nimport { AUTOMATION_INTERFACE_CANDIDATE } from \"./manifest-sources\";\nimport type {\n AutomationAttributeName,\n InterfaceEndpointName,\n InterfaceImportExport,\n InterfaceManifest,\n InterfaceRoutes,\n} from \"./types\";\n\n/** The routes this host has registrations for, in `src/routes.ts`. */\nconst MOUNTED_ROUTES: InterfaceRoutes = {\n list: \"/automations\",\n setup: \"/automations/new/:automationId\",\n detail: \"/automations/:automationId\",\n};\n\nconst DEFAULT_ENDPOINTS: InterfaceManifest[\"endpoints\"] = {\n list: \"/v1\",\n detail: \"/v1/{id}\",\n dispatch: \"/v1/{id}/dispatch\",\n runs: \"/v1/{id}/runs\",\n tarball: \"/v1/{id}/tarball\",\n health: \"/health\",\n capabilities: \"/v1/capabilities\",\n validate: \"/v1/validate\",\n createPrompt: \"/v1/preset/prompt\",\n createPlugin: \"/v1/preset/plugin\",\n};\n\nconst DEFAULT_IMPORT_EXPORT: InterfaceImportExport = {\n fileKind: \"automation\",\n fileVersion: 1,\n filenameSuffix: \".automation.json\",\n importDefaults: {\n repoProvider: \"github\",\n placeholderEventSource: \"agent-canvas-import\",\n },\n};\n\nconst DEFAULT_DOCS_URL =\n \"https://docs.openhands.dev/openhands/usage/automations/overview\";\n\n/**\n * Proven automations featured above the Beta group. NOT derived from\n * popularityRank (slack-standup-digest@94 outranks slack-channel-monitor@92\n * yet is Beta).\n */\nconst DEFAULT_FEATURED_AUTOMATION_IDS: readonly string[] = [\n \"github-pr-reviewer\",\n \"github-repo-monitor\",\n \"slack-channel-monitor\",\n];\n\n/**\n * Integrations whose automations are treated as event responders that poll\n * continuously, and so get the deployment-choice dialog.\n */\nconst DEFAULT_RESPONDER_INTEGRATION_IDS: readonly string[] = [\n \"github\",\n \"slack\",\n];\n\nexport interface AttributeSpec {\n present: boolean;\n /** Null means \"render the host's own translation\". */\n label: string | null;\n help: string | null;\n required: boolean;\n min: number | null;\n max: number | null;\n}\n\nconst ABSENT_ATTRIBUTE: AttributeSpec = {\n present: false,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n};\n\n/** Today's edit dialog, restated as specs so absence of a manifest changes nothing. */\nconst DEFAULT_ATTRIBUTES: Record<AutomationAttributeName, AttributeSpec> = {\n name: {\n present: true,\n label: null,\n help: null,\n required: true,\n min: null,\n max: null,\n },\n prompt: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n },\n model: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n },\n timeout: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: 1,\n max: AUTOMATION_TIMEOUT_MAX_SECONDS,\n },\n schedule: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n },\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction getCatalogIds(): ReadonlySet<string> {\n return new Set(\n (AUTOMATION_CATALOG as readonly unknown[]).flatMap((entry) =>\n isRecord(entry) && typeof entry.id === \"string\" ? [entry.id] : [],\n ),\n );\n}\n\nfunction admitInterfaceManifest(candidate: unknown): InterfaceManifest | null {\n if (candidate === undefined) return null;\n\n const result = validateInterfaceManifest(candidate, {\n catalogIds: getCatalogIds(),\n mountedRoutes: MOUNTED_ROUTES,\n });\n if (!result.valid) {\n // Mirrors the setup registry: a rejected manifest is skipped loudly, and\n // the host's defaults stand.\n console.warn(\n \"Rejected the automation interface manifest:\",\n result.errors.join(\"; \"),\n );\n return null;\n }\n return candidate as InterfaceManifest;\n}\n\nconst ADMITTED = admitInterfaceManifest(AUTOMATION_INTERFACE_CANDIDATE);\n\nfunction substituteRouteParam(pattern: string, id: string): string {\n return pattern.replace(\":automationId\", encodeURIComponent(id));\n}\n\nexport function automationListPath(): string {\n return (ADMITTED?.routes ?? MOUNTED_ROUTES).list;\n}\n\nexport function automationSetupPath(id: string): string {\n return substituteRouteParam((ADMITTED?.routes ?? MOUNTED_ROUTES).setup, id);\n}\n\nexport function automationDetailPath(id: string): string {\n return substituteRouteParam((ADMITTED?.routes ?? MOUNTED_ROUTES).detail, id);\n}\n\nexport function getAutomationEndpoint(name: InterfaceEndpointName): string {\n return (ADMITTED?.endpoints ?? DEFAULT_ENDPOINTS)[name];\n}\n\n/** An id-parameterized endpoint with `{id}` substituted, encoded. */\nexport function getAutomationIdEndpoint(\n name: \"detail\" | \"dispatch\" | \"runs\" | \"tarball\",\n id: string,\n): string {\n return getAutomationEndpoint(name).replace(\"{id}\", encodeURIComponent(id));\n}\n\nexport interface InterfaceCopy {\n sidebarLabel: string | null;\n commandMenuTitle: string | null;\n commandMenuDescription: string | null;\n commandMenuKeywords: string | null;\n listTitle: string | null;\n listSubtitle: string | null;\n detailBackLabel: string | null;\n editTitle: string | null;\n}\n\nconst HOST_COPY: InterfaceCopy = {\n sidebarLabel: null,\n commandMenuTitle: null,\n commandMenuDescription: null,\n commandMenuKeywords: null,\n listTitle: null,\n listSubtitle: null,\n detailBackLabel: null,\n editTitle: null,\n};\n\nexport function getInterfaceCopy(): InterfaceCopy {\n if (!ADMITTED) return HOST_COPY;\n return {\n sidebarLabel: ADMITTED.navigation.sidebar.label,\n commandMenuTitle: ADMITTED.navigation.commandMenu.title,\n commandMenuDescription: ADMITTED.navigation.commandMenu.description,\n commandMenuKeywords: ADMITTED.navigation.commandMenu.keywords,\n listTitle: ADMITTED.pages.list.title,\n listSubtitle: ADMITTED.pages.list.subtitle,\n detailBackLabel: ADMITTED.pages.detail.backLabel,\n editTitle: ADMITTED.pages.edit.title,\n };\n}\n\nexport function getAttributeSpec(name: AutomationAttributeName): AttributeSpec {\n if (!ADMITTED) return DEFAULT_ATTRIBUTES[name];\n\n const attribute = ADMITTED.attributes[name];\n if (!attribute) return ABSENT_ATTRIBUTE;\n return {\n present: true,\n label: attribute.label,\n help: attribute.help ?? null,\n required: attribute.required,\n min: attribute.constraints?.min ?? null,\n max: attribute.constraints?.max ?? null,\n };\n}\n\nexport function getImportExportSpec(): InterfaceImportExport {\n return ADMITTED?.importExport ?? DEFAULT_IMPORT_EXPORT;\n}\n\nexport function getAutomationsDocsUrl(): string {\n return ADMITTED?.docsUrl ?? DEFAULT_DOCS_URL;\n}\n\nexport function getFeaturedAutomationIds(): readonly string[] {\n return ADMITTED?.featuredAutomationIds ?? DEFAULT_FEATURED_AUTOMATION_IDS;\n}\n\nexport function getResponderIntegrationIds(): readonly string[] {\n return ADMITTED?.responderIntegrationIds ?? DEFAULT_RESPONDER_INTEGRATION_IDS;\n}\n"],"mappings":"wMA0BA,IAAM,EAAkC,CACtC,KAAM,eACN,MAAO,iCACP,OAAQ,4BACV,EAEM,EAAoD,CACxD,KAAM,MACN,OAAQ,WACR,SAAU,oBACV,KAAM,gBACN,QAAS,mBACT,OAAQ,UACR,aAAc,mBACd,SAAU,eACV,aAAc,oBACd,aAAc,mBAChB,EAEM,EAA+C,CACnD,SAAU,aACV,YAAa,EACb,eAAgB,mBAChB,eAAgB,CACd,aAAc,SACd,uBAAwB,qBAC1B,CACF,EAwFA,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,SAAS,GAAqC,CAC5C,OAAO,IAAI,IACR,EAAA,QAA0C,QAAS,GAClD,EAAS,CAAK,GAAK,OAAO,EAAM,IAAO,SAAW,CAAC,EAAM,EAAE,EAAI,CAAC,CAClE,CACF,CACF,CAEA,SAAS,EAAuB,EAA8C,CAC5E,GAAI,IAAc,IAAA,GAAW,OAAO,KAEpC,IAAM,EAAS,EAAA,0BAA0B,EAAW,CAClD,WAAY,EAAc,EAC1B,cAAe,CACjB,CAAC,EAUD,OATK,EAAO,MASL,GANL,QAAQ,KACN,8CACA,EAAO,OAAO,KAAK,IAAI,CACzB,EACO,KAGX,CAEA,IAAM,EAAW,EAAuB,EAAA,8BAA8B,EAMtE,SAAgB,GAA6B,CAC3C,OAAQ,GAAU,QAAU,GAAgB,IAC9C,CAUA,SAAgB,EAAsB,EAAqC,CACzE,OAAQ,GAAU,WAAa,GAAmB,EACpD,CAGA,SAAgB,EACd,EACA,EACQ,CACR,OAAO,EAAsB,CAAI,EAAE,QAAQ,OAAQ,mBAAmB,CAAE,CAAC,CAC3E,CAaA,IAAM,EAA2B,CAC/B,aAAc,KACd,iBAAkB,KAClB,uBAAwB,KACxB,oBAAqB,KACrB,UAAW,KACX,aAAc,KACd,gBAAiB,KACjB,UAAW,IACb,EAEA,SAAgB,GAAkC,CAEhD,OADK,EACE,CACL,aAAc,EAAS,WAAW,QAAQ,MAC1C,iBAAkB,EAAS,WAAW,YAAY,MAClD,uBAAwB,EAAS,WAAW,YAAY,YACxD,oBAAqB,EAAS,WAAW,YAAY,SACrD,UAAW,EAAS,MAAM,KAAK,MAC/B,aAAc,EAAS,MAAM,KAAK,SAClC,gBAAiB,EAAS,MAAM,OAAO,UACvC,UAAW,EAAS,MAAM,KAAK,KACjC,EAVsB,CAWxB,CAiBA,SAAgB,GAA6C,CAC3D,OAAO,GAAU,cAAgB,CACnC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The automation interface seam.
3
+ *
4
+ * Every automation-specific datum the host's surfaces render — routes,
5
+ * navigation and page copy, the settable attributes, the import/export
6
+ * envelope, endpoint paths, the featured and responder id lists — is served
7
+ * from here.
8
+ * The published interface manifest supplies it when the pinned
9
+ * `@openhands/extensions` ships one and it passes admission; otherwise the
10
+ * host's own defaults do, which reproduce today's behavior exactly. Copy
11
+ * defaults are null, meaning "render the host's own translation".
12
+ */
13
+ import type { AutomationAttributeName, InterfaceEndpointName, InterfaceImportExport } from "./types";
14
+ export interface AttributeSpec {
15
+ present: boolean;
16
+ /** Null means "render the host's own translation". */
17
+ label: string | null;
18
+ help: string | null;
19
+ required: boolean;
20
+ min: number | null;
21
+ max: number | null;
22
+ }
23
+ export declare function automationListPath(): string;
24
+ export declare function automationSetupPath(id: string): string;
25
+ export declare function automationDetailPath(id: string): string;
26
+ export declare function getAutomationEndpoint(name: InterfaceEndpointName): string;
27
+ /** An id-parameterized endpoint with `{id}` substituted, encoded. */
28
+ export declare function getAutomationIdEndpoint(name: "detail" | "dispatch" | "runs" | "tarball", id: string): string;
29
+ export interface InterfaceCopy {
30
+ sidebarLabel: string | null;
31
+ commandMenuTitle: string | null;
32
+ commandMenuDescription: string | null;
33
+ commandMenuKeywords: string | null;
34
+ listTitle: string | null;
35
+ listSubtitle: string | null;
36
+ detailBackLabel: string | null;
37
+ editTitle: string | null;
38
+ }
39
+ export declare function getInterfaceCopy(): InterfaceCopy;
40
+ export declare function getAttributeSpec(name: AutomationAttributeName): AttributeSpec;
41
+ export declare function getImportExportSpec(): InterfaceImportExport;
42
+ export declare function getAutomationsDocsUrl(): string;
43
+ export declare function getFeaturedAutomationIds(): readonly string[];
44
+ export declare function getResponderIntegrationIds(): readonly string[];
@@ -0,0 +1,81 @@
1
+ import e from "../node_modules/@openhands/extensions/automations/index.js";
2
+ import { validateInterfaceManifest as t } from "./interface-validation.js";
3
+ import { AUTOMATION_INTERFACE_CANDIDATE as n } from "./manifest-sources.js";
4
+ //#region src/manifests/automation-interface.ts
5
+ var r = {
6
+ list: "/automations",
7
+ setup: "/automations/new/:automationId",
8
+ detail: "/automations/:automationId"
9
+ }, i = {
10
+ list: "/v1",
11
+ detail: "/v1/{id}",
12
+ dispatch: "/v1/{id}/dispatch",
13
+ runs: "/v1/{id}/runs",
14
+ tarball: "/v1/{id}/tarball",
15
+ health: "/health",
16
+ capabilities: "/v1/capabilities",
17
+ validate: "/v1/validate",
18
+ createPrompt: "/v1/preset/prompt",
19
+ createPlugin: "/v1/preset/plugin"
20
+ }, a = {
21
+ fileKind: "automation",
22
+ fileVersion: 1,
23
+ filenameSuffix: ".automation.json",
24
+ importDefaults: {
25
+ repoProvider: "github",
26
+ placeholderEventSource: "agent-canvas-import"
27
+ }
28
+ };
29
+ function o(e) {
30
+ return typeof e == "object" && !!e && !Array.isArray(e);
31
+ }
32
+ function s() {
33
+ return new Set(e.flatMap((e) => o(e) && typeof e.id == "string" ? [e.id] : []));
34
+ }
35
+ function c(e) {
36
+ if (e === void 0) return null;
37
+ let n = t(e, {
38
+ catalogIds: s(),
39
+ mountedRoutes: r
40
+ });
41
+ return n.valid ? e : (console.warn("Rejected the automation interface manifest:", n.errors.join("; ")), null);
42
+ }
43
+ var l = c(n);
44
+ function u() {
45
+ return (l?.routes ?? r).list;
46
+ }
47
+ function d(e) {
48
+ return (l?.endpoints ?? i)[e];
49
+ }
50
+ function f(e, t) {
51
+ return d(e).replace("{id}", encodeURIComponent(t));
52
+ }
53
+ var p = {
54
+ sidebarLabel: null,
55
+ commandMenuTitle: null,
56
+ commandMenuDescription: null,
57
+ commandMenuKeywords: null,
58
+ listTitle: null,
59
+ listSubtitle: null,
60
+ detailBackLabel: null,
61
+ editTitle: null
62
+ };
63
+ function m() {
64
+ return l ? {
65
+ sidebarLabel: l.navigation.sidebar.label,
66
+ commandMenuTitle: l.navigation.commandMenu.title,
67
+ commandMenuDescription: l.navigation.commandMenu.description,
68
+ commandMenuKeywords: l.navigation.commandMenu.keywords,
69
+ listTitle: l.pages.list.title,
70
+ listSubtitle: l.pages.list.subtitle,
71
+ detailBackLabel: l.pages.detail.backLabel,
72
+ editTitle: l.pages.edit.title
73
+ } : p;
74
+ }
75
+ function h() {
76
+ return l?.importExport ?? a;
77
+ }
78
+ //#endregion
79
+ export { u as automationListPath, d as getAutomationEndpoint, f as getAutomationIdEndpoint, h as getImportExportSpec, m as getInterfaceCopy };
80
+
81
+ //# sourceMappingURL=automation-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation-interface.js","names":[],"sources":["../../src/manifests/automation-interface.ts"],"sourcesContent":["/**\n * The automation interface seam.\n *\n * Every automation-specific datum the host's surfaces render — routes,\n * navigation and page copy, the settable attributes, the import/export\n * envelope, endpoint paths, the featured and responder id lists — is served\n * from here.\n * The published interface manifest supplies it when the pinned\n * `@openhands/extensions` ships one and it passes admission; otherwise the\n * host's own defaults do, which reproduce today's behavior exactly. Copy\n * defaults are null, meaning \"render the host's own translation\".\n */\n\nimport { AUTOMATION_CATALOG } from \"@openhands/extensions/automations\";\nimport { AUTOMATION_TIMEOUT_MAX_SECONDS } from \"#/utils/automation-timeout\";\nimport { validateInterfaceManifest } from \"./interface-validation\";\nimport { AUTOMATION_INTERFACE_CANDIDATE } from \"./manifest-sources\";\nimport type {\n AutomationAttributeName,\n InterfaceEndpointName,\n InterfaceImportExport,\n InterfaceManifest,\n InterfaceRoutes,\n} from \"./types\";\n\n/** The routes this host has registrations for, in `src/routes.ts`. */\nconst MOUNTED_ROUTES: InterfaceRoutes = {\n list: \"/automations\",\n setup: \"/automations/new/:automationId\",\n detail: \"/automations/:automationId\",\n};\n\nconst DEFAULT_ENDPOINTS: InterfaceManifest[\"endpoints\"] = {\n list: \"/v1\",\n detail: \"/v1/{id}\",\n dispatch: \"/v1/{id}/dispatch\",\n runs: \"/v1/{id}/runs\",\n tarball: \"/v1/{id}/tarball\",\n health: \"/health\",\n capabilities: \"/v1/capabilities\",\n validate: \"/v1/validate\",\n createPrompt: \"/v1/preset/prompt\",\n createPlugin: \"/v1/preset/plugin\",\n};\n\nconst DEFAULT_IMPORT_EXPORT: InterfaceImportExport = {\n fileKind: \"automation\",\n fileVersion: 1,\n filenameSuffix: \".automation.json\",\n importDefaults: {\n repoProvider: \"github\",\n placeholderEventSource: \"agent-canvas-import\",\n },\n};\n\nconst DEFAULT_DOCS_URL =\n \"https://docs.openhands.dev/openhands/usage/automations/overview\";\n\n/**\n * Proven automations featured above the Beta group. NOT derived from\n * popularityRank (slack-standup-digest@94 outranks slack-channel-monitor@92\n * yet is Beta).\n */\nconst DEFAULT_FEATURED_AUTOMATION_IDS: readonly string[] = [\n \"github-pr-reviewer\",\n \"github-repo-monitor\",\n \"slack-channel-monitor\",\n];\n\n/**\n * Integrations whose automations are treated as event responders that poll\n * continuously, and so get the deployment-choice dialog.\n */\nconst DEFAULT_RESPONDER_INTEGRATION_IDS: readonly string[] = [\n \"github\",\n \"slack\",\n];\n\nexport interface AttributeSpec {\n present: boolean;\n /** Null means \"render the host's own translation\". */\n label: string | null;\n help: string | null;\n required: boolean;\n min: number | null;\n max: number | null;\n}\n\nconst ABSENT_ATTRIBUTE: AttributeSpec = {\n present: false,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n};\n\n/** Today's edit dialog, restated as specs so absence of a manifest changes nothing. */\nconst DEFAULT_ATTRIBUTES: Record<AutomationAttributeName, AttributeSpec> = {\n name: {\n present: true,\n label: null,\n help: null,\n required: true,\n min: null,\n max: null,\n },\n prompt: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n },\n model: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n },\n timeout: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: 1,\n max: AUTOMATION_TIMEOUT_MAX_SECONDS,\n },\n schedule: {\n present: true,\n label: null,\n help: null,\n required: false,\n min: null,\n max: null,\n },\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction getCatalogIds(): ReadonlySet<string> {\n return new Set(\n (AUTOMATION_CATALOG as readonly unknown[]).flatMap((entry) =>\n isRecord(entry) && typeof entry.id === \"string\" ? [entry.id] : [],\n ),\n );\n}\n\nfunction admitInterfaceManifest(candidate: unknown): InterfaceManifest | null {\n if (candidate === undefined) return null;\n\n const result = validateInterfaceManifest(candidate, {\n catalogIds: getCatalogIds(),\n mountedRoutes: MOUNTED_ROUTES,\n });\n if (!result.valid) {\n // Mirrors the setup registry: a rejected manifest is skipped loudly, and\n // the host's defaults stand.\n console.warn(\n \"Rejected the automation interface manifest:\",\n result.errors.join(\"; \"),\n );\n return null;\n }\n return candidate as InterfaceManifest;\n}\n\nconst ADMITTED = admitInterfaceManifest(AUTOMATION_INTERFACE_CANDIDATE);\n\nfunction substituteRouteParam(pattern: string, id: string): string {\n return pattern.replace(\":automationId\", encodeURIComponent(id));\n}\n\nexport function automationListPath(): string {\n return (ADMITTED?.routes ?? MOUNTED_ROUTES).list;\n}\n\nexport function automationSetupPath(id: string): string {\n return substituteRouteParam((ADMITTED?.routes ?? MOUNTED_ROUTES).setup, id);\n}\n\nexport function automationDetailPath(id: string): string {\n return substituteRouteParam((ADMITTED?.routes ?? MOUNTED_ROUTES).detail, id);\n}\n\nexport function getAutomationEndpoint(name: InterfaceEndpointName): string {\n return (ADMITTED?.endpoints ?? DEFAULT_ENDPOINTS)[name];\n}\n\n/** An id-parameterized endpoint with `{id}` substituted, encoded. */\nexport function getAutomationIdEndpoint(\n name: \"detail\" | \"dispatch\" | \"runs\" | \"tarball\",\n id: string,\n): string {\n return getAutomationEndpoint(name).replace(\"{id}\", encodeURIComponent(id));\n}\n\nexport interface InterfaceCopy {\n sidebarLabel: string | null;\n commandMenuTitle: string | null;\n commandMenuDescription: string | null;\n commandMenuKeywords: string | null;\n listTitle: string | null;\n listSubtitle: string | null;\n detailBackLabel: string | null;\n editTitle: string | null;\n}\n\nconst HOST_COPY: InterfaceCopy = {\n sidebarLabel: null,\n commandMenuTitle: null,\n commandMenuDescription: null,\n commandMenuKeywords: null,\n listTitle: null,\n listSubtitle: null,\n detailBackLabel: null,\n editTitle: null,\n};\n\nexport function getInterfaceCopy(): InterfaceCopy {\n if (!ADMITTED) return HOST_COPY;\n return {\n sidebarLabel: ADMITTED.navigation.sidebar.label,\n commandMenuTitle: ADMITTED.navigation.commandMenu.title,\n commandMenuDescription: ADMITTED.navigation.commandMenu.description,\n commandMenuKeywords: ADMITTED.navigation.commandMenu.keywords,\n listTitle: ADMITTED.pages.list.title,\n listSubtitle: ADMITTED.pages.list.subtitle,\n detailBackLabel: ADMITTED.pages.detail.backLabel,\n editTitle: ADMITTED.pages.edit.title,\n };\n}\n\nexport function getAttributeSpec(name: AutomationAttributeName): AttributeSpec {\n if (!ADMITTED) return DEFAULT_ATTRIBUTES[name];\n\n const attribute = ADMITTED.attributes[name];\n if (!attribute) return ABSENT_ATTRIBUTE;\n return {\n present: true,\n label: attribute.label,\n help: attribute.help ?? null,\n required: attribute.required,\n min: attribute.constraints?.min ?? null,\n max: attribute.constraints?.max ?? null,\n };\n}\n\nexport function getImportExportSpec(): InterfaceImportExport {\n return ADMITTED?.importExport ?? DEFAULT_IMPORT_EXPORT;\n}\n\nexport function getAutomationsDocsUrl(): string {\n return ADMITTED?.docsUrl ?? DEFAULT_DOCS_URL;\n}\n\nexport function getFeaturedAutomationIds(): readonly string[] {\n return ADMITTED?.featuredAutomationIds ?? DEFAULT_FEATURED_AUTOMATION_IDS;\n}\n\nexport function getResponderIntegrationIds(): readonly string[] {\n return ADMITTED?.responderIntegrationIds ?? DEFAULT_RESPONDER_INTEGRATION_IDS;\n}\n"],"mappings":";;;;AA0BA,IAAM,IAAkC;CACtC,MAAM;CACN,OAAO;CACP,QAAQ;AACV,GAEM,IAAoD;CACxD,MAAM;CACN,QAAQ;CACR,UAAU;CACV,MAAM;CACN,SAAS;CACT,QAAQ;CACR,cAAc;CACd,UAAU;CACV,cAAc;CACd,cAAc;AAChB,GAEM,IAA+C;CACnD,UAAU;CACV,aAAa;CACb,gBAAgB;CAChB,gBAAgB;EACd,cAAc;EACd,wBAAwB;CAC1B;AACF;AAwFA,SAAS,EAAS,GAAkD;CAClE,OAAO,OAAO,KAAU,cAAY,KAAkB,CAAC,MAAM,QAAQ,CAAK;AAC5E;AAEA,SAAS,IAAqC;CAC5C,OAAO,IAAI,IACR,EAA0C,SAAS,MAClD,EAAS,CAAK,KAAK,OAAO,EAAM,MAAO,WAAW,CAAC,EAAM,EAAE,IAAI,CAAC,CAClE,CACF;AACF;AAEA,SAAS,EAAuB,GAA8C;CAC5E,IAAI,MAAc,KAAA,GAAW,OAAO;CAEpC,IAAM,IAAS,EAA0B,GAAW;EAClD,YAAY,EAAc;EAC1B,eAAe;CACjB,CAAC;CAUD,OATK,EAAO,QASL,KANL,QAAQ,KACN,+CACA,EAAO,OAAO,KAAK,IAAI,CACzB,GACO;AAGX;AAEA,IAAM,IAAW,EAAuB,CAA8B;AAMtE,SAAgB,IAA6B;CAC3C,QAAQ,GAAU,UAAU,GAAgB;AAC9C;AAUA,SAAgB,EAAsB,GAAqC;CACzE,QAAQ,GAAU,aAAa,GAAmB;AACpD;AAGA,SAAgB,EACd,GACA,GACQ;CACR,OAAO,EAAsB,CAAI,EAAE,QAAQ,QAAQ,mBAAmB,CAAE,CAAC;AAC3E;AAaA,IAAM,IAA2B;CAC/B,cAAc;CACd,kBAAkB;CAClB,wBAAwB;CACxB,qBAAqB;CACrB,WAAW;CACX,cAAc;CACd,iBAAiB;CACjB,WAAW;AACb;AAEA,SAAgB,IAAkC;CAEhD,OADK,IACE;EACL,cAAc,EAAS,WAAW,QAAQ;EAC1C,kBAAkB,EAAS,WAAW,YAAY;EAClD,wBAAwB,EAAS,WAAW,YAAY;EACxD,qBAAqB,EAAS,WAAW,YAAY;EACrD,WAAW,EAAS,MAAM,KAAK;EAC/B,cAAc,EAAS,MAAM,KAAK;EAClC,iBAAiB,EAAS,MAAM,OAAO;EACvC,WAAW,EAAS,MAAM,KAAK;CACjC,IAVsB;AAWxB;AAiBA,SAAgB,IAA6C;CAC3D,OAAO,GAAU,gBAAgB;AACnC"}
@@ -0,0 +1,2 @@
1
+ require("../_virtual/_rolldown/runtime.cjs"),require("../utils/automation-catalog.cjs");var e=require("./automation-interface.cjs").getAutomationEndpoint(`createPrompt`);exports.AUTOMATION_CREATE_ENDPOINT=e;
2
+ //# sourceMappingURL=automation-setup.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation-setup.cjs","names":[],"sources":["../../src/manifests/automation-setup.ts"],"sourcesContent":["/**\n * The only module that knows a setup entry configures an *automation*.\n *\n * The published contract states just what varies between entries; everything\n * derivable is the host's to generate. That derivation is here, and nowhere\n * else, so the rest of `src/manifests/` stays about forms rather than about\n * automations.\n *\n * The algorithm mirrors `tests/test_automation_setup.py::_render_payload` in\n * `OpenHands/extensions`, which is the authoritative reference: it produces the\n * request bodies published in that repository's contract fixtures, and those\n * were verified against the live service. The create model is `extra=\"forbid\"`,\n * so any divergence is a hard 422 rather than a dropped field.\n */\n\nimport { findAutomationCommand } from \"#/utils/automation-catalog\";\nimport { getAutomationEndpoint } from \"./automation-interface\";\nimport { collectFields } from \"./manifest-local-validation\";\nimport { interpolateText } from \"./manifest-template\";\nimport type {\n SetupBlock,\n SetupEntry,\n SetupFormValues,\n SetupRequestBody,\n SetupTriggerKind,\n} from \"./types\";\n\n/** The creation endpoint a derived draft would be posted to. */\nexport const AUTOMATION_CREATE_ENDPOINT = getAutomationEndpoint(\"createPrompt\");\n\n/**\n * Trigger properties a form field may fill, per trigger kind. A field under a\n * trigger kind whose name is listed here fills the trigger property of the same\n * name; anything else there, such as a phrase to match, is an input to `filter`.\n */\nconst TRIGGER_PROPERTIES: Record<SetupTriggerKind, readonly string[]> = {\n cron: [\"schedule\", \"timezone\"],\n event: [\"on\"],\n};\n\n/**\n * Repository properties a form field may fill, read the same way\n * {@link TRIGGER_PROPERTIES} is: a field whose name is listed here fills the\n * `repos[]` property of the same name. `url` and `provider` are absent because\n * neither is answered by a field of its own — they come from the repo-picker's\n * value and from its declared provider.\n *\n * These two lists are the only field names the derivation knows; everything\n * else it reads it finds by field type. An entry that wants a base branch in\n * its request therefore has to name that field `ref`.\n */\nconst REPO_PROPERTIES: readonly string[] = [\"ref\"];\n\nconst FORM_PLACEHOLDER_PATTERN = /\\{\\{form\\.([A-Za-z0-9_.]+)\\}\\}/g;\n\n/** The repository input, which supplies `repos` and an event trigger's source. */\nfunction findRepoPickerField(setup: SetupBlock) {\n const match = Object.entries(collectFields(setup)).find(\n ([, field]) => field.type === \"repo-picker\",\n );\n return match ? { name: match[0], field: match[1] } : null;\n}\n\n/** The single trigger kind a direct entry declares, with its fields. */\nfunction getTrigger(setup: SetupBlock) {\n const entries = Object.entries(setup.form.triggers ?? {});\n if (entries.length === 0) return null;\n const [kind, fields] = entries[0];\n return { kind: kind as SetupTriggerKind, fields: fields ?? {} };\n}\n\n/**\n * The create request body these form values produce.\n *\n * No entry declares it: `name` comes from the entry, `repos` from the\n * repo-picker field and its declared provider, and `trigger` from the key and\n * fields under `form.triggers`. Only `prompt` and an event `filter` are\n * declared, because only they cannot be read off the form.\n *\n * Returns null for an assisted entry, which hands setup to a conversation\n * instead of sending a body.\n */\nexport function buildCreatePayload(\n entry: SetupEntry,\n values: SetupFormValues,\n): SetupRequestBody | null {\n const { setup } = entry;\n if (setup.mode !== \"direct\" || !setup.prompt) return null;\n\n const scope = { form: values, automation: entry };\n const repoPicker = findRepoPickerField(setup);\n const repository = repoPicker ? values[repoPicker.name] : undefined;\n\n const payload: SetupRequestBody = {\n name: repository ? `${entry.name} - ${repository}` : entry.name,\n prompt: interpolateText(setup.prompt, scope),\n };\n\n if (repository && repoPicker?.field.provider) {\n const declared = REPO_PROPERTIES.filter((name) => name in values);\n payload.repos = [\n {\n url: repository,\n ...Object.fromEntries(declared.map((name) => [name, values[name]])),\n provider: repoPicker.field.provider,\n },\n ];\n }\n\n const trigger = getTrigger(setup);\n if (trigger) {\n const properties = TRIGGER_PROPERTIES[trigger.kind];\n const declared = Object.keys(trigger.fields).filter((name) =>\n properties.includes(name),\n );\n\n payload.trigger = {\n type: trigger.kind,\n ...Object.fromEntries(declared.map((name) => [name, values[name] ?? \"\"])),\n ...(trigger.kind === \"event\" && {\n source: repoPicker?.field.provider ?? \"\",\n // A filter is optional: an entry that declares none accepts every\n // delivered event, so the key is left off rather than sent empty.\n ...(setup.filter && { filter: interpolateText(setup.filter, scope) }),\n }),\n };\n }\n\n return payload;\n}\n\n/**\n * The preflight body the host sends. The same shape for every entry, so no\n * entry declares it.\n */\nexport function buildPreflightBody(\n entry: SetupEntry,\n values: SetupFormValues,\n): SetupRequestBody | null {\n const draft = buildCreatePayload(entry, values);\n if (!draft) return null;\n\n return {\n automationId: entry.id,\n endpoint: AUTOMATION_CREATE_ENDPOINT,\n draft,\n };\n}\n\n/**\n * What an assisted entry sends into the conversation that finishes setup.\n *\n * The command is not declared either: it lives once, in the owning skill's own\n * `triggers` frontmatter, and the skill defaults to the entry's id. An entry\n * whose skill is invoked by description rather than by command contributes\n * nothing here, and the answers alone open the conversation.\n */\nexport function buildAssistedMessage(\n entry: SetupEntry,\n values: SetupFormValues,\n): string {\n const command = findAutomationCommand(entry);\n const message = entry.setup.message\n ? interpolateText(entry.setup.message, { form: values, automation: entry })\n : \"\";\n\n return [command, message].filter(Boolean).join(\"\\n\\n\");\n}\n\nfunction collectPlaceholderFields(value: string): string[] {\n const names = Array.from(\n value.matchAll(FORM_PLACEHOLDER_PATTERN),\n (match) => match[1],\n );\n return Array.from(new Set(names));\n}\n\n/**\n * Which form fields built each payload path.\n *\n * Preflight and the create endpoint reject a draft by payload path, and the\n * host has to turn that back into a highlighted input. Building the body with\n * each field standing in for its own value recovers the mapping exactly, so an\n * entry does not declare it.\n */\nexport function deriveErrorMap(entry: SetupEntry): Record<string, string[]> {\n const mapping: Record<string, string[]> = {};\n\n const standIns = Object.fromEntries(\n Object.keys(collectFields(entry.setup)).map((name) => [\n name,\n `{{form.${name}}}`,\n ]),\n );\n const template = buildCreatePayload(entry, standIns);\n if (!template) return mapping;\n\n const walk = (node: unknown, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((item, index) => walk(item, `${path}[${index}]`));\n return;\n }\n if (typeof node === \"object\" && node !== null) {\n Object.entries(node).forEach(([key, item]) =>\n walk(item, path ? `${path}.${key}` : key),\n );\n return;\n }\n if (typeof node === \"string\") {\n const names = collectPlaceholderFields(node);\n if (names.length > 0) mapping[path] = names;\n }\n };\n\n walk(template, \"\");\n return mapping;\n}\n"],"mappings":"wFA4BA,IAAa,sCAA6B,EAAA,sBAAsB,cAAc"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The only module that knows a setup entry configures an *automation*.
3
+ *
4
+ * The published contract states just what varies between entries; everything
5
+ * derivable is the host's to generate. That derivation is here, and nowhere
6
+ * else, so the rest of `src/manifests/` stays about forms rather than about
7
+ * automations.
8
+ *
9
+ * The algorithm mirrors `tests/test_automation_setup.py::_render_payload` in
10
+ * `OpenHands/extensions`, which is the authoritative reference: it produces the
11
+ * request bodies published in that repository's contract fixtures, and those
12
+ * were verified against the live service. The create model is `extra="forbid"`,
13
+ * so any divergence is a hard 422 rather than a dropped field.
14
+ */
15
+ import type { SetupEntry, SetupFormValues, SetupRequestBody } from "./types";
16
+ /** The creation endpoint a derived draft would be posted to. */
17
+ export declare const AUTOMATION_CREATE_ENDPOINT: string;
18
+ /**
19
+ * The create request body these form values produce.
20
+ *
21
+ * No entry declares it: `name` comes from the entry, `repos` from the
22
+ * repo-picker field and its declared provider, and `trigger` from the key and
23
+ * fields under `form.triggers`. Only `prompt` and an event `filter` are
24
+ * declared, because only they cannot be read off the form.
25
+ *
26
+ * Returns null for an assisted entry, which hands setup to a conversation
27
+ * instead of sending a body.
28
+ */
29
+ export declare function buildCreatePayload(entry: SetupEntry, values: SetupFormValues): SetupRequestBody | null;
30
+ /**
31
+ * The preflight body the host sends. The same shape for every entry, so no
32
+ * entry declares it.
33
+ */
34
+ export declare function buildPreflightBody(entry: SetupEntry, values: SetupFormValues): SetupRequestBody | null;
35
+ /**
36
+ * What an assisted entry sends into the conversation that finishes setup.
37
+ *
38
+ * The command is not declared either: it lives once, in the owning skill's own
39
+ * `triggers` frontmatter, and the skill defaults to the entry's id. An entry
40
+ * whose skill is invoked by description rather than by command contributes
41
+ * nothing here, and the answers alone open the conversation.
42
+ */
43
+ export declare function buildAssistedMessage(entry: SetupEntry, values: SetupFormValues): string;
44
+ /**
45
+ * Which form fields built each payload path.
46
+ *
47
+ * Preflight and the create endpoint reject a draft by payload path, and the
48
+ * host has to turn that back into a highlighted input. Building the body with
49
+ * each field standing in for its own value recovers the mapping exactly, so an
50
+ * entry does not declare it.
51
+ */
52
+ export declare function deriveErrorMap(entry: SetupEntry): Record<string, string[]>;
@@ -0,0 +1,8 @@
1
+ import "../utils/automation-catalog.js";
2
+ import { getAutomationEndpoint as e } from "./automation-interface.js";
3
+ //#region src/manifests/automation-setup.ts
4
+ var t = e("createPrompt");
5
+ //#endregion
6
+ export { t as AUTOMATION_CREATE_ENDPOINT };
7
+
8
+ //# sourceMappingURL=automation-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation-setup.js","names":[],"sources":["../../src/manifests/automation-setup.ts"],"sourcesContent":["/**\n * The only module that knows a setup entry configures an *automation*.\n *\n * The published contract states just what varies between entries; everything\n * derivable is the host's to generate. That derivation is here, and nowhere\n * else, so the rest of `src/manifests/` stays about forms rather than about\n * automations.\n *\n * The algorithm mirrors `tests/test_automation_setup.py::_render_payload` in\n * `OpenHands/extensions`, which is the authoritative reference: it produces the\n * request bodies published in that repository's contract fixtures, and those\n * were verified against the live service. The create model is `extra=\"forbid\"`,\n * so any divergence is a hard 422 rather than a dropped field.\n */\n\nimport { findAutomationCommand } from \"#/utils/automation-catalog\";\nimport { getAutomationEndpoint } from \"./automation-interface\";\nimport { collectFields } from \"./manifest-local-validation\";\nimport { interpolateText } from \"./manifest-template\";\nimport type {\n SetupBlock,\n SetupEntry,\n SetupFormValues,\n SetupRequestBody,\n SetupTriggerKind,\n} from \"./types\";\n\n/** The creation endpoint a derived draft would be posted to. */\nexport const AUTOMATION_CREATE_ENDPOINT = getAutomationEndpoint(\"createPrompt\");\n\n/**\n * Trigger properties a form field may fill, per trigger kind. A field under a\n * trigger kind whose name is listed here fills the trigger property of the same\n * name; anything else there, such as a phrase to match, is an input to `filter`.\n */\nconst TRIGGER_PROPERTIES: Record<SetupTriggerKind, readonly string[]> = {\n cron: [\"schedule\", \"timezone\"],\n event: [\"on\"],\n};\n\n/**\n * Repository properties a form field may fill, read the same way\n * {@link TRIGGER_PROPERTIES} is: a field whose name is listed here fills the\n * `repos[]` property of the same name. `url` and `provider` are absent because\n * neither is answered by a field of its own — they come from the repo-picker's\n * value and from its declared provider.\n *\n * These two lists are the only field names the derivation knows; everything\n * else it reads it finds by field type. An entry that wants a base branch in\n * its request therefore has to name that field `ref`.\n */\nconst REPO_PROPERTIES: readonly string[] = [\"ref\"];\n\nconst FORM_PLACEHOLDER_PATTERN = /\\{\\{form\\.([A-Za-z0-9_.]+)\\}\\}/g;\n\n/** The repository input, which supplies `repos` and an event trigger's source. */\nfunction findRepoPickerField(setup: SetupBlock) {\n const match = Object.entries(collectFields(setup)).find(\n ([, field]) => field.type === \"repo-picker\",\n );\n return match ? { name: match[0], field: match[1] } : null;\n}\n\n/** The single trigger kind a direct entry declares, with its fields. */\nfunction getTrigger(setup: SetupBlock) {\n const entries = Object.entries(setup.form.triggers ?? {});\n if (entries.length === 0) return null;\n const [kind, fields] = entries[0];\n return { kind: kind as SetupTriggerKind, fields: fields ?? {} };\n}\n\n/**\n * The create request body these form values produce.\n *\n * No entry declares it: `name` comes from the entry, `repos` from the\n * repo-picker field and its declared provider, and `trigger` from the key and\n * fields under `form.triggers`. Only `prompt` and an event `filter` are\n * declared, because only they cannot be read off the form.\n *\n * Returns null for an assisted entry, which hands setup to a conversation\n * instead of sending a body.\n */\nexport function buildCreatePayload(\n entry: SetupEntry,\n values: SetupFormValues,\n): SetupRequestBody | null {\n const { setup } = entry;\n if (setup.mode !== \"direct\" || !setup.prompt) return null;\n\n const scope = { form: values, automation: entry };\n const repoPicker = findRepoPickerField(setup);\n const repository = repoPicker ? values[repoPicker.name] : undefined;\n\n const payload: SetupRequestBody = {\n name: repository ? `${entry.name} - ${repository}` : entry.name,\n prompt: interpolateText(setup.prompt, scope),\n };\n\n if (repository && repoPicker?.field.provider) {\n const declared = REPO_PROPERTIES.filter((name) => name in values);\n payload.repos = [\n {\n url: repository,\n ...Object.fromEntries(declared.map((name) => [name, values[name]])),\n provider: repoPicker.field.provider,\n },\n ];\n }\n\n const trigger = getTrigger(setup);\n if (trigger) {\n const properties = TRIGGER_PROPERTIES[trigger.kind];\n const declared = Object.keys(trigger.fields).filter((name) =>\n properties.includes(name),\n );\n\n payload.trigger = {\n type: trigger.kind,\n ...Object.fromEntries(declared.map((name) => [name, values[name] ?? \"\"])),\n ...(trigger.kind === \"event\" && {\n source: repoPicker?.field.provider ?? \"\",\n // A filter is optional: an entry that declares none accepts every\n // delivered event, so the key is left off rather than sent empty.\n ...(setup.filter && { filter: interpolateText(setup.filter, scope) }),\n }),\n };\n }\n\n return payload;\n}\n\n/**\n * The preflight body the host sends. The same shape for every entry, so no\n * entry declares it.\n */\nexport function buildPreflightBody(\n entry: SetupEntry,\n values: SetupFormValues,\n): SetupRequestBody | null {\n const draft = buildCreatePayload(entry, values);\n if (!draft) return null;\n\n return {\n automationId: entry.id,\n endpoint: AUTOMATION_CREATE_ENDPOINT,\n draft,\n };\n}\n\n/**\n * What an assisted entry sends into the conversation that finishes setup.\n *\n * The command is not declared either: it lives once, in the owning skill's own\n * `triggers` frontmatter, and the skill defaults to the entry's id. An entry\n * whose skill is invoked by description rather than by command contributes\n * nothing here, and the answers alone open the conversation.\n */\nexport function buildAssistedMessage(\n entry: SetupEntry,\n values: SetupFormValues,\n): string {\n const command = findAutomationCommand(entry);\n const message = entry.setup.message\n ? interpolateText(entry.setup.message, { form: values, automation: entry })\n : \"\";\n\n return [command, message].filter(Boolean).join(\"\\n\\n\");\n}\n\nfunction collectPlaceholderFields(value: string): string[] {\n const names = Array.from(\n value.matchAll(FORM_PLACEHOLDER_PATTERN),\n (match) => match[1],\n );\n return Array.from(new Set(names));\n}\n\n/**\n * Which form fields built each payload path.\n *\n * Preflight and the create endpoint reject a draft by payload path, and the\n * host has to turn that back into a highlighted input. Building the body with\n * each field standing in for its own value recovers the mapping exactly, so an\n * entry does not declare it.\n */\nexport function deriveErrorMap(entry: SetupEntry): Record<string, string[]> {\n const mapping: Record<string, string[]> = {};\n\n const standIns = Object.fromEntries(\n Object.keys(collectFields(entry.setup)).map((name) => [\n name,\n `{{form.${name}}}`,\n ]),\n );\n const template = buildCreatePayload(entry, standIns);\n if (!template) return mapping;\n\n const walk = (node: unknown, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((item, index) => walk(item, `${path}[${index}]`));\n return;\n }\n if (typeof node === \"object\" && node !== null) {\n Object.entries(node).forEach(([key, item]) =>\n walk(item, path ? `${path}.${key}` : key),\n );\n return;\n }\n if (typeof node === \"string\") {\n const names = collectPlaceholderFields(node);\n if (names.length > 0) mapping[path] = names;\n }\n };\n\n walk(template, \"\");\n return mapping;\n}\n"],"mappings":";;;AA4BA,IAAa,IAA6B,EAAsB,cAAc"}
@@ -0,0 +1,2 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");var e=/<[A-Za-z/!]/,t=/^[a-z0-9]+(-[a-z0-9]+)*$/,n=`https://docs.openhands.dev/`,r=/^[a-z][a-z-]*$/,i=/^\.[a-z][a-z.]*json$/,a=/^[a-z0-9][a-z0-9.-]*$/,o=/^\/[A-Za-z0-9/{}_-]*$/,s=/^[^{}]*\{id\}[^{}]*$/,c=[`github`,`gitlab`,`bitbucket`],l={name:{type:`text`,required:!0},prompt:{type:`textarea`,required:!1},model:{type:`llm-profile`,required:!1},timeout:{type:`number`,required:!1},schedule:{type:`schedule`,required:!1}},u=Object.keys(l),d=[`list`,`health`,`capabilities`,`validate`,`createPrompt`,`createPlugin`],f=[`detail`,`dispatch`,`runs`,`tarball`];function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var m=class{errors=[];fail(e,t){return this.errors.push(`${e}: ${t}`),!1}copy(t,n){return typeof t!=`string`||t.length===0?this.fail(n,`must be a non-empty string`):e.test(t)?this.fail(n,`must not contain markup`):!0}closed(e,t,n){Object.keys(e).filter(e=>!t.includes(e)).forEach(e=>this.fail(`${n}.${e}`,`is not allowed`))}record(e,t){return p(e)?!0:(this.fail(t,`must be an object`),!1)}};function h(e,t,n){e.record(t,`routes`)&&(e.closed(t,[`list`,`setup`,`detail`],`routes`),[`list`,`setup`,`detail`].forEach(r=>{t[r]!==n[r]&&e.fail(`routes.${r}`,`must be "${n[r]}"`)}))}function g(e,t){if(e.record(t,`navigation`)&&(e.closed(t,[`sidebar`,`commandMenu`],`navigation`),e.record(t.sidebar,`navigation.sidebar`)&&(e.closed(t.sidebar,[`label`],`navigation.sidebar`),e.copy(t.sidebar.label,`navigation.sidebar.label`)),e.record(t.commandMenu,`navigation.commandMenu`))){let n=t.commandMenu;e.closed(n,[`title`,`description`,`keywords`],`navigation.commandMenu`),e.copy(n.title,`navigation.commandMenu.title`),e.copy(n.description,`navigation.commandMenu.description`),e.copy(n.keywords,`navigation.commandMenu.keywords`)}}function _(e,t){e.record(t,`pages`)&&(e.closed(t,[`list`,`detail`,`edit`],`pages`),e.record(t.list,`pages.list`)&&(e.closed(t.list,[`title`,`subtitle`],`pages.list`),e.copy(t.list.title,`pages.list.title`),e.copy(t.list.subtitle,`pages.list.subtitle`)),e.record(t.detail,`pages.detail`)&&(e.closed(t.detail,[`backLabel`],`pages.detail`),e.copy(t.detail.backLabel,`pages.detail.backLabel`)),e.record(t.edit,`pages.edit`)&&(e.closed(t.edit,[`title`],`pages.edit`),e.copy(t.edit.title,`pages.edit.title`)))}function v(e,t,n,r){if(!e.record(n,r))return;e.closed(n,[`type`,`label`,`help`,`required`,`constraints`],r);let{type:i,label:a,help:o,required:s,constraints:c}=n;if(i!==t.type&&e.fail(`${r}.type`,`must be "${t.type}", the control this host renders`),e.copy(a,`${r}.label`),o!==void 0&&e.copy(o,`${r}.help`),s!==t.required&&e.fail(`${r}.required`,`must be ${t.required}, what this host enforces`),c!==void 0){if(t.type!==`number`)e.fail(`${r}.constraints`,`is only allowed on a number attribute`);else if(e.record(c,`${r}.constraints`)){e.closed(c,[`min`,`max`],`${r}.constraints`);let{min:t,max:n}=c;t!==void 0&&t!==1&&e.fail(`${r}.constraints.min`,`must be the 1 this host enforces`),n!==void 0&&(!Number.isInteger(n)||n<1)&&e.fail(`${r}.constraints.max`,`must be a positive integer`)}}}function y(e,t){if(!e.record(t,`attributes`))return;let n=Object.keys(t);n.length===0&&e.fail(`attributes`,`must declare at least one attribute`),n.forEach(n=>{if(!u.includes(n)){e.fail(`attributes.${n}`,`is not a settable attribute`);return}v(e,l[n],t[n],`attributes.${n}`)})}function b(e,t){if(!e.record(t,`importExport`))return;e.closed(t,[`fileKind`,`fileVersion`,`filenameSuffix`,`importDefaults`],`importExport`);let{fileKind:n,fileVersion:o,filenameSuffix:s,importDefaults:l}=t;(typeof n!=`string`||!r.test(n))&&e.fail(`importExport.fileKind`,`must be a lowercase slug`),o!==1&&e.fail(`importExport.fileVersion`,`must be 1`),(typeof s!=`string`||!i.test(s))&&e.fail(`importExport.filenameSuffix`,`must be a .json suffix`),e.record(l,`importExport.importDefaults`)&&(e.closed(l,[`repoProvider`,`placeholderEventSource`],`importExport.importDefaults`),(typeof l.repoProvider!=`string`||!c.includes(l.repoProvider))&&e.fail(`importExport.importDefaults.repoProvider`,`is not a supported provider`),(typeof l.placeholderEventSource!=`string`||!a.test(l.placeholderEventSource))&&e.fail(`importExport.importDefaults.placeholderEventSource`,`must be a lowercase event source`))}function x(e,t){if(!e.record(t,`endpoints`))return;let n=[...d,...f];e.closed(t,n,`endpoints`);let r=n=>{let r=t[n];return typeof r!=`string`||!o.test(r)||r.includes(`//`)?(e.fail(`endpoints.${n}`,`must be a rooted service-relative path`),null):r};d.forEach(t=>{let n=r(t);n!==null&&/[{}]/.test(n)&&e.fail(`endpoints.${t}`,`must not carry a substitution`)}),f.forEach(t=>{let n=r(t);n!==null&&!s.test(n)&&e.fail(`endpoints.${t}`,`must carry exactly one {id}`)})}function S(e,n,r){if(!Array.isArray(n)||n.length===0)return e.fail(r,`must be a non-empty array`),[];let i=n.filter(n=>typeof n==`string`&&t.test(n)?!0:(e.fail(r,`must contain only lowercase slugs`),!1));return new Set(i).size!==i.length&&e.fail(r,`must not repeat an id`),i}var C=[`version`,`routes`,`navigation`,`pages`,`docsUrl`,`attributes`,`importExport`,`endpoints`,`featuredAutomationIds`,`responderIntegrationIds`];function w(e,t){if(!p(e))return{valid:!1,errors:[`interface: must be an object`]};if(e.version!==`1.0`)return{valid:!1,errors:[`interface.version: must be "1.0"`]};let r=new m;return r.closed(e,C,`interface`),h(r,e.routes,t.mountedRoutes),g(r,e.navigation),_(r,e.pages),(typeof e.docsUrl!=`string`||!e.docsUrl.startsWith(n))&&r.fail(`docsUrl`,`must start with ${n}`),y(r,e.attributes),b(r,e.importExport),x(r,e.endpoints),S(r,e.featuredAutomationIds,`featuredAutomationIds`).forEach(e=>{t.catalogIds.has(e)||r.fail(`featuredAutomationIds`,`${e} is not a catalog entry`)}),S(r,e.responderIntegrationIds,`responderIntegrationIds`),{valid:r.errors.length===0,errors:r.errors}}exports.validateInterfaceManifest=w;
2
+ //# sourceMappingURL=interface-validation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface-validation.cjs","names":[],"sources":["../../src/manifests/interface-validation.ts"],"sourcesContent":["/**\n * Admission policy for the extension-published Automation interface manifest.\n *\n * Like a setup entry, the interface manifest is data authored in a different\n * repository that instructs this host to render copy, build links, and address\n * requests, so the host decides what it is *permitted* to state. Admission is\n * all-or-nothing: one bad field rejects the whole manifest, and the host falls\n * back to its own defaults rather than rendering a partially-trusted mix.\n */\n\nimport type {\n AutomationAttributeName,\n InterfaceAttributeType,\n InterfaceRoutes,\n} from \"./types\";\nimport { INTERFACE_VERSION } from \"./types\";\n\n/** Copy must never be able to inject markup into the host. */\nconst MARKUP_PATTERN = /<[A-Za-z/!]/;\nconst SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n/** The one URL the manifest may state, pinned to the product documentation. */\nconst DOCS_URL_PREFIX = \"https://docs.openhands.dev/\";\nconst FILE_KIND_PATTERN = /^[a-z][a-z-]*$/;\nconst FILENAME_SUFFIX_PATTERN = /^\\.[a-z][a-z.]*json$/;\nconst EVENT_SOURCE_PATTERN = /^[a-z0-9][a-z0-9.-]*$/;\n/** Service-relative only: rooted, no traversal, no query, no fragment. */\nconst ENDPOINT_PATTERN = /^\\/[A-Za-z0-9/{}_-]*$/;\n/** Exactly one `{id}` substitution and no other braces. */\nconst ID_ENDPOINT_PATTERN = /^[^{}]*\\{id\\}[^{}]*$/;\n\nconst GIT_PROVIDERS = [\"github\", \"gitlab\", \"bitbucket\"] as const;\n/**\n * The attribute semantics this host's edit dialog implements: the control it\n * renders per property and the requiredness it enforces. Admission pins a\n * declared attribute to exactly these, so an admitted manifest can never\n * promise a control, a requiredness, or (below) a minimum the form would\n * silently ignore.\n */\nconst HOST_ATTRIBUTES: Record<\n AutomationAttributeName,\n { type: InterfaceAttributeType; required: boolean }\n> = {\n name: { type: \"text\", required: true },\n prompt: { type: \"textarea\", required: false },\n model: { type: \"llm-profile\", required: false },\n timeout: { type: \"number\", required: false },\n schedule: { type: \"schedule\", required: false },\n};\nconst ATTRIBUTE_NAMES = Object.keys(HOST_ATTRIBUTES);\nconst PLAIN_ENDPOINT_NAMES = [\n \"list\",\n \"health\",\n \"capabilities\",\n \"validate\",\n \"createPrompt\",\n \"createPlugin\",\n] as const;\nconst ID_ENDPOINT_NAMES = [\"detail\", \"dispatch\", \"runs\", \"tarball\"] as const;\n\nexport interface InterfaceValidationContext {\n /** Ids of the published automation catalog, for the featured-list check. */\n catalogIds: ReadonlySet<string>;\n /** The routes this host has registrations for. A manifest must match them. */\n mountedRoutes: InterfaceRoutes;\n}\n\nexport interface InterfaceValidationResult {\n valid: boolean;\n errors: string[];\n}\n\ntype Rec = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Rec {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nclass InterfaceChecker {\n readonly errors: string[] = [];\n\n fail(path: string, reason: string): false {\n this.errors.push(`${path}: ${reason}`);\n return false;\n }\n\n /** Literal user-visible copy. Carries no markup. */\n copy(value: unknown, path: string): boolean {\n if (typeof value !== \"string\" || value.length === 0) {\n return this.fail(path, \"must be a non-empty string\");\n }\n if (MARKUP_PATTERN.test(value)) {\n return this.fail(path, \"must not contain markup\");\n }\n return true;\n }\n\n /** A closed object: every present key must be an expected one. */\n closed(container: Rec, allowed: readonly string[], path: string): void {\n Object.keys(container)\n .filter((key) => !allowed.includes(key))\n .forEach((key) => this.fail(`${path}.${key}`, \"is not allowed\"));\n }\n\n record(value: unknown, path: string): value is Rec {\n if (isRecord(value)) return true;\n this.fail(path, \"must be an object\");\n return false;\n }\n}\n\nfunction checkRoutes(\n check: InterfaceChecker,\n routes: unknown,\n mounted: InterfaceRoutes,\n): void {\n if (!check.record(routes, \"routes\")) return;\n check.closed(routes, [\"list\", \"setup\", \"detail\"], \"routes\");\n\n // The host serves what it has registrations for, so a declared route must be\n // exactly the mounted shape — the manifest owns link construction, not the\n // router table.\n ([\"list\", \"setup\", \"detail\"] as const).forEach((name) => {\n if (routes[name] !== mounted[name]) {\n check.fail(`routes.${name}`, `must be \"${mounted[name]}\"`);\n }\n });\n}\n\nfunction checkNavigation(check: InterfaceChecker, navigation: unknown): void {\n if (!check.record(navigation, \"navigation\")) return;\n check.closed(navigation, [\"sidebar\", \"commandMenu\"], \"navigation\");\n\n if (check.record(navigation.sidebar, \"navigation.sidebar\")) {\n check.closed(navigation.sidebar, [\"label\"], \"navigation.sidebar\");\n check.copy(navigation.sidebar.label, \"navigation.sidebar.label\");\n }\n if (check.record(navigation.commandMenu, \"navigation.commandMenu\")) {\n const menu = navigation.commandMenu;\n check.closed(\n menu,\n [\"title\", \"description\", \"keywords\"],\n \"navigation.commandMenu\",\n );\n check.copy(menu.title, \"navigation.commandMenu.title\");\n check.copy(menu.description, \"navigation.commandMenu.description\");\n check.copy(menu.keywords, \"navigation.commandMenu.keywords\");\n }\n}\n\nfunction checkPages(check: InterfaceChecker, pages: unknown): void {\n if (!check.record(pages, \"pages\")) return;\n check.closed(pages, [\"list\", \"detail\", \"edit\"], \"pages\");\n\n if (check.record(pages.list, \"pages.list\")) {\n check.closed(pages.list, [\"title\", \"subtitle\"], \"pages.list\");\n check.copy(pages.list.title, \"pages.list.title\");\n check.copy(pages.list.subtitle, \"pages.list.subtitle\");\n }\n if (check.record(pages.detail, \"pages.detail\")) {\n check.closed(pages.detail, [\"backLabel\"], \"pages.detail\");\n check.copy(pages.detail.backLabel, \"pages.detail.backLabel\");\n }\n if (check.record(pages.edit, \"pages.edit\")) {\n check.closed(pages.edit, [\"title\"], \"pages.edit\");\n check.copy(pages.edit.title, \"pages.edit.title\");\n }\n}\n\nfunction checkAttribute(\n check: InterfaceChecker,\n host: { type: InterfaceAttributeType; required: boolean },\n attribute: unknown,\n path: string,\n): void {\n if (!check.record(attribute, path)) return;\n check.closed(\n attribute,\n [\"type\", \"label\", \"help\", \"required\", \"constraints\"],\n path,\n );\n\n const { type, label, help, required, constraints } = attribute;\n if (type !== host.type) {\n check.fail(\n `${path}.type`,\n `must be \"${host.type}\", the control this host renders`,\n );\n }\n check.copy(label, `${path}.label`);\n if (help !== undefined) check.copy(help, `${path}.help`);\n if (required !== host.required) {\n check.fail(\n `${path}.required`,\n `must be ${host.required}, what this host enforces`,\n );\n }\n\n if (constraints !== undefined) {\n if (host.type !== \"number\") {\n check.fail(\n `${path}.constraints`,\n \"is only allowed on a number attribute\",\n );\n } else if (check.record(constraints, `${path}.constraints`)) {\n check.closed(constraints, [\"min\", \"max\"], `${path}.constraints`);\n const { min, max } = constraints;\n // The form validates a positive integer, i.e. an effective minimum of 1;\n // any other declared minimum would be a promise it does not keep.\n if (min !== undefined && min !== 1) {\n check.fail(\n `${path}.constraints.min`,\n \"must be the 1 this host enforces\",\n );\n }\n if (\n max !== undefined &&\n (!Number.isInteger(max) || (max as number) < 1)\n ) {\n check.fail(`${path}.constraints.max`, \"must be a positive integer\");\n }\n }\n }\n}\n\nfunction checkAttributes(check: InterfaceChecker, attributes: unknown): void {\n if (!check.record(attributes, \"attributes\")) return;\n const names = Object.keys(attributes);\n if (names.length === 0) {\n check.fail(\"attributes\", \"must declare at least one attribute\");\n }\n names.forEach((name) => {\n if (!ATTRIBUTE_NAMES.includes(name)) {\n check.fail(`attributes.${name}`, \"is not a settable attribute\");\n return;\n }\n checkAttribute(\n check,\n HOST_ATTRIBUTES[name as AutomationAttributeName],\n attributes[name],\n `attributes.${name}`,\n );\n });\n}\n\nfunction checkImportExport(\n check: InterfaceChecker,\n importExport: unknown,\n): void {\n if (!check.record(importExport, \"importExport\")) return;\n check.closed(\n importExport,\n [\"fileKind\", \"fileVersion\", \"filenameSuffix\", \"importDefaults\"],\n \"importExport\",\n );\n\n const { fileKind, fileVersion, filenameSuffix, importDefaults } =\n importExport;\n if (typeof fileKind !== \"string\" || !FILE_KIND_PATTERN.test(fileKind)) {\n check.fail(\"importExport.fileKind\", \"must be a lowercase slug\");\n }\n if (fileVersion !== 1) {\n check.fail(\"importExport.fileVersion\", \"must be 1\");\n }\n if (\n typeof filenameSuffix !== \"string\" ||\n !FILENAME_SUFFIX_PATTERN.test(filenameSuffix)\n ) {\n check.fail(\"importExport.filenameSuffix\", \"must be a .json suffix\");\n }\n if (check.record(importDefaults, \"importExport.importDefaults\")) {\n check.closed(\n importDefaults,\n [\"repoProvider\", \"placeholderEventSource\"],\n \"importExport.importDefaults\",\n );\n if (\n typeof importDefaults.repoProvider !== \"string\" ||\n !(GIT_PROVIDERS as readonly string[]).includes(\n importDefaults.repoProvider,\n )\n ) {\n check.fail(\n \"importExport.importDefaults.repoProvider\",\n \"is not a supported provider\",\n );\n }\n if (\n typeof importDefaults.placeholderEventSource !== \"string\" ||\n !EVENT_SOURCE_PATTERN.test(importDefaults.placeholderEventSource)\n ) {\n check.fail(\n \"importExport.importDefaults.placeholderEventSource\",\n \"must be a lowercase event source\",\n );\n }\n }\n}\n\nfunction checkEndpoints(check: InterfaceChecker, endpoints: unknown): void {\n if (!check.record(endpoints, \"endpoints\")) return;\n const allowed = [...PLAIN_ENDPOINT_NAMES, ...ID_ENDPOINT_NAMES];\n check.closed(endpoints, allowed, \"endpoints\");\n\n const endpointAt = (name: string): string | null => {\n const value = endpoints[name];\n if (\n typeof value !== \"string\" ||\n !ENDPOINT_PATTERN.test(value) ||\n value.includes(\"//\")\n ) {\n check.fail(`endpoints.${name}`, \"must be a rooted service-relative path\");\n return null;\n }\n return value;\n };\n\n PLAIN_ENDPOINT_NAMES.forEach((name) => {\n const value = endpointAt(name);\n if (value !== null && /[{}]/.test(value)) {\n check.fail(`endpoints.${name}`, \"must not carry a substitution\");\n }\n });\n ID_ENDPOINT_NAMES.forEach((name) => {\n const value = endpointAt(name);\n if (value !== null && !ID_ENDPOINT_PATTERN.test(value)) {\n check.fail(`endpoints.${name}`, \"must carry exactly one {id}\");\n }\n });\n}\n\nfunction checkSlugList(\n check: InterfaceChecker,\n value: unknown,\n path: string,\n): string[] {\n if (!Array.isArray(value) || value.length === 0) {\n check.fail(path, \"must be a non-empty array\");\n return [];\n }\n const slugs = value.filter((item): item is string => {\n if (typeof item === \"string\" && SLUG_PATTERN.test(item)) return true;\n check.fail(path, \"must contain only lowercase slugs\");\n return false;\n });\n if (new Set(slugs).size !== slugs.length) {\n check.fail(path, \"must not repeat an id\");\n }\n return slugs;\n}\n\nconst TOP_LEVEL_KEYS = [\n \"version\",\n \"routes\",\n \"navigation\",\n \"pages\",\n \"docsUrl\",\n \"attributes\",\n \"importExport\",\n \"endpoints\",\n \"featuredAutomationIds\",\n \"responderIntegrationIds\",\n];\n\n/**\n * Decide whether this host will act on a published interface manifest.\n *\n * The version is checked first and fails closed: a format this host does not\n * recognise is refused rather than interpreted with today's rules.\n */\nexport function validateInterfaceManifest(\n candidate: unknown,\n context: InterfaceValidationContext,\n): InterfaceValidationResult {\n if (!isRecord(candidate)) {\n return { valid: false, errors: [\"interface: must be an object\"] };\n }\n if (candidate.version !== INTERFACE_VERSION) {\n return {\n valid: false,\n errors: [`interface.version: must be \"${INTERFACE_VERSION}\"`],\n };\n }\n\n const check = new InterfaceChecker();\n check.closed(candidate, TOP_LEVEL_KEYS, \"interface\");\n\n checkRoutes(check, candidate.routes, context.mountedRoutes);\n checkNavigation(check, candidate.navigation);\n checkPages(check, candidate.pages);\n if (\n typeof candidate.docsUrl !== \"string\" ||\n !candidate.docsUrl.startsWith(DOCS_URL_PREFIX)\n ) {\n check.fail(\"docsUrl\", `must start with ${DOCS_URL_PREFIX}`);\n }\n checkAttributes(check, candidate.attributes);\n checkImportExport(check, candidate.importExport);\n checkEndpoints(check, candidate.endpoints);\n\n checkSlugList(\n check,\n candidate.featuredAutomationIds,\n \"featuredAutomationIds\",\n ).forEach((id) => {\n if (!context.catalogIds.has(id)) {\n check.fail(\"featuredAutomationIds\", `${id} is not a catalog entry`);\n }\n });\n checkSlugList(\n check,\n candidate.responderIntegrationIds,\n \"responderIntegrationIds\",\n );\n\n return { valid: check.errors.length === 0, errors: check.errors };\n}\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Admission policy for the extension-published Automation interface manifest.
3
+ *
4
+ * Like a setup entry, the interface manifest is data authored in a different
5
+ * repository that instructs this host to render copy, build links, and address
6
+ * requests, so the host decides what it is *permitted* to state. Admission is
7
+ * all-or-nothing: one bad field rejects the whole manifest, and the host falls
8
+ * back to its own defaults rather than rendering a partially-trusted mix.
9
+ */
10
+ import type { InterfaceRoutes } from "./types";
11
+ export interface InterfaceValidationContext {
12
+ /** Ids of the published automation catalog, for the featured-list check. */
13
+ catalogIds: ReadonlySet<string>;
14
+ /** The routes this host has registrations for. A manifest must match them. */
15
+ mountedRoutes: InterfaceRoutes;
16
+ }
17
+ export interface InterfaceValidationResult {
18
+ valid: boolean;
19
+ errors: string[];
20
+ }
21
+ /**
22
+ * Decide whether this host will act on a published interface manifest.
23
+ *
24
+ * The version is checked first and fails closed: a format this host does not
25
+ * recognise is refused rather than interpreted with today's rules.
26
+ */
27
+ export declare function validateInterfaceManifest(candidate: unknown, context: InterfaceValidationContext): InterfaceValidationResult;