@openhands/agent-canvas 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{Trans-DP5rcauH.js → Trans-B7lYw4uD.js} +1 -1
  4. package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-WUD4tfSq.js} +1 -1
  5. package/build/assets/active-backend-context-mY7Gff5c.js +2 -0
  6. package/build/assets/{agent-context-settings-BwAakl29.js → agent-context-settings-BTUmWEzL.js} +1 -1
  7. package/build/assets/{agent-profiles-settings-BYU6aWus.js → agent-profiles-settings-Ilqid_R5.js} +1 -1
  8. package/build/assets/agent-server-conversation-service.api-C_7YnjzP.js +41 -0
  9. package/build/assets/{agent-settings-DEPFl5hR.js → agent-settings-BGTyoT6X.js} +2 -2
  10. package/build/assets/agent-settings-CxfT4ksO.js +1 -0
  11. package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-eRyIwDyU.js} +1 -1
  12. package/build/assets/api-key-entry-screen-JOx3SH1-.js +1 -0
  13. package/build/assets/app-settings-D53QZy5p.js +1 -0
  14. package/build/assets/automation-detail-nEflClmc.js +2 -0
  15. package/build/assets/{automation-export-Ca2ehC-k.js → automation-export-BO_kfqC8.js} +1 -1
  16. package/build/assets/{automations-list-ZHQSW8qD.js → automations-list-BYncC7gv.js} +1 -1
  17. package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-C02hGa8t.js} +1 -1
  18. package/build/assets/backend-form-modal-CKrBF80P.js +1 -0
  19. package/build/assets/{backend-synced-settings-badge-DdUfuSN8.js → backend-synced-settings-badge-CQ9xtNWm.js} +1 -1
  20. package/build/assets/{badge-B6q3sVom.js → badge-CzXbf7tR.js} +1 -1
  21. package/build/assets/{base-modal-CSHhJTSr.js → base-modal-DkVyzFMt.js} +1 -1
  22. package/build/assets/{brand-button-CQO8oqVo.js → brand-button-BUlDL-mz.js} +1 -1
  23. package/build/assets/{browser-BUDJnBg4.js → browser-3QjrEr1D.js} +1 -1
  24. package/build/assets/{browser-tab-Cir7KbAL.js → browser-tab-BijpUbdt.js} +1 -1
  25. package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-BKsVjhtA.js} +1 -1
  26. package/build/assets/check-CrxQfJZ2.js +1 -0
  27. package/build/assets/chevron-down-D_LsyTA7.js +1 -0
  28. package/build/assets/circle-check-DZn9HkLE.js +1 -0
  29. package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-DdjUiOo1.js} +1 -1
  30. package/build/assets/cloud-funnel-analytics-NlmDoeo2.js +1 -0
  31. package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Dl9UtvD6.js} +1 -1
  32. package/build/assets/{command-menu-N_BriUy8.js → command-menu-CvLPs7dg.js} +1 -1
  33. package/build/assets/{condenser-settings-jNGOKFGz.js → condenser-settings-C4Y9CzQV.js} +1 -1
  34. package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-CRBJSllP.js} +1 -1
  35. package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-FGaafXGh.js} +1 -1
  36. package/build/assets/conversation-D_ORtpKC.js +1 -0
  37. package/build/assets/conversation-Dpc5nmGi.js +90 -0
  38. package/build/assets/conversation-panel-D_ORtpKC.js +1 -0
  39. package/build/assets/conversation-state-store-CGRQemtx.js +1 -0
  40. package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-CDjvNgpG.js} +1 -1
  41. package/build/assets/{copy-B8Y5ufoR.js → copy-Drwu97Gx.js} +1 -1
  42. package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-NbN1clVr.js} +1 -1
  43. package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-CDm_WrVu.js} +1 -1
  44. package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-CqA2BTCL.js} +1 -1
  45. package/build/assets/{entry.client-CCrlta8r.js → entry.client-BO2KQj0y.js} +2 -2
  46. package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-DSqPZnsD.js} +1 -1
  47. package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-mGl2pqqx.js} +1 -1
  48. package/build/assets/extensions-hub-Br3Lgynp.js +1 -0
  49. package/build/assets/extensions-navigation-BQmstKDZ.js +1 -0
  50. package/build/assets/{external-link-Cnnd6ikC.js → external-link-D9B2QMPf.js} +1 -1
  51. package/build/assets/files-tab-4c9HFSLo.js +1 -0
  52. package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-CtVAktAy.js} +1 -1
  53. package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-DICE64sz.js} +1 -1
  54. package/build/assets/git-provider-icon-0PqmIS_S.js +1 -0
  55. package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-KMsA9c4a.js} +1 -1
  56. package/build/assets/home-D9JsyEmE.js +1 -0
  57. package/build/assets/{home-BZclW6kd.js → home-TFhnmZLx.js} +1 -1
  58. package/build/assets/index-home-D9JsyEmE.js +1 -0
  59. package/build/assets/install-server-modal-BgGRnqA0.js +1 -0
  60. package/build/assets/{launch-Bik37u9Y.js → launch-DjkKw55l.js} +1 -1
  61. package/build/assets/{list-todo-_BXQzOiB.js → list-todo-BpAf7aOT.js} +1 -1
  62. package/build/assets/{llm-not-configured-banner-znJFsW_O.js → llm-not-configured-banner-Y4W9-sar.js} +4 -4
  63. package/build/assets/llm-settings-D8zNkIlP.js +1 -0
  64. package/build/assets/llm-settings-nPwv7hKu.js +1 -0
  65. package/build/assets/{llm-subscription-service-_QUsVybQ.js → llm-subscription-service-COTgZc1C.js} +1 -1
  66. package/build/assets/loader-circle-CGD6-Vak.js +1 -0
  67. package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DRFyh6Iy.js} +1 -1
  68. package/build/assets/manage-backends-modal-DiRWE3tJ.js +1 -0
  69. package/build/assets/manifest-1cf33a7b.js +1 -0
  70. package/build/assets/markdown-renderer-U40HF0Ak.js +8 -0
  71. package/build/assets/mcp-xDMaHzOw.js +9 -0
  72. package/build/assets/{messages-CYztjKLQ.js → messages-CdNfZPgd.js} +2 -2
  73. package/build/assets/{modal-body-DQhiw-AR.js → modal-body-C3bGicn4.js} +1 -1
  74. package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-DFFO6BMU.js} +1 -1
  75. package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-vxkAIRyZ.js} +1 -1
  76. package/build/assets/{onboarding-9pEMFGtN.js → onboarding-DWuFieEA.js} +1 -1
  77. package/build/assets/onboarding-modal-C8m72Dpb.js +1 -0
  78. package/build/assets/organization-service.api-CQ73CB-S.js +1 -0
  79. package/build/assets/{pencil-8_lvWDoZ.js → pencil-DzW2GB2M.js} +1 -1
  80. package/build/assets/{planner-tab-Dr8B-ZBI.js → planner-tab-YG0bGxDY.js} +1 -1
  81. package/build/assets/plugins-management-service-ijhH8OSh.js +1 -0
  82. package/build/assets/plus-CTGLo3aa.js +1 -0
  83. package/build/assets/profiles-service.api-C32pPm70.js +1 -0
  84. package/build/assets/providers-DuSn9s2i.js +1 -0
  85. package/build/assets/proxy-BiyDhMBd.js +1 -0
  86. package/build/assets/{puzzle-DXWdfaa7.js → puzzle-DlqT0yvr.js} +1 -1
  87. package/build/assets/{recommended-automations-launcher-Dye8Li08.js → recommended-automations-launcher-Dru1yN46.js} +2 -2
  88. package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-Br5254f4.js} +1 -1
  89. package/build/assets/root-DOLLQteU.js +2 -0
  90. package/build/assets/root-layout-xmylWoew.js +3 -0
  91. package/build/assets/schema-field-htfNouTG.js +1 -0
  92. package/build/assets/{sdk-section-page-Di5mT86Y.js → sdk-section-page-D0K1dBQY.js} +1 -1
  93. package/build/assets/search-BrpWXWUi.js +1 -0
  94. package/build/assets/secrets-service-Dbv5Zb8G.js +1 -0
  95. package/build/assets/{secrets-settings-DPlA3moO.js → secrets-settings-Da4SSaX9.js} +1 -1
  96. package/build/assets/{segmented-toggle-DbbD3Tve.js → segmented-toggle-CZKOdIly.js} +1 -1
  97. package/build/assets/settings-F4a09IxY.js +1 -0
  98. package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-jOiv5Yrk.js} +1 -1
  99. package/build/assets/{settings-index-D5dDKrDt.js → settings-index-CyJBf5NA.js} +1 -1
  100. package/build/assets/{settings-input-BjW_zyTN.js → settings-input-BEaTCem1.js} +1 -1
  101. package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-VqMzkYYt.js} +1 -1
  102. package/build/assets/{settings-modal-DsJk2THd.js → settings-modal-C-S1NpbC.js} +1 -1
  103. package/build/assets/settings-service.api-CTJRrvMu.js +1 -0
  104. package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-B405oU_v.js} +1 -1
  105. package/build/assets/{shared-conversation-DU1kwDTF.js → shared-conversation-BvWtTwES.js} +1 -1
  106. package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-BGMuyC86.js} +1 -1
  107. package/build/assets/{sidebar-mobile-menu-toggle-BlmI8OrA.js → sidebar-mobile-menu-toggle-xiKoUfGa.js} +1 -1
  108. package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-DA4_ct9G.js} +1 -1
  109. package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-FRJ3rADB.js} +1 -1
  110. package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-BMdhr_sd.js} +1 -1
  111. package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-CGUkgcVH.js} +1 -1
  112. package/build/assets/{skills-plugins-YJSV6A0M.js → skills-plugins-C5eJnyft.js} +1 -1
  113. package/build/assets/{skills-settings-BbREHv_-.js → skills-settings-pUxMr6WZ.js} +1 -1
  114. package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-B3kIdVyH.js} +1 -1
  115. package/build/assets/{task-list-tab-Dzim5ftn.js → task-list-tab-B3k4W1cK.js} +1 -1
  116. package/build/assets/{terminal-CYFAMiXx.js → terminal-CBI_41Zc.js} +1 -1
  117. package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-DYRr9CAR.js} +1 -1
  118. package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-gZPlx23R.js} +1 -1
  119. package/build/assets/{typography-C6fuRTTT.js → typography-B1UxuuEC.js} +1 -1
  120. package/build/assets/{use-acp-credential-form-CuBXKNvP.js → use-acp-credential-form-CjSvKWFH.js} +1 -1
  121. package/build/assets/use-activate-agent-profile-DCRf47e-.js +1 -0
  122. package/build/assets/use-agent-profiles-DmT9zxAN.js +1 -0
  123. package/build/assets/{use-can-manage-org-profiles-Uai-HHx2.js → use-can-manage-org-profiles-vBiP7rHF.js} +1 -1
  124. package/build/assets/use-cloud-current-user-id-BMq9gw93.js +1 -0
  125. package/build/assets/use-config-C959QcRC.js +1 -0
  126. package/build/assets/{use-create-conversation-DzcM79TE.js → use-create-conversation-CakhLF0X.js} +1 -1
  127. package/build/assets/{use-create-secret-2YLjoQw-.js → use-create-secret-RT4QtSS9.js} +1 -1
  128. package/build/assets/use-llm-profiles-CdaxVpyY.js +1 -0
  129. package/build/assets/use-onboarding-completion-CJU4MNAY.js +1 -0
  130. package/build/assets/use-plugins-marketplace-D-93nqtJ.js +1 -0
  131. package/build/assets/{use-save-agent-profile-Q2M72WgR.js → use-save-agent-profile-DGJ3-u0M.js} +1 -1
  132. package/build/assets/{use-save-settings-BZK7zVsK.js → use-save-settings--C6LZXfI.js} +1 -1
  133. package/build/assets/use-settings-DIAo5KFk.js +1 -0
  134. package/build/assets/use-settings-nav-items-DPK5sxvR.js +16 -0
  135. package/build/assets/use-skills-D_mLhYNa.js +1 -0
  136. package/build/assets/use-tracking-COqZLobY.js +1 -0
  137. package/build/assets/{use-user-conversation-43duhf7D.js → use-user-conversation-DhcAEyJX.js} +1 -1
  138. package/build/assets/{useMutation-DyQXZFEF.js → useMutation-DHLpZ6J0.js} +1 -1
  139. package/build/assets/utils-DsWhWn2F.js +1 -0
  140. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CYPMCkX1.js} +1 -1
  141. package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-atebg0iG.js} +1 -1
  142. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-G9DMrR7m.js} +1 -1
  143. package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-DEhW1h3I.js} +1 -1
  144. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js → vendor~root-layout~index-home~home~conversation-panel~conversation-Acmf1sKj.js} +1 -1
  145. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-CmzCY1BT.js} +1 -1
  146. package/build/assets/{vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js → vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-C7Yh77RT.js} +1 -1
  147. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~bi2r7bko-Bw4AuHN1.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~bi2r7bko-VFnwct3q.js} +1 -1
  148. package/build/assets/{verification-settings-B4DL3Tez.js → verification-settings-Vr5cN4md.js} +1 -1
  149. package/build/assets/x-Dx_JbpHA.js +1 -0
  150. package/build/favicon-16x16.png +0 -0
  151. package/build/favicon-32x32.png +0 -0
  152. package/build/favicon.ico +0 -0
  153. package/build/index.html +4 -4
  154. package/build/locales/ar/openhands.json +2 -0
  155. package/build/locales/ca/openhands.json +2 -0
  156. package/build/locales/de/openhands.json +2 -0
  157. package/build/locales/en/openhands.json +2 -0
  158. package/build/locales/es/openhands.json +2 -0
  159. package/build/locales/fr/openhands.json +2 -0
  160. package/build/locales/it/openhands.json +2 -0
  161. package/build/locales/ja/openhands.json +2 -0
  162. package/build/locales/ko-KR/openhands.json +2 -0
  163. package/build/locales/no/openhands.json +2 -0
  164. package/build/locales/pt/openhands.json +2 -0
  165. package/build/locales/tr/openhands.json +2 -0
  166. package/build/locales/uk/openhands.json +2 -0
  167. package/build/locales/zh-CN/openhands.json +2 -0
  168. package/build/locales/zh-TW/openhands.json +2 -0
  169. package/config/defaults.json +4 -4
  170. package/dist/api/agent-server-adapter.cjs +1 -1
  171. package/dist/api/agent-server-adapter.cjs.map +1 -1
  172. package/dist/api/agent-server-adapter.js +7 -7
  173. package/dist/api/agent-server-adapter.js.map +1 -1
  174. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  175. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  176. package/dist/api/automation-service/automation-service.api.js +95 -95
  177. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  178. package/dist/api/backend-registry/storage.cjs +1 -1
  179. package/dist/api/backend-registry/storage.cjs.map +1 -1
  180. package/dist/api/backend-registry/storage.js +1 -1
  181. package/dist/api/backend-registry/storage.js.map +1 -1
  182. package/dist/api/backend-registry/types.d.ts +2 -0
  183. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  184. package/dist/api/cloud/conversation-service.api.js +22 -22
  185. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  186. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  187. package/dist/api/mcp-service/mcp-service.api.js +19 -19
  188. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  189. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  190. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  191. package/dist/api/settings-service/settings-service.api.js +26 -12
  192. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  193. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  194. package/dist/components/features/mcp-page/custom-server-editor.js +16 -16
  195. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  196. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  197. package/dist/components/features/mcp-page/installed-server-card.d.ts +2 -2
  198. package/dist/components/features/mcp-page/installed-server-card.js +6 -7
  199. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  200. package/dist/components/features/mcp-page/installed-servers-section.cjs +1 -1
  201. package/dist/components/features/mcp-page/installed-servers-section.cjs.map +1 -1
  202. package/dist/components/features/mcp-page/installed-servers-section.d.ts +2 -2
  203. package/dist/components/features/mcp-page/installed-servers-section.js +2 -2
  204. package/dist/components/features/mcp-page/installed-servers-section.js.map +1 -1
  205. package/dist/components/features/mcp-page/mcp-server-health.cjs +1 -1
  206. package/dist/components/features/mcp-page/mcp-server-health.js +4 -4
  207. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +1 -1
  208. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
  209. package/dist/components/features/settings/mcp-settings/mcp-server-form.js +2 -1
  210. package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
  211. package/dist/config/defaults.cjs +1 -1
  212. package/dist/config/defaults.cjs.map +1 -1
  213. package/dist/config/defaults.js +3 -3
  214. package/dist/config/defaults.js.map +1 -1
  215. package/dist/contexts/active-backend-context.cjs +1 -1
  216. package/dist/contexts/active-backend-context.cjs.map +1 -1
  217. package/dist/contexts/active-backend-context.d.ts +3 -2
  218. package/dist/contexts/active-backend-context.js +55 -42
  219. package/dist/contexts/active-backend-context.js.map +1 -1
  220. package/dist/favicon-16x16.png +0 -0
  221. package/dist/favicon-32x32.png +0 -0
  222. package/dist/favicon.ico +0 -0
  223. package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
  224. package/dist/hooks/mutation/use-update-mcp-server.js +5 -5
  225. package/dist/hooks/query/use-cloud-current-user-id.cjs +1 -1
  226. package/dist/hooks/query/use-cloud-current-user-id.cjs.map +1 -1
  227. package/dist/hooks/query/use-cloud-current-user-id.js +7 -5
  228. package/dist/hooks/query/use-cloud-current-user-id.js.map +1 -1
  229. package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
  230. package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
  231. package/dist/hooks/query/use-cloud-organizations.js +5 -1
  232. package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
  233. package/dist/hooks/use-can-manage-org-profiles.cjs +1 -1
  234. package/dist/hooks/use-can-manage-org-profiles.cjs.map +1 -1
  235. package/dist/hooks/use-can-manage-org-profiles.js +2 -1
  236. package/dist/hooks/use-can-manage-org-profiles.js.map +1 -1
  237. package/dist/hooks/use-tracking.cjs +1 -1
  238. package/dist/hooks/use-tracking.js +9 -9
  239. package/dist/i18n/declaration.cjs +1 -1
  240. package/dist/i18n/declaration.cjs.map +1 -1
  241. package/dist/i18n/declaration.d.ts +2 -0
  242. package/dist/i18n/declaration.js +1 -1
  243. package/dist/i18n/declaration.js.map +1 -1
  244. package/dist/i18n/translation.cjs +1 -1
  245. package/dist/i18n/translation.cjs.map +1 -1
  246. package/dist/i18n/translation.js +34 -0
  247. package/dist/i18n/translation.js.map +1 -1
  248. package/dist/locales/ar/openhands.json +2 -0
  249. package/dist/locales/ca/openhands.json +2 -0
  250. package/dist/locales/de/openhands.json +2 -0
  251. package/dist/locales/en/openhands.json +2 -0
  252. package/dist/locales/es/openhands.json +2 -0
  253. package/dist/locales/fr/openhands.json +2 -0
  254. package/dist/locales/it/openhands.json +2 -0
  255. package/dist/locales/ja/openhands.json +2 -0
  256. package/dist/locales/ko-KR/openhands.json +2 -0
  257. package/dist/locales/no/openhands.json +2 -0
  258. package/dist/locales/pt/openhands.json +2 -0
  259. package/dist/locales/tr/openhands.json +2 -0
  260. package/dist/locales/uk/openhands.json +2 -0
  261. package/dist/locales/zh-CN/openhands.json +2 -0
  262. package/dist/locales/zh-TW/openhands.json +2 -0
  263. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
  264. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
  265. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +9 -0
  266. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
  267. package/dist/package.cjs +1 -1
  268. package/dist/package.cjs.map +1 -1
  269. package/dist/package.js +7 -2
  270. package/dist/package.js.map +1 -1
  271. package/dist/routes/app-settings.cjs +1 -1
  272. package/dist/routes/app-settings.js +5 -5
  273. package/dist/routes/mcp.cjs +1 -1
  274. package/dist/routes/mcp.cjs.map +1 -1
  275. package/dist/routes/mcp.js +73 -82
  276. package/dist/routes/mcp.js.map +1 -1
  277. package/dist/services/telemetry.cjs +1 -1
  278. package/dist/services/telemetry.cjs.map +1 -1
  279. package/dist/services/telemetry.d.ts +8 -0
  280. package/dist/services/telemetry.js +163 -116
  281. package/dist/services/telemetry.js.map +1 -1
  282. package/dist/types/mcp-server.d.ts +5 -0
  283. package/dist/types/settings.d.ts +3 -0
  284. package/dist/utils/mcp-config.cjs +1 -1
  285. package/dist/utils/mcp-config.cjs.map +1 -1
  286. package/dist/utils/mcp-config.d.ts +8 -0
  287. package/dist/utils/mcp-config.js +25 -20
  288. package/dist/utils/mcp-config.js.map +1 -1
  289. package/dist/utils/mcp-installed-servers.cjs +1 -1
  290. package/dist/utils/mcp-installed-servers.cjs.map +1 -1
  291. package/dist/utils/mcp-installed-servers.js +6 -3
  292. package/dist/utils/mcp-installed-servers.js.map +1 -1
  293. package/package.json +7 -2
  294. package/scripts/check-sdk-version-sync.mjs +6 -6
  295. package/scripts/dev-safe.mjs +2 -2
  296. package/scripts/stryker-diff.mjs +137 -0
  297. package/build/assets/active-backend-context-B9942JGX.js +0 -1
  298. package/build/assets/agent-server-conversation-service.api-D7qh9amG.js +0 -41
  299. package/build/assets/agent-settings-BbNLRtoh.js +0 -1
  300. package/build/assets/api-key-entry-screen-B2kVLRDQ.js +0 -1
  301. package/build/assets/app-settings-B92bjTei.js +0 -1
  302. package/build/assets/automation-detail-DoVSHQLs.js +0 -2
  303. package/build/assets/backend-form-modal-C0CIsQvd.js +0 -1
  304. package/build/assets/check-BMOG005H.js +0 -1
  305. package/build/assets/chevron-down-CV1zZP_K.js +0 -1
  306. package/build/assets/circle-check-lvN_jFN5.js +0 -1
  307. package/build/assets/client-source-D8jWKBfE.js +0 -1
  308. package/build/assets/cloud-funnel-analytics-CnCkPgQa.js +0 -1
  309. package/build/assets/conversation-DceG4LFS.js +0 -90
  310. package/build/assets/conversation-Do2Vg7uo.js +0 -1
  311. package/build/assets/conversation-panel-Do2Vg7uo.js +0 -1
  312. package/build/assets/conversation-state-store-BORusMiV.js +0 -1
  313. package/build/assets/extensions-hub-B2WudOET.js +0 -1
  314. package/build/assets/extensions-navigation-CYjIM65d.js +0 -1
  315. package/build/assets/files-tab-LSBijbEi.js +0 -1
  316. package/build/assets/git-provider-icon-DeQUgZVE.js +0 -1
  317. package/build/assets/home-C_R5pEbs.js +0 -1
  318. package/build/assets/index-home-C_R5pEbs.js +0 -1
  319. package/build/assets/install-server-modal-xCf76eim.js +0 -1
  320. package/build/assets/llm-settings-BYo9SN0I.js +0 -1
  321. package/build/assets/llm-settings-BaM0zJg5.js +0 -1
  322. package/build/assets/loader-circle-6zlEYCJw.js +0 -1
  323. package/build/assets/manage-backends-modal-n6PtHOER.js +0 -1
  324. package/build/assets/manifest-e9bbad7b.js +0 -1
  325. package/build/assets/markdown-renderer-Dkmjmx_d.js +0 -8
  326. package/build/assets/mcp-BJUOnO6v.js +0 -9
  327. package/build/assets/onboarding-modal-dYsjXJwx.js +0 -1
  328. package/build/assets/organization-service.api-HsxJhNCf.js +0 -1
  329. package/build/assets/plugins-management-service-DEjBqDoT.js +0 -1
  330. package/build/assets/plus-vIbGD459.js +0 -1
  331. package/build/assets/profiles-service.api-BddMsEhq.js +0 -1
  332. package/build/assets/providers-BxJi3BMO.js +0 -1
  333. package/build/assets/proxy-CN3HaaOW.js +0 -1
  334. package/build/assets/root-D4hpCAq9.js +0 -2
  335. package/build/assets/root-layout-a4-4sfbh.js +0 -3
  336. package/build/assets/schema-field-CZSs0hQP.js +0 -1
  337. package/build/assets/search-sKuYKllf.js +0 -1
  338. package/build/assets/secrets-service-i4CCd-UN.js +0 -1
  339. package/build/assets/settings-SHSt9Rq2.js +0 -1
  340. package/build/assets/settings-service.api-i_HHIqJP.js +0 -1
  341. package/build/assets/telemetry-B-2fXtqV.js +0 -2
  342. package/build/assets/use-activate-agent-profile-CXDcjVt8.js +0 -1
  343. package/build/assets/use-agent-profiles-CliaHofi.js +0 -1
  344. package/build/assets/use-cloud-current-user-id-BzamKpu-.js +0 -1
  345. package/build/assets/use-config-DPEYpfIj.js +0 -1
  346. package/build/assets/use-llm-profiles-Ci3zAVzV.js +0 -1
  347. package/build/assets/use-onboarding-completion-STApsofr.js +0 -1
  348. package/build/assets/use-plugins-marketplace-CzzdrUSK.js +0 -1
  349. package/build/assets/use-settings-BKpkUS4y.js +0 -1
  350. package/build/assets/use-settings-nav-items-BlXge_bf.js +0 -16
  351. package/build/assets/use-skills-BltA9XrV.js +0 -1
  352. package/build/assets/use-tracking-De7qByD4.js +0 -1
  353. package/build/assets/utils-qjs_KuS4.js +0 -1
  354. package/build/assets/x-EjvKGawc.js +0 -1
@@ -1,21 +1,21 @@
1
1
  import { getActiveBackend as e, getEffectiveLocalBackend as t } from "../backend-registry/active-store.js";
2
2
  import { NoBackendAvailableError as n } from "../agent-server-client-options.js";
3
3
  import r from "../../node_modules/axios/lib/axios.js";
4
- import { callCloudProxy as i } from "../cloud/proxy.js";
5
- import { AGENT_CANVAS_CLIENT_HEADERS as a, OPENHANDS_TELEMETRY_DISTINCT_ID_HEADER as o } from "../client-source.js";
6
- import { getTelemetryConsent as s, getTelemetryDistinctId as c, getTelemetryDistinctIdForConsentSync as l } from "../../services/telemetry.js";
4
+ import { AGENT_CANVAS_CLIENT_HEADERS as i, OPENHANDS_TELEMETRY_DISTINCT_ID_HEADER as a } from "../client-source.js";
5
+ import { clearPendingLocalTelemetryRevocation as o, getTelemetryConsent as s, getTelemetryDistinctId as c, getTelemetryDistinctIdForConsentSync as l } from "../../services/telemetry.js";
6
+ import { callCloudProxy as u } from "../cloud/proxy.js";
7
7
  //#region src/api/automation-service/automation-service.api.ts
8
- var u = "/api/automation", d = r.create();
9
- async function f(e = {}) {
8
+ var d = "/api/automation", f = r.create();
9
+ async function p(e = {}) {
10
10
  let t = await c();
11
11
  return {
12
- ...a,
13
- ...t ? { [o]: t } : {},
12
+ ...i,
13
+ ...t ? { [a]: t } : {},
14
14
  ...e
15
15
  };
16
16
  }
17
- d.interceptors.request.use(async (e) => {
18
- let r = await f();
17
+ f.interceptors.request.use(async (e) => {
18
+ let r = await p();
19
19
  if (Object.entries(r).forEach(([t, n]) => {
20
20
  e.headers.set(t, n);
21
21
  }), e.baseURL) return e;
@@ -25,17 +25,17 @@ d.interceptors.request.use(async (e) => {
25
25
  let a = i.apiKey?.trim();
26
26
  return a && e.headers.set("X-Session-API-Key", a), e;
27
27
  });
28
- function p(e) {
28
+ function m(e) {
29
29
  return typeof e == "string" && e.trim() || null;
30
30
  }
31
- function m(e) {
32
- return typeof e == "string" ? p(e) : p(e.sdk_version) ?? p(e.version);
31
+ function h(e) {
32
+ return typeof e == "string" ? m(e) : m(e.sdk_version) ?? m(e.version);
33
33
  }
34
- function h(e, t) {
34
+ function g(e, t) {
35
35
  let n = new URLSearchParams();
36
36
  return n.set("limit", String(e)), n.set("offset", String(t)), n.toString();
37
37
  }
38
- function g(e) {
38
+ function _(e) {
39
39
  return e.trigger.type === "event" ? {
40
40
  type: "event",
41
41
  source: e.trigger.source,
@@ -47,10 +47,10 @@ function g(e) {
47
47
  timezone: e.timezone ?? e.trigger.timezone ?? "UTC"
48
48
  };
49
49
  }
50
- function _() {
50
+ function v() {
51
51
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? `pending.${crypto.randomUUID()}` : `pending.${Date.now()}.${Math.random().toString(36).slice(2, 10)}`;
52
52
  }
53
- function v(e) {
53
+ function y(e) {
54
54
  if (!e.prompt) throw Error("An automation prompt is required for import.");
55
55
  let t = e.repository ? [{
56
56
  url: e.repository,
@@ -58,14 +58,14 @@ function v(e) {
58
58
  ...!e.repository.includes("://") && !e.repository.startsWith("git@") && { provider: "github" }
59
59
  }] : void 0;
60
60
  return {
61
- path: `${u}/v1/preset/${e.plugins?.length ? "plugin" : "prompt"}`,
61
+ path: `${d}/v1/preset/${e.plugins?.length ? "plugin" : "prompt"}`,
62
62
  body: {
63
63
  name: e.name,
64
64
  prompt: e.prompt,
65
65
  trigger: {
66
66
  type: "event",
67
67
  source: "agent-canvas-import",
68
- on: _()
68
+ on: v()
69
69
  },
70
70
  ...e.model && { model: e.model },
71
71
  ...t && { repos: t },
@@ -74,58 +74,58 @@ function v(e) {
74
74
  }
75
75
  };
76
76
  }
77
- async function y(e) {
77
+ async function b(e) {
78
78
  let t = e.apiKey.trim();
79
79
  return {
80
80
  baseURL: e.host,
81
- headers: await f(t ? { "X-Session-API-Key": t } : {})
81
+ headers: await p(t ? { "X-Session-API-Key": t } : {})
82
82
  };
83
83
  }
84
- async function b(e) {
85
- return f(e.orgId ? { "X-Org-Id": e.orgId } : {});
84
+ async function x(e) {
85
+ return p(e.orgId ? { "X-Org-Id": e.orgId } : {});
86
86
  }
87
- var x = class t {
87
+ var S = class t {
88
88
  static async syncTelemetryConsent(t = s()) {
89
89
  if (e().backend.kind !== "local") return;
90
90
  let n = await l();
91
- await d.post(`${u}/v1/telemetry/consent`, {
91
+ await f.post(`${d}/v1/telemetry/consent`, {
92
92
  consent_granted: t === "granted",
93
93
  frontend_distinct_id: n
94
- }, { timeout: 5e3 });
94
+ }, { timeout: 5e3 }), t !== "granted" && n && o(n);
95
95
  }
96
96
  static async getSdkVersion() {
97
- let t = e(), n = `${u}/sdk-version`;
97
+ let t = e(), n = `${d}/sdk-version`;
98
98
  try {
99
99
  let e;
100
- if (t.backend.kind === "cloud") e = await i({
100
+ if (t.backend.kind === "cloud") e = await u({
101
101
  backend: t.backend,
102
102
  method: "GET",
103
103
  path: n,
104
- headers: await b(t),
104
+ headers: await x(t),
105
105
  timeoutSeconds: 5
106
106
  });
107
107
  else {
108
- let { data: t } = await d.get(n, { timeout: 5e3 });
108
+ let { data: t } = await f.get(n, { timeout: 5e3 });
109
109
  e = t;
110
110
  }
111
- return m(e);
111
+ return h(e);
112
112
  } catch {
113
113
  return null;
114
114
  }
115
115
  }
116
116
  static async listAutomations(t = {}) {
117
- let { limit: n = 50, offset: r = 0 } = t, a = e().backend;
118
- if (a.kind === "cloud") return i({
119
- backend: a,
117
+ let { limit: n = 50, offset: r = 0 } = t, i = e().backend;
118
+ if (i.kind === "cloud") return u({
119
+ backend: i,
120
120
  method: "GET",
121
- path: `${u}/v1?${h(n, r)}`,
122
- headers: await f()
121
+ path: `${d}/v1?${g(n, r)}`,
122
+ headers: await p()
123
123
  });
124
- let { data: o } = await d.get(`${u}/v1`, { params: {
124
+ let { data: a } = await f.get(`${d}/v1`, { params: {
125
125
  limit: n,
126
126
  offset: r
127
127
  } });
128
- return o;
128
+ return a;
129
129
  }
130
130
  static async getAutomations(e = 50, n = 0) {
131
131
  return t.listAutomations({
@@ -134,51 +134,51 @@ var x = class t {
134
134
  });
135
135
  }
136
136
  static async getAutomation(t) {
137
- let n = e().backend, r = `${u}/v1/${encodeURIComponent(t)}`;
138
- if (n.kind === "cloud") return i({
137
+ let n = e().backend, r = `${d}/v1/${encodeURIComponent(t)}`;
138
+ if (n.kind === "cloud") return u({
139
139
  backend: n,
140
140
  method: "GET",
141
141
  path: r,
142
- headers: await f()
142
+ headers: await p()
143
143
  });
144
- let { data: a } = await d.get(r);
145
- return a;
144
+ let { data: i } = await f.get(r);
145
+ return i;
146
146
  }
147
147
  static async createAutomation(t) {
148
- let n = e(), { path: r, body: a } = v(t), o;
149
- if (n.backend.kind === "cloud") o = await i({
148
+ let n = e(), { path: r, body: i } = y(t), a;
149
+ if (n.backend.kind === "cloud") a = await u({
150
150
  backend: n.backend,
151
151
  method: "POST",
152
152
  path: r,
153
- body: a,
154
- headers: await b(n)
153
+ body: i,
154
+ headers: await x(n)
155
155
  });
156
156
  else {
157
- let { data: e } = await d.post(r, a, await y(n.backend));
158
- o = e;
157
+ let { data: e } = await f.post(r, i, await b(n.backend));
158
+ a = e;
159
159
  }
160
- let s = `${u}/v1/${encodeURIComponent(o.id)}`, c = {
161
- trigger: g(t),
160
+ let o = `${d}/v1/${encodeURIComponent(a.id)}`, s = {
161
+ trigger: _(t),
162
162
  enabled: !1
163
163
  };
164
164
  try {
165
- if (n.backend.kind === "cloud") return await i({
165
+ if (n.backend.kind === "cloud") return await u({
166
166
  backend: n.backend,
167
167
  method: "PATCH",
168
- path: s,
169
- body: c,
170
- headers: await b(n)
168
+ path: o,
169
+ body: s,
170
+ headers: await x(n)
171
171
  });
172
- let { data: e } = await d.patch(s, c, await y(n.backend));
172
+ let { data: e } = await f.patch(o, s, await b(n.backend));
173
173
  return e;
174
174
  } catch (e) {
175
175
  try {
176
- n.backend.kind === "cloud" ? await i({
176
+ n.backend.kind === "cloud" ? await u({
177
177
  backend: n.backend,
178
178
  method: "DELETE",
179
- path: s,
180
- headers: await b(n)
181
- }) : await d.delete(s, await y(n.backend));
179
+ path: o,
180
+ headers: await x(n)
181
+ }) : await f.delete(o, await b(n.backend));
182
182
  } catch (t) {
183
183
  throw AggregateError([e, t], "Failed to disable the imported automation and clean it up.");
184
184
  }
@@ -186,54 +186,54 @@ var x = class t {
186
186
  }
187
187
  }
188
188
  static async updateAutomation(t, n) {
189
- let r = e().backend, a = `${u}/v1/${encodeURIComponent(t)}`;
190
- if (r.kind === "cloud") return i({
189
+ let r = e().backend, i = `${d}/v1/${encodeURIComponent(t)}`;
190
+ if (r.kind === "cloud") return u({
191
191
  backend: r,
192
192
  method: "PATCH",
193
- path: a,
193
+ path: i,
194
194
  body: n,
195
- headers: await f()
195
+ headers: await p()
196
196
  });
197
- let { data: o } = await d.patch(a, n);
198
- return o;
197
+ let { data: a } = await f.patch(i, n);
198
+ return a;
199
199
  }
200
200
  static async deleteAutomation(t) {
201
- let n = e().backend, r = `${u}/v1/${encodeURIComponent(t)}`;
201
+ let n = e().backend, r = `${d}/v1/${encodeURIComponent(t)}`;
202
202
  if (n.kind === "cloud") {
203
- await i({
203
+ await u({
204
204
  backend: n,
205
205
  method: "DELETE",
206
206
  path: r,
207
- headers: await f()
207
+ headers: await p()
208
208
  });
209
209
  return;
210
210
  }
211
- await d.delete(r);
211
+ await f.delete(r);
212
212
  }
213
213
  static async dispatchAutomation(t) {
214
- let n = e().backend, r = `${u}/v1/${encodeURIComponent(t)}/dispatch`;
215
- if (n.kind === "cloud") return i({
214
+ let n = e().backend, r = `${d}/v1/${encodeURIComponent(t)}/dispatch`;
215
+ if (n.kind === "cloud") return u({
216
216
  backend: n,
217
217
  method: "POST",
218
218
  path: r,
219
- headers: await f()
219
+ headers: await p()
220
220
  });
221
- let { data: a } = await d.post(r);
222
- return a;
221
+ let { data: i } = await f.post(r);
222
+ return i;
223
223
  }
224
224
  static async listAutomationRuns(t, n = {}) {
225
- let { limit: r = 50, offset: a = 0 } = n, o = e().backend, s = `${u}/v1/${encodeURIComponent(t)}/runs`;
226
- if (o.kind === "cloud") return i({
227
- backend: o,
225
+ let { limit: r = 50, offset: i = 0 } = n, a = e().backend, o = `${d}/v1/${encodeURIComponent(t)}/runs`;
226
+ if (a.kind === "cloud") return u({
227
+ backend: a,
228
228
  method: "GET",
229
- path: `${s}?${h(r, a)}`,
230
- headers: await f()
229
+ path: `${o}?${g(r, i)}`,
230
+ headers: await p()
231
231
  });
232
- let { data: c } = await d.get(s, { params: {
232
+ let { data: s } = await f.get(o, { params: {
233
233
  limit: r,
234
- offset: a
234
+ offset: i
235
235
  } });
236
- return c;
236
+ return s;
237
237
  }
238
238
  static async getAutomationRuns(e, n = 50, r = 0) {
239
239
  return t.listAutomationRuns(e, {
@@ -245,32 +245,32 @@ var x = class t {
245
245
  return t.updateAutomation(e, { enabled: n });
246
246
  }
247
247
  static async downloadTarball(t, n) {
248
- let r = e().backend, a = `${u}/v1/${encodeURIComponent(t)}/tarball`, o;
249
- if (r.kind === "cloud") o = await i({
248
+ let r = e().backend, i = `${d}/v1/${encodeURIComponent(t)}/tarball`, a;
249
+ if (r.kind === "cloud") a = await u({
250
250
  backend: r,
251
251
  method: "GET",
252
- path: a,
252
+ path: i,
253
253
  responseType: "blob",
254
- headers: await f()
254
+ headers: await p()
255
255
  });
256
256
  else {
257
- let { data: e } = await d.get(a, { responseType: "blob" });
258
- o = e;
257
+ let { data: e } = await f.get(i, { responseType: "blob" });
258
+ a = e;
259
259
  }
260
- let s = URL.createObjectURL(o), c = document.createElement("a");
261
- c.href = s, c.download = `${n}.tar`, c.click(), URL.revokeObjectURL(s);
260
+ let o = URL.createObjectURL(a), s = document.createElement("a");
261
+ s.href = o, s.download = `${n}.tar`, s.click(), URL.revokeObjectURL(o);
262
262
  }
263
263
  static async checkHealth() {
264
- let t = e().backend, n = `${u}/health`;
264
+ let t = e().backend, n = `${d}/health`;
265
265
  try {
266
- if (t.kind === "cloud") return await i({
266
+ if (t.kind === "cloud") return await u({
267
267
  backend: t,
268
268
  method: "GET",
269
269
  path: n,
270
270
  timeoutSeconds: 5,
271
- headers: await f()
271
+ headers: await p()
272
272
  });
273
- let { data: e } = await d.get(n, { timeout: 5e3 });
273
+ let { data: e } = await f.get(n, { timeout: 5e3 });
274
274
  return e;
275
275
  } catch {
276
276
  return { status: "error" };
@@ -278,6 +278,6 @@ var x = class t {
278
278
  }
279
279
  };
280
280
  //#endregion
281
- export { x as default };
281
+ export { S as default };
282
282
 
283
283
  //# sourceMappingURL=automation-service.api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"automation-service.api.js","names":[],"sources":["../../../src/api/automation-service/automation-service.api.ts"],"sourcesContent":["import axios from \"axios\";\nimport {\n getTelemetryConsent,\n getTelemetryDistinctId,\n getTelemetryDistinctIdForConsentSync,\n type TelemetryConsent,\n} from \"#/services/telemetry\";\nimport type {\n Automation,\n AutomationRun,\n AutomationSpec,\n AutomationTrigger,\n AutomationsResponse,\n AutomationRunsResponse,\n} from \"#/types/automation\";\nimport type { Backend, ResolvedActiveBackend } from \"../backend-registry/types\";\nimport {\n getActiveBackend,\n getEffectiveLocalBackend,\n} from \"../backend-registry/active-store\";\nimport { NoBackendAvailableError } from \"../agent-server-client-options\";\nimport { callCloudProxy } from \"../cloud/proxy\";\nimport {\n AGENT_CANVAS_CLIENT_HEADERS,\n OPENHANDS_TELEMETRY_DISTINCT_ID_HEADER,\n} from \"../client-source\";\n\nconst AUTOMATION_BASE_PATH = \"/api/automation\";\n\nexport interface AutomationHealthResponse {\n status: \"ok\" | \"error\";\n message?: string;\n}\n\ntype AutomationSdkVersionResponse =\n | string\n | {\n sdk_version?: unknown;\n version?: unknown;\n };\n\n// Local automation calls go to the automation sidecar that\n// `scripts/dev-with-automation.mjs` mounts behind the local agent-server.\n// Both backends use the same session API key and the same `X-Session-API-Key`\n// header for consistency.\nconst localAutomationAxios = axios.create();\n\nasync function buildAutomationRequestHeaders(\n extraHeaders: Record<string, string> = {},\n): Promise<Record<string, string>> {\n const telemetryDistinctId = await getTelemetryDistinctId();\n return {\n ...AGENT_CANVAS_CLIENT_HEADERS,\n ...(telemetryDistinctId\n ? { [OPENHANDS_TELEMETRY_DISTINCT_ID_HEADER]: telemetryDistinctId }\n : {}),\n ...extraHeaders,\n };\n}\n\nlocalAutomationAxios.interceptors.request.use(async (config) => {\n const requestHeaders = await buildAutomationRequestHeaders();\n Object.entries(requestHeaders).forEach(([name, value]) => {\n config.headers.set(name, value);\n });\n\n // Import uses an explicit baseURL/header pair so its POST, PATCH, and\n // cleanup stay pinned to the backend selected when the mutation started.\n if (config.baseURL) return config;\n\n // Resolve the local backend on every call so it tracks the\n // currently-active local backend (and any host/key edits made via the\n // manage-backends UI), rather than freezing whatever value the\n // agent-server-config produced at module load time.\n // Using the backend registry (rather than the build-time VITE_SESSION_API_KEY\n // env var) ensures the published npm package picks up the runtime-injected\n // session key that scripts/static-server.mjs seeds into localStorage, fixing\n // the 401 errors reported in issue #829.\n const backend = getEffectiveLocalBackend();\n if (!backend) throw new NoBackendAvailableError();\n // eslint-disable-next-line no-param-reassign\n config.baseURL = backend.host;\n\n const apiKey = backend.apiKey?.trim();\n if (apiKey) {\n config.headers.set(\"X-Session-API-Key\", apiKey);\n }\n return config;\n});\n\nfunction normalizeAutomationSdkVersion(version: unknown): string | null {\n if (typeof version !== \"string\") return null;\n const trimmed = version.trim();\n return trimmed || null;\n}\n\nfunction getAutomationSdkVersionFromResponse(\n response: AutomationSdkVersionResponse,\n): string | null {\n if (typeof response === \"string\") {\n return normalizeAutomationSdkVersion(response);\n }\n return (\n normalizeAutomationSdkVersion(response.sdk_version) ??\n normalizeAutomationSdkVersion(response.version)\n );\n}\n\nfunction buildPaginationQuery(limit: number, offset: number): string {\n const params = new URLSearchParams();\n params.set(\"limit\", String(limit));\n params.set(\"offset\", String(offset));\n return params.toString();\n}\n\nfunction buildImportedTrigger(spec: AutomationSpec): AutomationTrigger {\n if (spec.trigger.type === \"event\") {\n return {\n type: \"event\",\n source: spec.trigger.source,\n on: spec.trigger.on,\n ...(spec.trigger.filter && { filter: spec.trigger.filter }),\n };\n }\n\n return {\n type: \"cron\",\n schedule: spec.trigger.schedule,\n timezone: spec.timezone ?? spec.trigger.timezone ?? \"UTC\",\n };\n}\n\nfunction generatePendingImportEvent(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return `pending.${crypto.randomUUID()}`;\n }\n return `pending.${Date.now()}.${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction buildCreateAutomationRequest(spec: AutomationSpec) {\n if (!spec.prompt) {\n throw new Error(\"An automation prompt is required for import.\");\n }\n\n const repos = spec.repository\n ? [\n {\n url: spec.repository,\n ...(spec.branch && { ref: spec.branch }),\n ...(!spec.repository.includes(\"://\") &&\n !spec.repository.startsWith(\"git@\") && { provider: \"github\" }),\n },\n ]\n : undefined;\n\n return {\n path: `${AUTOMATION_BASE_PATH}/v1/preset/${spec.plugins?.length ? \"plugin\" : \"prompt\"}`,\n body: {\n name: spec.name,\n prompt: spec.prompt,\n // Preset creation defaults to enabled. A unique event trigger keeps the\n // new record inert until the real trigger and disabled state are applied\n // together in the follow-up PATCH.\n trigger: {\n type: \"event\",\n source: \"agent-canvas-import\",\n on: generatePendingImportEvent(),\n },\n ...(spec.model && { model: spec.model }),\n ...(repos && { repos }),\n ...(spec.plugins?.length && {\n plugins: spec.plugins.map((source) => ({ source })),\n }),\n ...(spec.timeout != null && { timeout: spec.timeout }),\n },\n };\n}\n\nasync function buildPinnedLocalConfig(backend: Backend) {\n const apiKey = backend.apiKey.trim();\n return {\n baseURL: backend.host,\n headers: await buildAutomationRequestHeaders(\n apiKey ? { \"X-Session-API-Key\": apiKey } : {},\n ),\n };\n}\n\nasync function buildPinnedCloudHeaders(active: ResolvedActiveBackend) {\n return buildAutomationRequestHeaders(\n active.orgId ? { \"X-Org-Id\": active.orgId } : {},\n );\n}\n\nclass AutomationService {\n static async syncTelemetryConsent(\n consent: TelemetryConsent = getTelemetryConsent(),\n ): Promise<void> {\n const active = getActiveBackend();\n if (active.backend.kind !== \"local\") return;\n\n const frontendDistinctId = await getTelemetryDistinctIdForConsentSync();\n await localAutomationAxios.post(\n `${AUTOMATION_BASE_PATH}/v1/telemetry/consent`,\n {\n consent_granted: consent === \"granted\",\n frontend_distinct_id: frontendDistinctId,\n },\n { timeout: 5000 },\n );\n }\n\n static async getSdkVersion(): Promise<string | null> {\n const active = getActiveBackend();\n const path = `${AUTOMATION_BASE_PATH}/sdk-version`;\n\n try {\n let response: AutomationSdkVersionResponse;\n if (active.backend.kind === \"cloud\") {\n response = await callCloudProxy<AutomationSdkVersionResponse>({\n backend: active.backend,\n method: \"GET\",\n path,\n headers: await buildPinnedCloudHeaders(active),\n timeoutSeconds: 5,\n });\n } else {\n const { data } =\n await localAutomationAxios.get<AutomationSdkVersionResponse>(path, {\n timeout: 5000,\n });\n response = data;\n }\n\n return getAutomationSdkVersionFromResponse(response);\n } catch {\n return null;\n }\n }\n\n static async listAutomations(\n params: { limit?: number; offset?: number } = {},\n ): Promise<AutomationsResponse> {\n const { limit = 50, offset = 0 } = params;\n const active = getActiveBackend().backend;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<AutomationsResponse>({\n backend: active,\n method: \"GET\",\n path: `${AUTOMATION_BASE_PATH}/v1?${buildPaginationQuery(limit, offset)}`,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.get<AutomationsResponse>(\n `${AUTOMATION_BASE_PATH}/v1`,\n { params: { limit, offset } },\n );\n return data;\n }\n\n static async getAutomations(\n limit = 50,\n offset = 0,\n ): Promise<AutomationsResponse> {\n return AutomationService.listAutomations({ limit, offset });\n }\n\n static async getAutomation(id: string): Promise<Automation> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<Automation>({\n backend: active,\n method: \"GET\",\n path,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.get<Automation>(path);\n return data;\n }\n\n static async createAutomation(spec: AutomationSpec): Promise<Automation> {\n const active = getActiveBackend();\n const { path, body } = buildCreateAutomationRequest(spec);\n\n let created: Automation;\n if (active.backend.kind === \"cloud\") {\n created = await callCloudProxy<Automation>({\n backend: active.backend,\n method: \"POST\",\n path,\n body,\n headers: await buildPinnedCloudHeaders(active),\n });\n } else {\n const { data } = await localAutomationAxios.post<Automation>(\n path,\n body,\n await buildPinnedLocalConfig(active.backend),\n );\n created = data;\n }\n\n const updatePath = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(created.id)}`;\n const updateBody: Partial<Automation> = {\n trigger: buildImportedTrigger(spec),\n enabled: false,\n };\n\n try {\n if (active.backend.kind === \"cloud\") {\n return await callCloudProxy<Automation>({\n backend: active.backend,\n method: \"PATCH\",\n path: updatePath,\n body: updateBody,\n headers: await buildPinnedCloudHeaders(active),\n });\n }\n\n const { data } = await localAutomationAxios.patch<Automation>(\n updatePath,\n updateBody,\n await buildPinnedLocalConfig(active.backend),\n );\n return data;\n } catch (updateError) {\n try {\n if (active.backend.kind === \"cloud\") {\n await callCloudProxy<unknown>({\n backend: active.backend,\n method: \"DELETE\",\n path: updatePath,\n headers: await buildPinnedCloudHeaders(active),\n });\n } else {\n await localAutomationAxios.delete(\n updatePath,\n await buildPinnedLocalConfig(active.backend),\n );\n }\n } catch (cleanupError) {\n throw new AggregateError(\n [updateError, cleanupError],\n \"Failed to disable the imported automation and clean it up.\",\n );\n }\n throw updateError;\n }\n }\n\n static async updateAutomation(\n id: string,\n body: Partial<Automation>,\n ): Promise<Automation> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<Automation>({\n backend: active,\n method: \"PATCH\",\n path,\n body: body as Record<string, unknown>,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.patch<Automation>(path, body);\n return data;\n }\n\n static async deleteAutomation(id: string): Promise<void> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}`;\n\n if (active.kind === \"cloud\") {\n await callCloudProxy<unknown>({\n backend: active,\n method: \"DELETE\",\n path,\n headers: await buildAutomationRequestHeaders(),\n });\n return;\n }\n\n await localAutomationAxios.delete(path);\n }\n\n static async dispatchAutomation(id: string): Promise<AutomationRun> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}/dispatch`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<AutomationRun>({\n backend: active,\n method: \"POST\",\n path,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.post<AutomationRun>(path);\n return data;\n }\n\n static async listAutomationRuns(\n id: string,\n params: { limit?: number; offset?: number } = {},\n ): Promise<AutomationRunsResponse> {\n const { limit = 50, offset = 0 } = params;\n const active = getActiveBackend().backend;\n const basePath = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}/runs`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<AutomationRunsResponse>({\n backend: active,\n method: \"GET\",\n path: `${basePath}?${buildPaginationQuery(limit, offset)}`,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.get<AutomationRunsResponse>(\n basePath,\n { params: { limit, offset } },\n );\n return data;\n }\n\n static async getAutomationRuns(\n id: string,\n limit = 50,\n offset = 0,\n ): Promise<AutomationRunsResponse> {\n return AutomationService.listAutomationRuns(id, { limit, offset });\n }\n\n static async toggleAutomation(\n id: string,\n enabled: boolean,\n ): Promise<Automation> {\n return AutomationService.updateAutomation(id, { enabled });\n }\n\n static async downloadTarball(id: string, name: string): Promise<void> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}/tarball`;\n\n let blob: Blob;\n if (active.kind === \"cloud\") {\n blob = await callCloudProxy<Blob>({\n backend: active,\n method: \"GET\",\n path,\n responseType: \"blob\",\n headers: await buildAutomationRequestHeaders(),\n });\n } else {\n const { data } = await localAutomationAxios.get<Blob>(path, {\n responseType: \"blob\",\n });\n blob = data;\n }\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${name}.tar`;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n static async checkHealth(): Promise<AutomationHealthResponse> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/health`;\n\n try {\n if (active.kind === \"cloud\") {\n const response = await callCloudProxy<AutomationHealthResponse>({\n backend: active,\n method: \"GET\",\n path,\n // Fail fast, matching the local branch's 5s timeout below.\n timeoutSeconds: 5,\n headers: await buildAutomationRequestHeaders(),\n });\n return response;\n }\n\n const { data } = await localAutomationAxios.get<AutomationHealthResponse>(\n path,\n { timeout: 5000 },\n );\n return data;\n } catch {\n return { status: \"error\" };\n }\n }\n}\n\nexport default AutomationService;\n"],"mappings":"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"}
1
+ {"version":3,"file":"automation-service.api.js","names":[],"sources":["../../../src/api/automation-service/automation-service.api.ts"],"sourcesContent":["import axios from \"axios\";\nimport {\n clearPendingLocalTelemetryRevocation,\n getTelemetryConsent,\n getTelemetryDistinctId,\n getTelemetryDistinctIdForConsentSync,\n type TelemetryConsent,\n} from \"#/services/telemetry\";\nimport type {\n Automation,\n AutomationRun,\n AutomationSpec,\n AutomationTrigger,\n AutomationsResponse,\n AutomationRunsResponse,\n} from \"#/types/automation\";\nimport type { Backend, ResolvedActiveBackend } from \"../backend-registry/types\";\nimport {\n getActiveBackend,\n getEffectiveLocalBackend,\n} from \"../backend-registry/active-store\";\nimport { NoBackendAvailableError } from \"../agent-server-client-options\";\nimport { callCloudProxy } from \"../cloud/proxy\";\nimport {\n AGENT_CANVAS_CLIENT_HEADERS,\n OPENHANDS_TELEMETRY_DISTINCT_ID_HEADER,\n} from \"../client-source\";\n\nconst AUTOMATION_BASE_PATH = \"/api/automation\";\n\nexport interface AutomationHealthResponse {\n status: \"ok\" | \"error\";\n message?: string;\n}\n\ntype AutomationSdkVersionResponse =\n | string\n | {\n sdk_version?: unknown;\n version?: unknown;\n };\n\n// Local automation calls go to the automation sidecar that\n// `scripts/dev-with-automation.mjs` mounts behind the local agent-server.\n// Both backends use the same session API key and the same `X-Session-API-Key`\n// header for consistency.\nconst localAutomationAxios = axios.create();\n\nasync function buildAutomationRequestHeaders(\n extraHeaders: Record<string, string> = {},\n): Promise<Record<string, string>> {\n const telemetryDistinctId = await getTelemetryDistinctId();\n return {\n ...AGENT_CANVAS_CLIENT_HEADERS,\n ...(telemetryDistinctId\n ? { [OPENHANDS_TELEMETRY_DISTINCT_ID_HEADER]: telemetryDistinctId }\n : {}),\n ...extraHeaders,\n };\n}\n\nlocalAutomationAxios.interceptors.request.use(async (config) => {\n const requestHeaders = await buildAutomationRequestHeaders();\n Object.entries(requestHeaders).forEach(([name, value]) => {\n config.headers.set(name, value);\n });\n\n // Import uses an explicit baseURL/header pair so its POST, PATCH, and\n // cleanup stay pinned to the backend selected when the mutation started.\n if (config.baseURL) return config;\n\n // Resolve the local backend on every call so it tracks the\n // currently-active local backend (and any host/key edits made via the\n // manage-backends UI), rather than freezing whatever value the\n // agent-server-config produced at module load time.\n // Using the backend registry (rather than the build-time VITE_SESSION_API_KEY\n // env var) ensures the published npm package picks up the runtime-injected\n // session key that scripts/static-server.mjs seeds into localStorage, fixing\n // the 401 errors reported in issue #829.\n const backend = getEffectiveLocalBackend();\n if (!backend) throw new NoBackendAvailableError();\n // eslint-disable-next-line no-param-reassign\n config.baseURL = backend.host;\n\n const apiKey = backend.apiKey?.trim();\n if (apiKey) {\n config.headers.set(\"X-Session-API-Key\", apiKey);\n }\n return config;\n});\n\nfunction normalizeAutomationSdkVersion(version: unknown): string | null {\n if (typeof version !== \"string\") return null;\n const trimmed = version.trim();\n return trimmed || null;\n}\n\nfunction getAutomationSdkVersionFromResponse(\n response: AutomationSdkVersionResponse,\n): string | null {\n if (typeof response === \"string\") {\n return normalizeAutomationSdkVersion(response);\n }\n return (\n normalizeAutomationSdkVersion(response.sdk_version) ??\n normalizeAutomationSdkVersion(response.version)\n );\n}\n\nfunction buildPaginationQuery(limit: number, offset: number): string {\n const params = new URLSearchParams();\n params.set(\"limit\", String(limit));\n params.set(\"offset\", String(offset));\n return params.toString();\n}\n\nfunction buildImportedTrigger(spec: AutomationSpec): AutomationTrigger {\n if (spec.trigger.type === \"event\") {\n return {\n type: \"event\",\n source: spec.trigger.source,\n on: spec.trigger.on,\n ...(spec.trigger.filter && { filter: spec.trigger.filter }),\n };\n }\n\n return {\n type: \"cron\",\n schedule: spec.trigger.schedule,\n timezone: spec.timezone ?? spec.trigger.timezone ?? \"UTC\",\n };\n}\n\nfunction generatePendingImportEvent(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return `pending.${crypto.randomUUID()}`;\n }\n return `pending.${Date.now()}.${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction buildCreateAutomationRequest(spec: AutomationSpec) {\n if (!spec.prompt) {\n throw new Error(\"An automation prompt is required for import.\");\n }\n\n const repos = spec.repository\n ? [\n {\n url: spec.repository,\n ...(spec.branch && { ref: spec.branch }),\n ...(!spec.repository.includes(\"://\") &&\n !spec.repository.startsWith(\"git@\") && { provider: \"github\" }),\n },\n ]\n : undefined;\n\n return {\n path: `${AUTOMATION_BASE_PATH}/v1/preset/${spec.plugins?.length ? \"plugin\" : \"prompt\"}`,\n body: {\n name: spec.name,\n prompt: spec.prompt,\n // Preset creation defaults to enabled. A unique event trigger keeps the\n // new record inert until the real trigger and disabled state are applied\n // together in the follow-up PATCH.\n trigger: {\n type: \"event\",\n source: \"agent-canvas-import\",\n on: generatePendingImportEvent(),\n },\n ...(spec.model && { model: spec.model }),\n ...(repos && { repos }),\n ...(spec.plugins?.length && {\n plugins: spec.plugins.map((source) => ({ source })),\n }),\n ...(spec.timeout != null && { timeout: spec.timeout }),\n },\n };\n}\n\nasync function buildPinnedLocalConfig(backend: Backend) {\n const apiKey = backend.apiKey.trim();\n return {\n baseURL: backend.host,\n headers: await buildAutomationRequestHeaders(\n apiKey ? { \"X-Session-API-Key\": apiKey } : {},\n ),\n };\n}\n\nasync function buildPinnedCloudHeaders(active: ResolvedActiveBackend) {\n return buildAutomationRequestHeaders(\n active.orgId ? { \"X-Org-Id\": active.orgId } : {},\n );\n}\n\nclass AutomationService {\n static async syncTelemetryConsent(\n consent: TelemetryConsent = getTelemetryConsent(),\n ): Promise<void> {\n const active = getActiveBackend();\n if (active.backend.kind !== \"local\") return;\n\n const frontendDistinctId = await getTelemetryDistinctIdForConsentSync();\n await localAutomationAxios.post(\n `${AUTOMATION_BASE_PATH}/v1/telemetry/consent`,\n {\n consent_granted: consent === \"granted\",\n frontend_distinct_id: frontendDistinctId,\n },\n { timeout: 5000 },\n );\n if (consent !== \"granted\" && frontendDistinctId) {\n clearPendingLocalTelemetryRevocation(frontendDistinctId);\n }\n }\n\n static async getSdkVersion(): Promise<string | null> {\n const active = getActiveBackend();\n const path = `${AUTOMATION_BASE_PATH}/sdk-version`;\n\n try {\n let response: AutomationSdkVersionResponse;\n if (active.backend.kind === \"cloud\") {\n response = await callCloudProxy<AutomationSdkVersionResponse>({\n backend: active.backend,\n method: \"GET\",\n path,\n headers: await buildPinnedCloudHeaders(active),\n timeoutSeconds: 5,\n });\n } else {\n const { data } =\n await localAutomationAxios.get<AutomationSdkVersionResponse>(path, {\n timeout: 5000,\n });\n response = data;\n }\n\n return getAutomationSdkVersionFromResponse(response);\n } catch {\n return null;\n }\n }\n\n static async listAutomations(\n params: { limit?: number; offset?: number } = {},\n ): Promise<AutomationsResponse> {\n const { limit = 50, offset = 0 } = params;\n const active = getActiveBackend().backend;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<AutomationsResponse>({\n backend: active,\n method: \"GET\",\n path: `${AUTOMATION_BASE_PATH}/v1?${buildPaginationQuery(limit, offset)}`,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.get<AutomationsResponse>(\n `${AUTOMATION_BASE_PATH}/v1`,\n { params: { limit, offset } },\n );\n return data;\n }\n\n static async getAutomations(\n limit = 50,\n offset = 0,\n ): Promise<AutomationsResponse> {\n return AutomationService.listAutomations({ limit, offset });\n }\n\n static async getAutomation(id: string): Promise<Automation> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<Automation>({\n backend: active,\n method: \"GET\",\n path,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.get<Automation>(path);\n return data;\n }\n\n static async createAutomation(spec: AutomationSpec): Promise<Automation> {\n const active = getActiveBackend();\n const { path, body } = buildCreateAutomationRequest(spec);\n\n let created: Automation;\n if (active.backend.kind === \"cloud\") {\n created = await callCloudProxy<Automation>({\n backend: active.backend,\n method: \"POST\",\n path,\n body,\n headers: await buildPinnedCloudHeaders(active),\n });\n } else {\n const { data } = await localAutomationAxios.post<Automation>(\n path,\n body,\n await buildPinnedLocalConfig(active.backend),\n );\n created = data;\n }\n\n const updatePath = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(created.id)}`;\n const updateBody: Partial<Automation> = {\n trigger: buildImportedTrigger(spec),\n enabled: false,\n };\n\n try {\n if (active.backend.kind === \"cloud\") {\n return await callCloudProxy<Automation>({\n backend: active.backend,\n method: \"PATCH\",\n path: updatePath,\n body: updateBody,\n headers: await buildPinnedCloudHeaders(active),\n });\n }\n\n const { data } = await localAutomationAxios.patch<Automation>(\n updatePath,\n updateBody,\n await buildPinnedLocalConfig(active.backend),\n );\n return data;\n } catch (updateError) {\n try {\n if (active.backend.kind === \"cloud\") {\n await callCloudProxy<unknown>({\n backend: active.backend,\n method: \"DELETE\",\n path: updatePath,\n headers: await buildPinnedCloudHeaders(active),\n });\n } else {\n await localAutomationAxios.delete(\n updatePath,\n await buildPinnedLocalConfig(active.backend),\n );\n }\n } catch (cleanupError) {\n throw new AggregateError(\n [updateError, cleanupError],\n \"Failed to disable the imported automation and clean it up.\",\n );\n }\n throw updateError;\n }\n }\n\n static async updateAutomation(\n id: string,\n body: Partial<Automation>,\n ): Promise<Automation> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<Automation>({\n backend: active,\n method: \"PATCH\",\n path,\n body: body as Record<string, unknown>,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.patch<Automation>(path, body);\n return data;\n }\n\n static async deleteAutomation(id: string): Promise<void> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}`;\n\n if (active.kind === \"cloud\") {\n await callCloudProxy<unknown>({\n backend: active,\n method: \"DELETE\",\n path,\n headers: await buildAutomationRequestHeaders(),\n });\n return;\n }\n\n await localAutomationAxios.delete(path);\n }\n\n static async dispatchAutomation(id: string): Promise<AutomationRun> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}/dispatch`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<AutomationRun>({\n backend: active,\n method: \"POST\",\n path,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.post<AutomationRun>(path);\n return data;\n }\n\n static async listAutomationRuns(\n id: string,\n params: { limit?: number; offset?: number } = {},\n ): Promise<AutomationRunsResponse> {\n const { limit = 50, offset = 0 } = params;\n const active = getActiveBackend().backend;\n const basePath = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}/runs`;\n\n if (active.kind === \"cloud\") {\n return callCloudProxy<AutomationRunsResponse>({\n backend: active,\n method: \"GET\",\n path: `${basePath}?${buildPaginationQuery(limit, offset)}`,\n headers: await buildAutomationRequestHeaders(),\n });\n }\n\n const { data } = await localAutomationAxios.get<AutomationRunsResponse>(\n basePath,\n { params: { limit, offset } },\n );\n return data;\n }\n\n static async getAutomationRuns(\n id: string,\n limit = 50,\n offset = 0,\n ): Promise<AutomationRunsResponse> {\n return AutomationService.listAutomationRuns(id, { limit, offset });\n }\n\n static async toggleAutomation(\n id: string,\n enabled: boolean,\n ): Promise<Automation> {\n return AutomationService.updateAutomation(id, { enabled });\n }\n\n static async downloadTarball(id: string, name: string): Promise<void> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/v1/${encodeURIComponent(id)}/tarball`;\n\n let blob: Blob;\n if (active.kind === \"cloud\") {\n blob = await callCloudProxy<Blob>({\n backend: active,\n method: \"GET\",\n path,\n responseType: \"blob\",\n headers: await buildAutomationRequestHeaders(),\n });\n } else {\n const { data } = await localAutomationAxios.get<Blob>(path, {\n responseType: \"blob\",\n });\n blob = data;\n }\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${name}.tar`;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n static async checkHealth(): Promise<AutomationHealthResponse> {\n const active = getActiveBackend().backend;\n const path = `${AUTOMATION_BASE_PATH}/health`;\n\n try {\n if (active.kind === \"cloud\") {\n const response = await callCloudProxy<AutomationHealthResponse>({\n backend: active,\n method: \"GET\",\n path,\n // Fail fast, matching the local branch's 5s timeout below.\n timeoutSeconds: 5,\n headers: await buildAutomationRequestHeaders(),\n });\n return response;\n }\n\n const { data } = await localAutomationAxios.get<AutomationHealthResponse>(\n path,\n { timeout: 5000 },\n );\n return data;\n } catch {\n return { status: \"error\" };\n }\n }\n}\n\nexport default AutomationService;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../_virtual/_rolldown/runtime.cjs");const e=require("./default-backend.cjs");var t=`openhands-backends`,n=`openhands-active-backend`;function r(e){return e===`local`||e===`cloud`}function i(e){return e===void 0||e===`api-key`||e===`cookie`}function a(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.id==`string`&&t.id.length>0&&typeof t.name==`string`&&typeof t.host==`string`&&typeof t.apiKey==`string`&&r(t.kind)&&i(t.authMode)}function o(e){try{let{hostname:t}=new URL(e);return t===`localhost`||t===`127.0.0.1`||t===`::1`||t===`[::1]`}catch{return!1}}function s(e,t){return e.id!==`default-local`||e.kind!==`local`?!1:e.host===t.host||o(e.host)&&o(t.host)}function c(t){let n=e.makeDefaultLocalBackend();if(!n)return t;let r=!1,i=t.map(e=>!s(e,n)||e.apiKey===n.apiKey?e:(r=!0,{...e,apiKey:n.apiKey}));return r?(l(i),i):t}function l(e){if(!(typeof window>`u`))try{window.localStorage.setItem(t,JSON.stringify(e))}catch{}}function u(){if(typeof window>`u`)return[];try{let n=e.makeLockedCloudBackend();if(n)return l([n]),h()?.backendId!==n.id&&g({backendId:n.id}),[n];let r=window.localStorage.getItem(t);if(r===null){let t=e.makeDefaultLocalBackend();return t?(l([t]),[t]):[]}let i=JSON.parse(r);if(!Array.isArray(i))return[];let o=i.filter(a);if(o.length===0){let t=e.makeDefaultLocalBackend();return t?(l([t]),[t]):[]}return c(o)}catch{return[]}}function d(e){if(!e)return null;try{let t=JSON.parse(e);if(typeof t!=`object`||!t||typeof t.backendId!=`string`)return null;let n=t.orgId;return{backendId:t.backendId,orgId:typeof n==`string`&&n.length>0?n:null}}catch{return null}}function f(e,t){try{return e?.getItem(t)??null}catch{return null}}function p(e,t,n){try{e?.setItem(t,n)}catch{}}function m(e,t){try{e?.removeItem(t)}catch{}}function h(){return typeof window>`u`?null:d(f(window.sessionStorage,n))||d(f(window.localStorage,n))}function g(e){if(typeof window>`u`)return;if(!e){m(window.sessionStorage,n),m(window.localStorage,n);return}let t=JSON.stringify({backendId:e.backendId,orgId:e.orgId??null});p(window.sessionStorage,n,t),p(window.localStorage,n,t)}exports.readStoredActiveBackend=h,exports.readStoredBackends=u,exports.writeStoredActiveBackend=g,exports.writeStoredBackends=l;
1
+ require("../../_virtual/_rolldown/runtime.cjs");const e=require("./default-backend.cjs");var t=`openhands-backends`,n=`openhands-active-backend`;function r(e){return e===`local`||e===`cloud`}function i(e){return e===void 0||e===`api-key`||e===`cookie`}function a(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.id==`string`&&t.id.length>0&&typeof t.name==`string`&&typeof t.host==`string`&&typeof t.apiKey==`string`&&r(t.kind)&&i(t.authMode)&&(t.connectionRevision===void 0||typeof t.connectionRevision==`number`&&Number.isSafeInteger(t.connectionRevision)&&t.connectionRevision>=0)}function o(e){try{let{hostname:t}=new URL(e);return t===`localhost`||t===`127.0.0.1`||t===`::1`||t===`[::1]`}catch{return!1}}function s(e,t){return e.id!==`default-local`||e.kind!==`local`?!1:e.host===t.host||o(e.host)&&o(t.host)}function c(t){let n=e.makeDefaultLocalBackend();if(!n)return t;let r=!1,i=t.map(e=>!s(e,n)||e.apiKey===n.apiKey?e:(r=!0,{...e,apiKey:n.apiKey}));return r?(l(i),i):t}function l(e){if(!(typeof window>`u`))try{window.localStorage.setItem(t,JSON.stringify(e))}catch{}}function u(){if(typeof window>`u`)return[];try{let n=e.makeLockedCloudBackend();if(n)return l([n]),h()?.backendId!==n.id&&g({backendId:n.id}),[n];let r=window.localStorage.getItem(t);if(r===null){let t=e.makeDefaultLocalBackend();return t?(l([t]),[t]):[]}let i=JSON.parse(r);if(!Array.isArray(i))return[];let o=i.filter(a);if(o.length===0){let t=e.makeDefaultLocalBackend();return t?(l([t]),[t]):[]}return c(o)}catch{return[]}}function d(e){if(!e)return null;try{let t=JSON.parse(e);if(typeof t!=`object`||!t||typeof t.backendId!=`string`)return null;let n=t.orgId;return{backendId:t.backendId,orgId:typeof n==`string`&&n.length>0?n:null}}catch{return null}}function f(e,t){try{return e?.getItem(t)??null}catch{return null}}function p(e,t,n){try{e?.setItem(t,n)}catch{}}function m(e,t){try{e?.removeItem(t)}catch{}}function h(){return typeof window>`u`?null:d(f(window.sessionStorage,n))||d(f(window.localStorage,n))}function g(e){if(typeof window>`u`)return;if(!e){m(window.sessionStorage,n),m(window.localStorage,n);return}let t=JSON.stringify({backendId:e.backendId,orgId:e.orgId??null});p(window.sessionStorage,n,t),p(window.localStorage,n,t)}exports.readStoredActiveBackend=h,exports.readStoredBackends=u,exports.writeStoredActiveBackend=g,exports.writeStoredBackends=l;
2
2
  //# sourceMappingURL=storage.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.cjs","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode)\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"storage.cjs","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode) &&\n (v.connectionRevision === undefined ||\n (typeof v.connectionRevision === \"number\" &&\n Number.isSafeInteger(v.connectionRevision) &&\n v.connectionRevision >= 0))\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":"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"}
@@ -10,7 +10,7 @@ function a(e) {
10
10
  function o(e) {
11
11
  if (typeof e != "object" || !e) return !1;
12
12
  let t = e;
13
- return typeof t.id == "string" && t.id.length > 0 && typeof t.name == "string" && typeof t.host == "string" && typeof t.apiKey == "string" && i(t.kind) && a(t.authMode);
13
+ return typeof t.id == "string" && t.id.length > 0 && typeof t.name == "string" && typeof t.host == "string" && typeof t.apiKey == "string" && i(t.kind) && a(t.authMode) && (t.connectionRevision === void 0 || typeof t.connectionRevision == "number" && Number.isSafeInteger(t.connectionRevision) && t.connectionRevision >= 0);
14
14
  }
15
15
  function s(e) {
16
16
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode)\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":";;AAYA,IAAa,IAAuB,sBACvB,IAA6B;AAE1C,SAAS,EAAY,GAAsC;CACzD,OAAO,MAAU,WAAW,MAAU;AACxC;AAEA,SAAS,EAAgB,GAA0C;CACjE,OAAO,MAAU,KAAA,KAAa,MAAU,aAAa,MAAU;AACjE;AAEA,SAAS,EAAe,GAAkC;CACxD,IAAI,OAAO,KAAU,aAAY,GAAgB,OAAO;CACxD,IAAM,IAAI;CACV,OACE,OAAO,EAAE,MAAO,YAChB,EAAE,GAAG,SAAS,KACd,OAAO,EAAE,QAAS,YAClB,OAAO,EAAE,QAAS,YAClB,OAAO,EAAE,UAAW,YACpB,EAAY,EAAE,IAAI,KAClB,EAAgB,EAAE,QAAQ;AAE9B;AAEA,SAAS,EAAc,GAAwB;CAC7C,IAAI;EACF,IAAM,EAAE,gBAAa,IAAI,IAAI,CAAK;EAClC,OACE,MAAa,eACb,MAAa,eACb,MAAa,SACb,MAAa;CAEjB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,EACP,GACA,GACS;CAKT,OAJI,EAAQ,OAAA,mBAAoC,EAAQ,SAAS,UACxD,KAIP,EAAQ,SAAS,EAAe,QAC/B,EAAc,EAAQ,IAAI,KAAK,EAAc,EAAe,IAAI;AAErE;AAEA,SAAS,EAAgC,GAAgC;CACvE,IAAM,IAAiB,EAAwB;CAC/C,IAAI,CAAC,GAAgB,OAAO;CAE5B,IAAI,IAAU,IACR,IAAiB,EAAS,KAAK,MAC/B,CAAC,EAAsC,GAAS,CAAc,KAI9D,EAAQ,WAAW,EAAe,SAAe,KAErD,IAAU,IACH;EACL,GAAG;EACH,QAAQ,EAAe;CACzB,EACD;CAKD,OAHK,KAEL,EAAoB,CAAc,GAC3B,KAHc;AAIvB;AAEA,SAAgB,EAAoB,GAA2B;CACzD,aAAO,SAAW,MACtB,IAAI;EACF,OAAO,aAAa,QAAQ,GAAsB,KAAK,UAAU,CAAQ,CAAC;CAC5E,QAAQ,CAER;AACF;AAEA,SAAgB,IAAgC;CAC9C,IAAI,OAAO,SAAW,KAAa,OAAO,CAAC;CAE3C,IAAI;EACF,IAAM,IAAqB,EAAuB;EAClD,IAAI,GAMF,OALA,EAAoB,CAAC,CAAkB,CAAC,GAChB,EACpB,GAAiB,cAAc,EAAmB,MACpD,EAAyB,EAAE,WAAW,EAAmB,GAAG,CAAC,GAExD,CAAC,CAAkB;EAG5B,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAoB;EAI5D,IAAI,MAAQ,MAAM;GAChB,IAAM,IAAiB,EAAwB;GAI/C,OAHK,KAEL,EAAoB,CAAC,CAAc,CAAC,GAC7B,CAAC,CAAc,KAHM,CAAC;EAI/B;EAEA,IAAM,IAAS,KAAK,MAAM,CAAG;EAC7B,IAAI,CAAC,MAAM,QAAQ,CAAM,GAAG,OAAO,CAAC;EACpC,IAAM,IAAQ,EAAO,OAAO,CAAc;EAI1C,IAAI,EAAM,WAAW,GAAG;GACtB,IAAM,IAAiB,EAAwB;GAI/C,OAHK,KAEL,EAAoB,CAAC,CAAc,CAAC,GAC7B,CAAC,CAAc,KAHM,CAAC;EAI/B;EAGA,OADe,EAAgC,CACxC;CACT,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,EAAsB,GAA6C;CAC1E,IAAI,CAAC,GAAK,OAAO;CAEjB,IAAI;EACF,IAAM,IAAS,KAAK,MAAM,CAAG;EAC7B,IACE,OAAO,KAAW,aAClB,KACA,OAAQ,EAA4B,aAAc,UAElD,OAAO;EAET,IAAM,IAAY,EAA4B;EAC9C,OAAO;GACL,WAAY,EAA4B;GACxC,OACE,OAAO,KAAa,YAAY,EAAS,SAAS,IAAI,IAAW;EACrE;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,EACP,GACA,GACe;CACf,IAAI;EACF,OAAO,GAAS,QAAQ,CAAG,KAAK;CAClC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,EACP,GACA,GACA,GACM;CACN,IAAI;EACF,GAAS,QAAQ,GAAK,CAAK;CAC7B,QAAQ,CAER;AACF;AAEA,SAAS,EAAkB,GAA8B,GAAmB;CAC1E,IAAI;EACF,GAAS,WAAW,CAAG;CACzB,QAAQ,CAER;AACF;AAEA,SAAgB,IAAmD;CAWjE,OAVI,OAAO,SAAW,MAAoB,OAKjB,EACvB,EAAgB,OAAO,gBAAgB,CAA0B,CAE/D,KAEG,EACL,EAAgB,OAAO,cAAc,CAA0B,CACjE;AACF;AAEA,SAAgB,EACd,GACM;CACN,IAAI,OAAO,SAAW,KAAa;CAEnC,IAAI,CAAC,GAAW;EAEd,AADA,EAAkB,OAAO,gBAAgB,CAA0B,GACnE,EAAkB,OAAO,cAAc,CAA0B;EACjE;CACF;CAEA,IAAM,IAAa,KAAK,UAAU;EAChC,WAAW,EAAU;EACrB,OAAO,EAAU,SAAS;CAC5B,CAAC;CAQD,AALA,EACE,OAAO,gBACP,GACA,CACF,GACA,EAAiB,OAAO,cAAc,GAA4B,CAAU;AAC9E"}
1
+ {"version":3,"file":"storage.js","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode) &&\n (v.connectionRevision === undefined ||\n (typeof v.connectionRevision === \"number\" &&\n Number.isSafeInteger(v.connectionRevision) &&\n v.connectionRevision >= 0))\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":";;AAYA,IAAa,IAAuB,sBACvB,IAA6B;AAE1C,SAAS,EAAY,GAAsC;CACzD,OAAO,MAAU,WAAW,MAAU;AACxC;AAEA,SAAS,EAAgB,GAA0C;CACjE,OAAO,MAAU,KAAA,KAAa,MAAU,aAAa,MAAU;AACjE;AAEA,SAAS,EAAe,GAAkC;CACxD,IAAI,OAAO,KAAU,aAAY,GAAgB,OAAO;CACxD,IAAM,IAAI;CACV,OACE,OAAO,EAAE,MAAO,YAChB,EAAE,GAAG,SAAS,KACd,OAAO,EAAE,QAAS,YAClB,OAAO,EAAE,QAAS,YAClB,OAAO,EAAE,UAAW,YACpB,EAAY,EAAE,IAAI,KAClB,EAAgB,EAAE,QAAQ,MACzB,EAAE,uBAAuB,KAAA,KACvB,OAAO,EAAE,sBAAuB,YAC/B,OAAO,cAAc,EAAE,kBAAkB,KACzC,EAAE,sBAAsB;AAEhC;AAEA,SAAS,EAAc,GAAwB;CAC7C,IAAI;EACF,IAAM,EAAE,gBAAa,IAAI,IAAI,CAAK;EAClC,OACE,MAAa,eACb,MAAa,eACb,MAAa,SACb,MAAa;CAEjB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,EACP,GACA,GACS;CAKT,OAJI,EAAQ,OAAA,mBAAoC,EAAQ,SAAS,UACxD,KAIP,EAAQ,SAAS,EAAe,QAC/B,EAAc,EAAQ,IAAI,KAAK,EAAc,EAAe,IAAI;AAErE;AAEA,SAAS,EAAgC,GAAgC;CACvE,IAAM,IAAiB,EAAwB;CAC/C,IAAI,CAAC,GAAgB,OAAO;CAE5B,IAAI,IAAU,IACR,IAAiB,EAAS,KAAK,MAC/B,CAAC,EAAsC,GAAS,CAAc,KAI9D,EAAQ,WAAW,EAAe,SAAe,KAErD,IAAU,IACH;EACL,GAAG;EACH,QAAQ,EAAe;CACzB,EACD;CAKD,OAHK,KAEL,EAAoB,CAAc,GAC3B,KAHc;AAIvB;AAEA,SAAgB,EAAoB,GAA2B;CACzD,aAAO,SAAW,MACtB,IAAI;EACF,OAAO,aAAa,QAAQ,GAAsB,KAAK,UAAU,CAAQ,CAAC;CAC5E,QAAQ,CAER;AACF;AAEA,SAAgB,IAAgC;CAC9C,IAAI,OAAO,SAAW,KAAa,OAAO,CAAC;CAE3C,IAAI;EACF,IAAM,IAAqB,EAAuB;EAClD,IAAI,GAMF,OALA,EAAoB,CAAC,CAAkB,CAAC,GAChB,EACpB,GAAiB,cAAc,EAAmB,MACpD,EAAyB,EAAE,WAAW,EAAmB,GAAG,CAAC,GAExD,CAAC,CAAkB;EAG5B,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAoB;EAI5D,IAAI,MAAQ,MAAM;GAChB,IAAM,IAAiB,EAAwB;GAI/C,OAHK,KAEL,EAAoB,CAAC,CAAc,CAAC,GAC7B,CAAC,CAAc,KAHM,CAAC;EAI/B;EAEA,IAAM,IAAS,KAAK,MAAM,CAAG;EAC7B,IAAI,CAAC,MAAM,QAAQ,CAAM,GAAG,OAAO,CAAC;EACpC,IAAM,IAAQ,EAAO,OAAO,CAAc;EAI1C,IAAI,EAAM,WAAW,GAAG;GACtB,IAAM,IAAiB,EAAwB;GAI/C,OAHK,KAEL,EAAoB,CAAC,CAAc,CAAC,GAC7B,CAAC,CAAc,KAHM,CAAC;EAI/B;EAGA,OADe,EAAgC,CACxC;CACT,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,EAAsB,GAA6C;CAC1E,IAAI,CAAC,GAAK,OAAO;CAEjB,IAAI;EACF,IAAM,IAAS,KAAK,MAAM,CAAG;EAC7B,IACE,OAAO,KAAW,aAClB,KACA,OAAQ,EAA4B,aAAc,UAElD,OAAO;EAET,IAAM,IAAY,EAA4B;EAC9C,OAAO;GACL,WAAY,EAA4B;GACxC,OACE,OAAO,KAAa,YAAY,EAAS,SAAS,IAAI,IAAW;EACrE;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,EACP,GACA,GACe;CACf,IAAI;EACF,OAAO,GAAS,QAAQ,CAAG,KAAK;CAClC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,EACP,GACA,GACA,GACM;CACN,IAAI;EACF,GAAS,QAAQ,GAAK,CAAK;CAC7B,QAAQ,CAER;AACF;AAEA,SAAS,EAAkB,GAA8B,GAAmB;CAC1E,IAAI;EACF,GAAS,WAAW,CAAG;CACzB,QAAQ,CAER;AACF;AAEA,SAAgB,IAAmD;CAWjE,OAVI,OAAO,SAAW,MAAoB,OAKjB,EACvB,EAAgB,OAAO,gBAAgB,CAA0B,CAE/D,KAEG,EACL,EAAgB,OAAO,cAAc,CAA0B,CACjE;AACF;AAEA,SAAgB,EACd,GACM;CACN,IAAI,OAAO,SAAW,KAAa;CAEnC,IAAI,CAAC,GAAW;EAEd,AADA,EAAkB,OAAO,gBAAgB,CAA0B,GACnE,EAAkB,OAAO,cAAc,CAA0B;EACjE;CACF;CAEA,IAAM,IAAa,KAAK,UAAU;EAChC,WAAW,EAAU;EACrB,OAAO,EAAU,SAAS;CAC5B,CAAC;CAQD,AALA,EACE,OAAO,gBACP,GACA,CACF,GACA,EAAiB,OAAO,cAAc,GAA4B,CAAU;AAC9E"}
@@ -7,6 +7,8 @@ export interface Backend {
7
7
  apiKey: string;
8
8
  kind: BackendKind;
9
9
  authMode?: BackendAuthMode;
10
+ /** Changes whenever connection credentials change, invalidating keyed data. */
11
+ connectionRevision?: number;
10
12
  }
11
13
  export interface BackendSelection {
12
14
  backendId: string;
@@ -1,2 +1,2 @@
1
- require("../../_virtual/_rolldown/runtime.cjs");const e=require("../backend-registry/active-store.cjs"),t=require("./proxy.cjs"),n=require("../client-source.cjs"),r=require("../conversation-metadata-store.cjs");function i(e){if(!e?.id)return e;let t=r.getStoredConversationMetadata(e.id);return t?{...e,selected_repository:e.selected_repository??t.selected_repository??null,selected_branch:e.selected_branch??t.selected_branch??null,git_provider:e.git_provider??t.git_provider??null,selected_workspace:e.selected_workspace??t.selected_workspace??null}:e}function a(){let t=e.getActiveBackend().backend;if(t.kind!==`cloud`)throw Error(`Cloud conversations call requires a cloud backend.`);return t}async function o(e=20,n){let r=a(),o=new URLSearchParams;o.set(`limit`,String(e)),n&&o.set(`page_id`,n),o.set(`sort_order`,`UPDATED_AT_DESC`);let s=await t.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/search?${o.toString()}`});return{items:(s?.items??[]).map(e=>i(e)),next_page_id:s?.next_page_id??null}}async function s(e){if(e.length===0)return[];let n=a(),r=new URLSearchParams;for(let t of e)r.append(`ids`,t);return(await t.callCloudProxy({backend:n,method:`GET`,path:`/api/v1/app-conversations?${r.toString()}`})??[]).map(i)}async function c(e){return await t.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/app-conversations`,body:e,headers:n.AGENT_CANVAS_CLIENT_HEADERS})}async function l(e){return t.callCloudProxy({backend:a(),method:`GET`,path:`/api/v1/app-conversations/${e}/download`,responseType:`blob`})}async function u(e){await t.callCloudProxy({backend:a(),method:`DELETE`,path:`/api/v1/app-conversations/${e}`})}async function d(e,n){return await t.callCloudProxy({backend:a(),method:`PATCH`,path:`/api/v1/app-conversations/${e}`,body:{public:n}})}async function f(e){await t.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/pause`})}async function p(e){await t.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/resume`})}async function m(e,n){let r=a(),i=new URLSearchParams;return i.append(`file_path`,n),await t.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/${e}/file?${i.toString()}`})??``}async function h(e){let n=a(),r=new URLSearchParams;return r.set(`ids`,e),(await t.callCloudProxy({backend:n,method:`GET`,path:`/api/v1/app-conversations/start-tasks?${r.toString()}`}))?.[0]??null}exports.batchGetCloudConversations=s,exports.createCloudAppConversation=c,exports.deleteCloudConversation=u,exports.downloadCloudConversation=l,exports.getCloudAppConversationStartTask=h,exports.pauseCloudSandbox=f,exports.readCloudConversationFile=m,exports.resumeCloudSandbox=p,exports.searchCloudConversations=o,exports.updateCloudConversationPublicFlag=d;
1
+ require("../../_virtual/_rolldown/runtime.cjs");const e=require("../backend-registry/active-store.cjs"),t=require("../client-source.cjs"),n=require("./proxy.cjs"),r=require("../conversation-metadata-store.cjs");function i(e){if(!e?.id)return e;let t=r.getStoredConversationMetadata(e.id);return t?{...e,selected_repository:e.selected_repository??t.selected_repository??null,selected_branch:e.selected_branch??t.selected_branch??null,git_provider:e.git_provider??t.git_provider??null,selected_workspace:e.selected_workspace??t.selected_workspace??null}:e}function a(){let t=e.getActiveBackend().backend;if(t.kind!==`cloud`)throw Error(`Cloud conversations call requires a cloud backend.`);return t}async function o(e=20,t){let r=a(),o=new URLSearchParams;o.set(`limit`,String(e)),t&&o.set(`page_id`,t),o.set(`sort_order`,`UPDATED_AT_DESC`);let s=await n.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/search?${o.toString()}`});return{items:(s?.items??[]).map(e=>i(e)),next_page_id:s?.next_page_id??null}}async function s(e){if(e.length===0)return[];let t=a(),r=new URLSearchParams;for(let t of e)r.append(`ids`,t);return(await n.callCloudProxy({backend:t,method:`GET`,path:`/api/v1/app-conversations?${r.toString()}`})??[]).map(i)}async function c(e){return await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/app-conversations`,body:e,headers:t.AGENT_CANVAS_CLIENT_HEADERS})}async function l(e){return n.callCloudProxy({backend:a(),method:`GET`,path:`/api/v1/app-conversations/${e}/download`,responseType:`blob`})}async function u(e){await n.callCloudProxy({backend:a(),method:`DELETE`,path:`/api/v1/app-conversations/${e}`})}async function d(e,t){return await n.callCloudProxy({backend:a(),method:`PATCH`,path:`/api/v1/app-conversations/${e}`,body:{public:t}})}async function f(e){await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/pause`})}async function p(e){await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/resume`})}async function m(e,t){let r=a(),i=new URLSearchParams;return i.append(`file_path`,t),await n.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/${e}/file?${i.toString()}`})??``}async function h(e){let t=a(),r=new URLSearchParams;return r.set(`ids`,e),(await n.callCloudProxy({backend:t,method:`GET`,path:`/api/v1/app-conversations/start-tasks?${r.toString()}`}))?.[0]??null}exports.batchGetCloudConversations=s,exports.createCloudAppConversation=c,exports.deleteCloudConversation=u,exports.downloadCloudConversation=l,exports.getCloudAppConversationStartTask=h,exports.pauseCloudSandbox=f,exports.readCloudConversationFile=m,exports.resumeCloudSandbox=p,exports.searchCloudConversations=o,exports.updateCloudConversationPublicFlag=d;
2
2
  //# sourceMappingURL=conversation-service.api.cjs.map