@openhands/agent-canvas 1.0.0-alpha.9 → 1.0.0-beta.2

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 (370) hide show
  1. package/README.md +2 -2
  2. package/bin/agent-canvas.mjs +22 -2
  3. package/build/assets/{QueryClientProvider-B7kl84Kj.js → QueryClientProvider-CkGuhXg-.js} +1 -1
  4. package/build/assets/{Trans-1j65oy9O.js → Trans-Cvm_-SMi.js} +1 -1
  5. package/build/assets/acp-providers-CbiRekh9.js +1 -0
  6. package/build/assets/{acp-route-guard-CQTmeJwM.js → acp-route-guard-B2yoBZ_4.js} +1 -1
  7. package/build/assets/{active-backend-context-TVbjnvmP.js → active-backend-context-cCM1vYYZ.js} +1 -1
  8. package/build/assets/add-backend-modal-DIUQzMPa.js +1 -0
  9. package/build/assets/agent-server-client-options-Bc5ZorQZ.js +1 -0
  10. package/build/assets/agent-server-compatibility-BlkUsrX2.js +1 -0
  11. package/build/assets/agent-server-conversation-service.api-DFvqqEDo.js +5 -0
  12. package/build/assets/{agent-settings-B247S9G3.js → agent-settings-CnGSCmK8.js} +1 -1
  13. package/build/assets/{alert-banner-BWoqueRw.js → alert-banner-DtzAX654.js} +1 -1
  14. package/build/assets/{analytics-consent-form-modal-C7sXfxRh.js → analytics-consent-form-modal-CHZ3I37v.js} +1 -1
  15. package/build/assets/api-key-entry-screen-B2gynaCp.js +1 -0
  16. package/build/assets/{app-settings-BVeSaty9.js → app-settings-Db9ITeJH.js} +1 -1
  17. package/build/assets/{automation-detail-R-99FUce.js → automation-detail-Di7EOIZD.js} +1 -1
  18. package/build/assets/{automations-list-Dfu2c-_D.js → automations-list-IsIWdDiw.js} +1 -1
  19. package/build/assets/{backend-form-modal-DxYjqqAK.js → backend-form-modal-Dnk33xA_.js} +1 -1
  20. package/build/assets/{backend-synced-settings-badge-nAfiUWvM.js → backend-synced-settings-badge-Dc6c7GT4.js} +1 -1
  21. package/build/assets/{base-modal-CQRvRHu1.js → base-modal-_dYTw1ri.js} +1 -1
  22. package/build/assets/{brand-button-C2nEKopC.js → brand-button-Br7f0kZJ.js} +1 -1
  23. package/build/assets/{browser-HrYc5Gce.js → browser-D810xUYt.js} +2 -2
  24. package/build/assets/browser-store-Couc4S5D.js +1 -0
  25. package/build/assets/browser-tab-B-aIqXRl.js +1 -0
  26. package/build/assets/{checkmark-BJJrZUF8.js → checkmark-DL7acQA7.js} +1 -1
  27. package/build/assets/{chevron-left-small-CSh-sE9L.js → chevron-left-small-CVWf8TI6.js} +1 -1
  28. package/build/assets/{circle-plus-check-toggle-qs8Va1cC.js → circle-plus-check-toggle-P7ZZToV4.js} +1 -1
  29. package/build/assets/{clock-ZR4Kn-_Y.js → clock-BRjCgHTc.js} +1 -1
  30. package/build/assets/{close-BdmyeRqS.js → close-B5LROHR3.js} +1 -1
  31. package/build/assets/{combobox-caret-B53O9Hsq.js → combobox-caret-to1O8irE.js} +1 -1
  32. package/build/assets/{condenser-settings-A35V3yng.js → condenser-settings-wnEKhBof.js} +1 -1
  33. package/build/assets/{confirmation-modal-C9-La0h3.js → confirmation-modal-Dau3w_sa.js} +1 -1
  34. package/build/assets/{context-menu-list-item-Buu9nc0q.js → context-menu-list-item-CWNFpuiC.js} +1 -1
  35. package/build/assets/conversation-HlncOV7n.js +19 -0
  36. package/build/assets/conversation-MtnkpqA9.js +1 -0
  37. package/build/assets/conversation-panel-DxnM6tRe.js +1 -0
  38. package/build/assets/{conversation-service.api--f8WglOC.js → conversation-service.api-nb5W1PqR.js} +1 -1
  39. package/build/assets/{conversation-tab-empty-state-D8dNvo-V.js → conversation-tab-empty-state-DyssnnWa.js} +1 -1
  40. package/build/assets/conversation-websocket-context-C8_PkGLi.js +3 -0
  41. package/build/assets/{copy-C7Ti2d8C.js → copy-DYgmUdIw.js} +1 -1
  42. package/build/assets/{custom-toast-handlers-BOc3qeQ7.js → custom-toast-handlers-C-SZFmto.js} +1 -1
  43. package/build/assets/declaration-BNMqORFE.js +1 -0
  44. package/build/assets/{device-verify-CMusn8nX.js → device-verify-DqDlphsG.js} +1 -1
  45. package/build/assets/{dist-DZHSA2e6.js → dist-C6t0EXL7.js} +1 -1
  46. package/build/assets/{edit-automation-modal-Dnjxbjn7.js → edit-automation-modal-BGzR3nfZ.js} +1 -1
  47. package/build/assets/{ellipsis-button-ugUATsNo.js → ellipsis-button-ZyLMPURn.js} +1 -1
  48. package/build/assets/{entry.client-CqqXOSvd.js → entry.client-1VMHpktY.js} +2 -2
  49. package/build/assets/{enum-filter-dropdown-1vpOGySB.js → enum-filter-dropdown-CEgCdu4A.js} +1 -1
  50. package/build/assets/{environment-switch-overlay-CTCTQikP.js → environment-switch-overlay-XL8yCGP6.js} +1 -1
  51. package/build/assets/{extensions-hub-BSUseHVF.js → extensions-hub-C651jsVh.js} +1 -1
  52. package/build/assets/{extensions-navigation-CT1kc1u_.js → extensions-navigation-BYR8Giqq.js} +1 -1
  53. package/build/assets/files-tab-BhnLgimi.js +1 -0
  54. package/build/assets/{folder-0WSMImNX.js → folder-ZZJVGgd7.js} +1 -1
  55. package/build/assets/{git-control-bar-branch-button-C8u5rzjc.js → git-control-bar-branch-button-M34A5_vX.js} +2 -2
  56. package/build/assets/{git-provider-icon-D-a-rcLm.js → git-provider-icon-D5dCNy-k.js} +1 -1
  57. package/build/assets/home-CYQv7yc_.js +1 -0
  58. package/build/assets/{i18n-DjAGhTis.js → i18n-CTohRuoO.js} +1 -1
  59. package/build/assets/install-server-modal-f31_CLrW.js +1 -0
  60. package/build/assets/{launch-B2mbfOSm.js → launch-DHEUYn2A.js} +1 -1
  61. package/build/assets/{lesson-plan-DRYG5SLI.js → lesson-plan-dH5Bj0pN.js} +1 -1
  62. package/build/assets/{link-external-C9d6Fo3x.js → link-external-D2POYx4c.js} +1 -1
  63. package/build/assets/{llm-client-ChQzg4wX.js → llm-client-DaH1TuyR.js} +1 -1
  64. package/build/assets/llm-settings-Bql-vydt.js +1 -0
  65. package/build/assets/llm-settings-C_tal6Ds.js +1 -0
  66. package/build/assets/{loading-spinner-C04FGh14.js → loading-spinner-BPtYORNK.js} +1 -1
  67. package/build/assets/{manage-backends-modal-s22zCdEW.js → manage-backends-modal-l7RkKfwX.js} +1 -1
  68. package/build/assets/{manage-workspaces-modal-C5EuW8m1.js → manage-workspaces-modal-DhKF_8z3.js} +1 -1
  69. package/build/assets/manifest-6b31008e.js +1 -0
  70. package/build/assets/{markdown-renderer-CEX4Becj.js → markdown-renderer-DMzf2i4x.js} +1 -1
  71. package/build/assets/mcp-D2onbwVk.js +9 -0
  72. package/build/assets/{messages-6aOyUu3r.js → messages-BMzyOW2V.js} +1 -1
  73. package/build/assets/{modal-backdrop-DTYGVmOR.js → modal-backdrop-BAbgYsqB.js} +1 -1
  74. package/build/assets/{modal-body-YElmM1dV.js → modal-body-BI6Ru2Qr.js} +1 -1
  75. package/build/assets/{modal-close-button-C_GpQt9F.js → modal-close-button-t1Gh3qmL.js} +1 -1
  76. package/build/assets/{model-selector-DeMmw-Xa.js → model-selector-SM9IUz-q.js} +1 -1
  77. package/build/assets/{mutation-Cz7N4XAo.js → mutation-D0OogFCz.js} +1 -1
  78. package/build/assets/{navigation-context-DeIPtGPp.js → navigation-context-D0YWpT8d.js} +1 -1
  79. package/build/assets/{navigation-link-C9JD4PYD.js → navigation-link-Cn7KP3c5.js} +1 -1
  80. package/build/assets/{openhands-logo-CI5Fhn1W.js → openhands-logo-CnrF6LKb.js} +1 -1
  81. package/build/assets/{option-service.api-DsI1UW7N.js → option-service.api-KvY_mZMY.js} +1 -1
  82. package/build/assets/{organization-service.api-COwMPFg5.js → organization-service.api-DzYTHTYC.js} +1 -1
  83. package/build/assets/{path-utils-BVbe598W.js → path-utils-YohAYyMv.js} +1 -1
  84. package/build/assets/{plan-components-DEjMuDDG.js → plan-components-atxXCF0R.js} +1 -1
  85. package/build/assets/{planner-tab-bN6r1G-1.js → planner-tab-CFc-hV07.js} +1 -1
  86. package/build/assets/{profiles-client-BGkKEV9j.js → profiles-client-D6IkTJof.js} +1 -1
  87. package/build/assets/{providers-DXvCAN_u.js → providers-Bx6EfrzZ.js} +1 -1
  88. package/build/assets/{proxy-CurRmrqf.js → proxy-CxydCnis.js} +1 -1
  89. package/build/assets/{query-client-config-Ba7qAAoO.js → query-client-config-B7u9asM0.js} +1 -1
  90. package/build/assets/{recommended-automations-launcher-mJhK6Atl.js → recommended-automations-launcher-sgvfU62c.js} +3 -3
  91. package/build/assets/root-E6pcRIYp.js +2 -0
  92. package/build/assets/{root-layout-BjVwHmta.js → root-layout-DVepR4To.js} +2 -2
  93. package/build/assets/sdk-section-page-DOIKvwSL.js +1 -0
  94. package/build/assets/{sdk-settings-schema-QBYH-ONX.js → sdk-settings-schema-DsUf9wu1.js} +1 -1
  95. package/build/assets/{search-Cq_cFrDt.js → search-27Owlc3A.js} +1 -1
  96. package/build/assets/{secrets-service-Bwd5DeUs.js → secrets-service-BsnKFc2x.js} +1 -1
  97. package/build/assets/secrets-settings-Bz_UohPJ.js +1 -0
  98. package/build/assets/{server-client-C3mC8Hl3.js → server-client-DyAQ3NZ_.js} +1 -1
  99. package/build/assets/{settings-D7E2U5tK.js → settings-BYkVX7vW.js} +1 -1
  100. package/build/assets/{settings-client-CwjfwoiB.js → settings-client-C73C7IgV.js} +1 -1
  101. package/build/assets/{settings-dropdown-input-VwAXNrOb.js → settings-dropdown-input-BJYvGdg-.js} +1 -1
  102. package/build/assets/{settings-gear-BJwWR1ej.js → settings-gear-C77PgE_O.js} +1 -1
  103. package/build/assets/{settings-index-J-3BNR0W.js → settings-index-Dz0BmdJD.js} +1 -1
  104. package/build/assets/{settings-input-DBywAnA7.js → settings-input-Bn7F5C75.js} +1 -1
  105. package/build/assets/{settings-list-classes-BOS092DR.js → settings-list-classes-Bf80tWtc.js} +1 -1
  106. package/build/assets/{settings-modal-B8vgWDTe.js → settings-modal-Brzgh5Yw.js} +1 -1
  107. package/build/assets/{settings-section-header-context-32x6WTyL.js → settings-section-header-context-BgZe5YkE.js} +1 -1
  108. package/build/assets/{settings-service.api-FvJGK45W.js → settings-service.api-CZ3uWx4v.js} +1 -1
  109. package/build/assets/{settings-switch-DTKmHC8F.js → settings-switch-BeIKrWms.js} +1 -1
  110. package/build/assets/{shared-conversation-EZV0FRIf.js → shared-conversation-DChOdb0t.js} +1 -1
  111. package/build/assets/{sidebar-mobile-menu-toggle-BnbzzpQl.js → sidebar-mobile-menu-toggle-BWuf4PRH.js} +1 -1
  112. package/build/assets/{sidebar-nav-link-CnWoZcwc.js → sidebar-nav-link-BGjiJq-4.js} +1 -1
  113. package/build/assets/{skill-card-pill-row-tZ599jli.js → skill-card-pill-row-DF1axQCG.js} +1 -1
  114. package/build/assets/{skills-ZyAO5dyK.js → skills-ChIKZPK4.js} +1 -1
  115. package/build/assets/{skills-plugins-BSRz041I.js → skills-plugins-CcI_19lM.js} +1 -1
  116. package/build/assets/{skills-settings-CG2hu34D.js → skills-settings-DlA5hlXw.js} +1 -1
  117. package/build/assets/{status-CsatcFbK.js → status-hp6M6E7E.js} +1 -1
  118. package/build/assets/{styled-tooltip-CS3mB_1X.js → styled-tooltip-CBzrri6o.js} +1 -1
  119. package/build/assets/{switch-skeleton-C-CfhYYV.js → switch-skeleton-DnC9wLp7.js} +1 -1
  120. package/build/assets/{task-list-tab-465DDju0.js → task-list-tab-DUJn1sgz.js} +1 -1
  121. package/build/assets/{terminal-CcgBEVnC.js → terminal-CRf9S0Z2.js} +1 -1
  122. package/build/assets/{terminal-LNa-iU5c.js → terminal-RmuaSdhJ.js} +1 -1
  123. package/build/assets/{toggle-switch-k-IZCDbt.js → toggle-switch-Pvyp2RAN.js} +1 -1
  124. package/build/assets/{typography-vVUMoNUg.js → typography-gpuWmrQO.js} +1 -1
  125. package/build/assets/{u-check-circle-DplbarS5.js → u-check-circle-IUIfACQQ.js} +1 -1
  126. package/build/assets/{u-check-circle-half-yDuiSZHC.js → u-check-circle-half-C1YxB6py.js} +1 -1
  127. package/build/assets/{u-circuit-C9tYkpeK.js → u-circuit-BmVikJHu.js} +1 -1
  128. package/build/assets/{u-edit-KAUlufD8.js → u-edit-CFvXHqZk.js} +1 -1
  129. package/build/assets/use-active-conversation-Db3IWSPK.js +1 -0
  130. package/build/assets/{use-agent-settings-schema-Bvp5UzV8.js → use-agent-settings-schema-33Un7UF2.js} +1 -1
  131. package/build/assets/{use-agent-state-D2C9SeGw.js → use-agent-state-Bn8vS5sY.js} +1 -1
  132. package/build/assets/{use-cloud-current-user-id-DWVar4st.js → use-cloud-current-user-id-CvkXFnTT.js} +1 -1
  133. package/build/assets/use-config-Co1O8-Ey.js +1 -0
  134. package/build/assets/{use-create-conversation-BEZg__Vv.js → use-create-conversation-CKS3EAHu.js} +1 -1
  135. package/build/assets/use-get-secrets-DuhdIA59.js +1 -0
  136. package/build/assets/{use-handle-plan-click-uOpew2LO.js → use-handle-plan-click-C9zJpK8A.js} +1 -1
  137. package/build/assets/use-is-authed-BggE5wPj.js +1 -0
  138. package/build/assets/{use-is-creating-conversation-DhDeeWfA.js → use-is-creating-conversation-BZ5hB_Bg.js} +1 -1
  139. package/build/assets/{use-launch-skill-in-chat-DVGPFrbI.js → use-launch-skill-in-chat-fNN_xGZG.js} +1 -1
  140. package/build/assets/{use-llm-profiles-O4a9V6RC.js → use-llm-profiles-DDOol3gK.js} +1 -1
  141. package/build/assets/use-runtime-is-ready-CQCE3xZC.js +1 -0
  142. package/build/assets/{use-save-settings-CEEKSTWG.js → use-save-settings-VUrj_QNG.js} +1 -1
  143. package/build/assets/{use-settings-DQ7Oo1Hj.js → use-settings-DQIZmIov.js} +1 -1
  144. package/build/assets/{use-settings-nav-items-YmrXrjn9.js → use-settings-nav-items-1ZvovKSr.js} +1 -1
  145. package/build/assets/{use-skills-BIvlWblA.js → use-skills-DAMLFjKU.js} +1 -1
  146. package/build/assets/use-unified-vscode-url-sZt29HrC.js +1 -0
  147. package/build/assets/use-user-conversation-DfgEB6RW.js +1 -0
  148. package/build/assets/{useMutation-B4OUESdw.js → useMutation-DqrumCWD.js} +1 -1
  149. package/build/assets/{useTranslation-CpIcQBq6.js → useTranslation-DCOdSSMl.js} +1 -1
  150. package/build/assets/{utils-D-HX7JCe.js → utils-i18rdUj2.js} +1 -1
  151. package/build/assets/v4-CNn21NXa.js +1 -0
  152. package/build/assets/{vendor~browser-Dr71AdrG.js → vendor~browser-BNjNhjFU.js} +1 -1
  153. package/build/assets/{vendor~browser-tab-BiVxfjJo.js → vendor~browser-tab-BgwV1mxF.js} +1 -1
  154. package/build/assets/{vendor~conversation-panel~conversation-BlCIz9XQ.js → vendor~conversation-panel~conversation-a9SyrrhV.js} +1 -1
  155. package/build/assets/{vendor~files-tab-DtLR-QD9.js → vendor~files-tab-BGKayPiK.js} +1 -1
  156. package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Ds9quNZ9.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-smY2r837.js} +1 -1
  157. package/build/assets/{vendor~home~mcp~automations-list-C5PoHCy6.js → vendor~home~mcp~automations-list-Ccy2I0KU.js} +1 -1
  158. package/build/assets/{vendor~home~mcp~automations-list-BUBGGGYz.js → vendor~home~mcp~automations-list-DoPfwaXj.js} +1 -1
  159. package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-CGlZoBKa.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-DbfELDJu.js} +2 -2
  160. package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-DE11mPxp.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-Z3nsiNNq.js} +1 -1
  161. package/build/assets/{vendor~launch-Dg--Ssk6.js → vendor~launch-vdeRTWFu.js} +1 -1
  162. package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-DrXgiSCq.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-DW31UyBp.js} +1 -1
  163. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-8b8V5bfO.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-BkQGKpye.js} +1 -1
  164. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-Dy7L6fMG.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-DzIXV3Ui.js} +1 -1
  165. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-D40EXhZx.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-Bbs7UJ5U.js} +2 -2
  166. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-CHrEOFl6.js → vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-DTwbEEcX.js} +1 -1
  167. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-BP1SKG0F.js → vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-d2oallMa.js} +1 -1
  168. package/build/assets/{vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~kyz9p27j-CyUbhpbm.js → vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~f2l2lr17-CDXvdvb2.js} +1 -1
  169. package/build/assets/{verification-settings-BtlTiHP8.js → verification-settings-CsbvQcYS.js} +1 -1
  170. package/build/assets/{vscode-tab-B0vdh9gU.js → vscode-tab-Zb-QbTuV.js} +1 -1
  171. package/build/assets/{waiting-for-runtime-message-DWPl_Yby.js → waiting-for-runtime-message-CntjExbU.js} +1 -1
  172. package/build/assets/{x-mark-CWI0f9yI.js → x-mark-CrpjscNc.js} +1 -1
  173. package/build/index.html +4 -4
  174. package/build/locales/ar/openhands.json +7 -0
  175. package/build/locales/ca/openhands.json +7 -0
  176. package/build/locales/de/openhands.json +7 -0
  177. package/build/locales/en/openhands.json +7 -0
  178. package/build/locales/es/openhands.json +7 -0
  179. package/build/locales/fr/openhands.json +7 -0
  180. package/build/locales/it/openhands.json +7 -0
  181. package/build/locales/ja/openhands.json +7 -0
  182. package/build/locales/ko-KR/openhands.json +7 -0
  183. package/build/locales/no/openhands.json +7 -0
  184. package/build/locales/pt/openhands.json +7 -0
  185. package/build/locales/tr/openhands.json +7 -0
  186. package/build/locales/uk/openhands.json +7 -0
  187. package/build/locales/zh-CN/openhands.json +7 -0
  188. package/build/locales/zh-TW/openhands.json +7 -0
  189. package/config/defaults.json +0 -4
  190. package/dist/api/agent-server-adapter.cjs +1 -1
  191. package/dist/api/agent-server-adapter.cjs.map +1 -1
  192. package/dist/api/agent-server-adapter.js +1 -1
  193. package/dist/api/agent-server-adapter.js.map +1 -1
  194. package/dist/api/agent-server-compatibility.cjs +1 -1
  195. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  196. package/dist/api/agent-server-compatibility.d.ts +16 -0
  197. package/dist/api/agent-server-compatibility.js +31 -20
  198. package/dist/api/agent-server-compatibility.js.map +1 -1
  199. package/dist/api/agent-server-config.cjs +1 -1
  200. package/dist/api/agent-server-config.cjs.map +1 -1
  201. package/dist/api/agent-server-config.d.ts +45 -0
  202. package/dist/api/agent-server-config.js +49 -21
  203. package/dist/api/agent-server-config.js.map +1 -1
  204. package/dist/api/backend-registry/storage.cjs +1 -1
  205. package/dist/api/backend-registry/storage.cjs.map +1 -1
  206. package/dist/api/backend-registry/storage.js +34 -32
  207. package/dist/api/backend-registry/storage.js.map +1 -1
  208. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  209. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  210. package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +5 -4
  211. package/dist/api/conversation-service/agent-server-conversation-service.api.js +70 -76
  212. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  213. package/dist/components/features/backends/api-key-entry-screen.d.ts +10 -0
  214. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  215. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  216. package/dist/components/features/backends/backend-form-modal.d.ts +23 -2
  217. package/dist/components/features/backends/backend-form-modal.js +43 -38
  218. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  219. package/dist/components/features/browser/browser.cjs +1 -1
  220. package/dist/components/features/browser/browser.cjs.map +1 -1
  221. package/dist/components/features/browser/browser.js +10 -16
  222. package/dist/components/features/browser/browser.js.map +1 -1
  223. package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
  224. package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
  225. package/dist/components/features/mcp-page/install-server-modal.js +123 -116
  226. package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
  227. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  228. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  229. package/dist/components/features/mcp-page/installed-server-card.js +40 -40
  230. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  231. package/dist/components/features/mcp-page/marketplace-card.cjs +1 -1
  232. package/dist/components/features/mcp-page/marketplace-card.cjs.map +1 -1
  233. package/dist/components/features/mcp-page/marketplace-card.js +2 -3
  234. package/dist/components/features/mcp-page/marketplace-card.js.map +1 -1
  235. package/dist/components/features/mcp-page/marketplace-section.cjs +1 -1
  236. package/dist/components/features/mcp-page/marketplace-section.cjs.map +1 -1
  237. package/dist/components/features/mcp-page/marketplace-section.js +21 -21
  238. package/dist/components/features/mcp-page/marketplace-section.js.map +1 -1
  239. package/dist/components/features/onboarding/steps/setup-acp-secrets-step.d.ts +27 -0
  240. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  241. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +2 -0
  242. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
  243. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs.map +1 -1
  244. package/dist/components/features/settings/sdk-settings/sdk-section-page.d.ts +10 -1
  245. package/dist/components/features/settings/sdk-settings/sdk-section-page.js +87 -84
  246. package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
  247. package/dist/constants/acp-providers.cjs +1 -1
  248. package/dist/constants/acp-providers.cjs.map +1 -1
  249. package/dist/constants/acp-providers.d.ts +25 -0
  250. package/dist/constants/acp-providers.js +1 -0
  251. package/dist/constants/acp-providers.js.map +1 -1
  252. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  253. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  254. package/dist/contexts/conversation-websocket-context.js +136 -132
  255. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  256. package/dist/hooks/chat/use-model-interceptor.cjs.map +1 -1
  257. package/dist/hooks/chat/use-model-interceptor.js.map +1 -1
  258. package/dist/hooks/mutation/use-switch-llm-profile.cjs.map +1 -1
  259. package/dist/hooks/mutation/use-switch-llm-profile.d.ts +1 -1
  260. package/dist/hooks/mutation/use-switch-llm-profile.js.map +1 -1
  261. package/dist/hooks/query/use-config.cjs +1 -1
  262. package/dist/hooks/query/use-config.cjs.map +1 -1
  263. package/dist/hooks/query/use-config.js +10 -10
  264. package/dist/hooks/query/use-config.js.map +1 -1
  265. package/dist/hooks/query/use-local-git-info.cjs +3 -3
  266. package/dist/hooks/query/use-local-git-info.cjs.map +1 -1
  267. package/dist/hooks/query/use-local-git-info.js +24 -25
  268. package/dist/hooks/query/use-local-git-info.js.map +1 -1
  269. package/dist/i18n/declaration.cjs +1 -1
  270. package/dist/i18n/declaration.cjs.map +1 -1
  271. package/dist/i18n/declaration.d.ts +7 -0
  272. package/dist/i18n/declaration.js +1 -1
  273. package/dist/i18n/declaration.js.map +1 -1
  274. package/dist/i18n/translation.cjs +2 -2
  275. package/dist/i18n/translation.cjs.map +1 -1
  276. package/dist/i18n/translation.js +119 -0
  277. package/dist/i18n/translation.js.map +1 -1
  278. package/dist/locales/ar/openhands.json +7 -0
  279. package/dist/locales/ca/openhands.json +7 -0
  280. package/dist/locales/de/openhands.json +7 -0
  281. package/dist/locales/en/openhands.json +7 -0
  282. package/dist/locales/es/openhands.json +7 -0
  283. package/dist/locales/fr/openhands.json +7 -0
  284. package/dist/locales/it/openhands.json +7 -0
  285. package/dist/locales/ja/openhands.json +7 -0
  286. package/dist/locales/ko-KR/openhands.json +7 -0
  287. package/dist/locales/no/openhands.json +7 -0
  288. package/dist/locales/pt/openhands.json +7 -0
  289. package/dist/locales/tr/openhands.json +7 -0
  290. package/dist/locales/uk/openhands.json +7 -0
  291. package/dist/locales/zh-CN/openhands.json +7 -0
  292. package/dist/locales/zh-TW/openhands.json +7 -0
  293. package/dist/package.cjs +1 -1
  294. package/dist/package.cjs.map +1 -1
  295. package/dist/package.js +1 -1
  296. package/dist/package.js.map +1 -1
  297. package/dist/routes/mcp.cjs +1 -1
  298. package/dist/routes/mcp.cjs.map +1 -1
  299. package/dist/routes/mcp.js +64 -64
  300. package/dist/routes/mcp.js.map +1 -1
  301. package/dist/stores/browser-store.cjs +1 -1
  302. package/dist/stores/browser-store.cjs.map +1 -1
  303. package/dist/stores/browser-store.js +1 -1
  304. package/dist/stores/browser-store.js.map +1 -1
  305. package/dist/utils/mcp-marketplace-utils.cjs +1 -1
  306. package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
  307. package/dist/utils/mcp-marketplace-utils.d.ts +13 -22
  308. package/dist/utils/mcp-marketplace-utils.js +46 -28
  309. package/dist/utils/mcp-marketplace-utils.js.map +1 -1
  310. package/dist/utils/sdk-settings-schema.cjs +1 -1
  311. package/dist/utils/sdk-settings-schema.cjs.map +1 -1
  312. package/dist/utils/sdk-settings-schema.d.ts +1 -0
  313. package/dist/utils/sdk-settings-schema.js +1 -1
  314. package/dist/utils/sdk-settings-schema.js.map +1 -1
  315. package/package.json +1 -1
  316. package/scripts/dev-safe.mjs +59 -40
  317. package/scripts/dev-static.mjs +2 -3
  318. package/scripts/dev-with-automation.mjs +75 -19
  319. package/scripts/static-server.mjs +77 -35
  320. package/tools/canvas_ui_tool.py +4 -0
  321. package/build/assets/acp-providers-DauuOsW9.js +0 -1
  322. package/build/assets/add-backend-modal-FsnpTTgO.js +0 -1
  323. package/build/assets/agent-server-client-options-DT2GP6VJ.js +0 -1
  324. package/build/assets/agent-server-compatibility-2aOx5iWd.js +0 -1
  325. package/build/assets/agent-server-conversation-service.api-BZmUqtiO.js +0 -5
  326. package/build/assets/browser-store-C3AqxAO7.js +0 -1
  327. package/build/assets/browser-tab-B_BuTvrO.js +0 -1
  328. package/build/assets/conversation--ldUK72N.js +0 -19
  329. package/build/assets/conversation-eNrhH94O.js +0 -1
  330. package/build/assets/conversation-panel-B49Jpqpb.js +0 -1
  331. package/build/assets/conversation-websocket-context-BW68-J8o.js +0 -3
  332. package/build/assets/declaration-D378OjpZ.js +0 -1
  333. package/build/assets/files-tab-CQHdWpQt.js +0 -1
  334. package/build/assets/home-DD0GroCu.js +0 -1
  335. package/build/assets/install-server-modal-z5VaHeXd.js +0 -1
  336. package/build/assets/llm-settings-BEyqixPI.js +0 -1
  337. package/build/assets/llm-settings-BdiaGFbg.js +0 -1
  338. package/build/assets/manifest-9d1c34fb.js +0 -1
  339. package/build/assets/mcp-C06YssEI.js +0 -9
  340. package/build/assets/root-3t9rxEpE.js +0 -2
  341. package/build/assets/sdk-section-page-CJW0G04-.js +0 -1
  342. package/build/assets/secrets-settings-MLXqOtX2.js +0 -1
  343. package/build/assets/use-active-conversation-DS5j9R4q.js +0 -1
  344. package/build/assets/use-config-BSu_53GL.js +0 -1
  345. package/build/assets/use-conversation-id-DajhCn2A.js +0 -1
  346. package/build/assets/use-is-authed-hXC8vxgT.js +0 -1
  347. package/build/assets/use-runtime-is-ready-pGSbPddC.js +0 -1
  348. package/build/assets/use-unified-vscode-url-wAMzv8Sn.js +0 -1
  349. package/build/assets/use-user-conversation-B_zDoSeh.js +0 -1
  350. /package/build/assets/{automation-XLxhq3I8.js → automation-IdgZq6ZK.js} +0 -0
  351. /package/build/assets/{common-SMkEaBSr.js → common-DR1t-EeP.js} +0 -0
  352. /package/build/assets/{conversation-state-store-Bc0slAjL.js → conversation-state-store-u5jepov0.js} +0 -0
  353. /package/build/assets/{dist-yMQV8IUk.js → dist-BxBP7tFD.js} +0 -0
  354. /package/build/assets/{git-status-mapper-BI8FyUVp.js → git-status-mapper-DnL9OC8_.js} +0 -0
  355. /package/build/assets/{handle-capture-consent-BfZATzpI.js → handle-capture-consent-3XrjZ8wi.js} +0 -0
  356. /package/build/assets/{iconBase-C7N9pPOs.js → iconBase-DE30Zj_-.js} +0 -0
  357. /package/build/assets/{settings-D5am1n6X.js → settings-D_H-qsRm.js} +0 -0
  358. /package/build/assets/{settings-like-page-layout-classes-Bn-M9oOa.js → settings-like-page-layout-classes-I0BDBEoq.js} +0 -0
  359. /package/build/assets/{settings-utils-BsvSU3OM.js → settings-utils-B6Nl07io.js} +0 -0
  360. /package/build/assets/{sidebar-store-cOeaKmIm.js → sidebar-store-Uy3v0AOV.js} +0 -0
  361. /package/build/assets/{use-breakpoint-B86yKT9n.js → use-breakpoint-DbJ6FkQ-.js} +0 -0
  362. /package/build/assets/{use-click-outside-element-835W9pC6.js → use-click-outside-element-DffgWWoZ.js} +0 -0
  363. /package/build/assets/{use-task-list-DDeNHprj.js → use-task-list-CLJbuJgM.js} +0 -0
  364. /package/build/assets/{vendor~browser-BpdPBhgZ.js → vendor~browser-DDiZgqD3.js} +0 -0
  365. /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-Df7_G0zR.js → vendor~conversation-panel~conversation~alert-banner-DbvX3OcM.js} +0 -0
  366. /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~b4cctr4k-B7YVdv1X.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~g56ukk6u-DsSvIDZQ.js} +0 -0
  367. /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~i9dbt75i-CI82Did1.js → vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~hkqzh1hb-BZ0HXuHD.js} +0 -0
  368. /package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~pfbaerbd-zhv9fooy.js → vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~ninslayh-D9P8e98a.js} +0 -0
  369. /package/build/assets/{vendor~terminal-BUxzHKcC.js → vendor~terminal-DUrOWGFE.js} +0 -0
  370. /package/build/assets/{vscode-url-helper-jesbpos5.js → vscode-url-helper-Cwy1A62q.js} +0 -0
@@ -134,6 +134,7 @@ function parseArgs() {
134
134
  dynamic: false,
135
135
  staticDir: null,
136
136
  skipBuild: false,
137
+ public: false,
137
138
  };
138
139
 
139
140
  for (let i = 0; i < args.length; i++) {
@@ -164,6 +165,9 @@ function parseArgs() {
164
165
  case "--skip-build":
165
166
  config.skipBuild = true;
166
167
  break;
168
+ case "--public":
169
+ config.public = true;
170
+ break;
167
171
  case "-h":
168
172
  case "--help":
169
173
  showHelp();
@@ -281,6 +285,18 @@ async function buildConfig(args, env = process.env) {
281
285
  env.OH_AUTOMATION_REPO = args.automationRepo;
282
286
  }
283
287
 
288
+ const isPublic = args.public;
289
+
290
+ // In public mode, LOCAL_BACKEND_API_KEY is required — without it the
291
+ // auth screen has nothing to validate against.
292
+ if (isPublic && !env.LOCAL_BACKEND_API_KEY) {
293
+ logError(
294
+ "PUBLIC MODE requires LOCAL_BACKEND_API_KEY environment variable.\n" +
295
+ " Example: LOCAL_BACKEND_API_KEY=my-secret npm run dev -- --public",
296
+ );
297
+ process.exit(1);
298
+ }
299
+
284
300
  // Preferred ports (from env or defaults).
285
301
  // OH_CANVAS_SAFE_BACKEND_PORT / OH_CANVAS_SAFE_AUTOMATION_PORT /
286
302
  // OH_CANVAS_SAFE_VITE_PORT allow tests (and advanced users) to redirect
@@ -303,11 +319,14 @@ async function buildConfig(args, env = process.env) {
303
319
 
304
320
  const vscodePort = preferredBackendPort + 1000;
305
321
 
306
- // Session API key — shared by both agent-server and automation backend.
322
+ // API key — shared by both agent-server and automation backend.
307
323
  // Both validate it via the `X-Session-API-Key` header.
324
+ // LOCAL_BACKEND_API_KEY is the single user-facing env var: if set it's
325
+ // used directly; otherwise one is auto-generated and persisted.
308
326
  const stateDir =
309
327
  env.OH_CANVAS_SAFE_STATE_DIR ||
310
328
  join(homedir(), ".openhands", "agent-canvas");
329
+
311
330
  const safeConfig = buildSafeDevConfig(projectRoot, {
312
331
  ...env,
313
332
  OH_CANVAS_SAFE_STATE_DIR: stateDir,
@@ -316,6 +335,19 @@ async function buildConfig(args, env = process.env) {
316
335
  });
317
336
  const sessionApiKey = safeConfig.sessionApiKey;
318
337
 
338
+ if (isPublic) {
339
+ logService(
340
+ "auth",
341
+ "PUBLIC MODE — key will NOT be injected into the frontend",
342
+ c.yellow,
343
+ );
344
+ logService(
345
+ "auth",
346
+ "Users must paste the LOCAL_BACKEND_API_KEY in the browser",
347
+ c.dim,
348
+ );
349
+ }
350
+
319
351
  return {
320
352
  // Ingress port (main entry point)
321
353
  ingressPort: preferredIngressPort,
@@ -335,6 +367,9 @@ async function buildConfig(args, env = process.env) {
335
367
  // Auth — single key for both backends
336
368
  sessionApiKey,
337
369
 
370
+ // Public mode — the session key should NOT be baked into the frontend
371
+ isPublic,
372
+
338
373
  verbose: args.verbose,
339
374
  };
340
375
  }
@@ -517,6 +552,9 @@ function startAgentServer(config) {
517
552
  const agentServerEnv = {
518
553
  ...buildAgentServerEnv(safeConfig),
519
554
  ...buildAgentServerAutomationEnv(config),
555
+ // Ensure the agent-server uses the resolved key from config. This is
556
+ // LOCAL_BACKEND_API_KEY when set, or the auto-generated persisted key.
557
+ OH_SESSION_API_KEYS_0: config.sessionApiKey,
520
558
  };
521
559
 
522
560
  spawnService(
@@ -726,22 +764,31 @@ function startVite(config) {
726
764
  const frontendCommand = buildNpmScriptCommand("dev:frontend");
727
765
  const runtimeServicesInfo = buildAutomationRuntimeServicesInfo(config);
728
766
 
767
+ const viteEnv = {
768
+ // Point Vite at the ingress (so client-side fetches work)
769
+ VITE_BACKEND_HOST: `127.0.0.1:${config.ingressPort}`,
770
+ VITE_BACKEND_BASE_URL: `http://127.0.0.1:${config.ingressPort}`,
771
+ VITE_WORKING_DIR:
772
+ config.viteWorkingDir ?? join(config.stateDir, "workspaces"),
773
+ VITE_FRONTEND_PORT: config.vitePort.toString(),
774
+ // Inform the frontend (and downstream, the agent's system prompt) about
775
+ // which services are available in this dev stack.
776
+ VITE_RUNTIME_SERVICES_INFO: JSON.stringify(runtimeServicesInfo),
777
+ };
778
+
779
+ // In local mode, bake the session key into the frontend so the user
780
+ // never has to paste it. In public mode, omit the key and set
781
+ // VITE_AUTH_REQUIRED so the frontend shows the API key entry screen
782
+ // immediately (no network round-trip needed).
783
+ if (config.isPublic) {
784
+ viteEnv.VITE_AUTH_REQUIRED = "true";
785
+ } else {
786
+ viteEnv.VITE_SESSION_API_KEY = config.sessionApiKey;
787
+ }
788
+
729
789
  spawnService("vite", frontendCommand.command, frontendCommand.args, {
730
790
  cwd: config.canvasPath,
731
- env: {
732
- // Point Vite at the ingress (so client-side fetches work)
733
- VITE_BACKEND_HOST: `127.0.0.1:${config.ingressPort}`,
734
- VITE_BACKEND_BASE_URL: `http://127.0.0.1:${config.ingressPort}`,
735
- VITE_WORKING_DIR:
736
- config.viteWorkingDir ?? join(config.stateDir, "workspaces"),
737
- VITE_FRONTEND_PORT: config.vitePort.toString(),
738
- // Session API key — used by the frontend for both agent-server and
739
- // automation auth via the `X-Session-API-Key` header.
740
- VITE_SESSION_API_KEY: config.sessionApiKey,
741
- // Inform the frontend (and downstream, the agent's system prompt) about
742
- // which services are available in this dev stack.
743
- VITE_RUNTIME_SERVICES_INFO: JSON.stringify(runtimeServicesInfo),
744
- },
791
+ env: viteEnv,
745
792
  color: c.magenta,
746
793
  });
747
794
  }
@@ -905,10 +952,18 @@ async function main(options = {}) {
905
952
  // Human-readable label for the dev mode, surfaced in the agent's
906
953
  // <RUNTIME_SERVICES> system-prompt block.
907
954
  mode = "dev:automation",
955
+ // When true, enable public mode (require LOCAL_BACKEND_API_KEY,
956
+ // don't bake session key into frontend).
957
+ isPublic: isPublicOverride,
908
958
  } = options;
909
959
 
910
960
  const args = parseArgs();
911
961
 
962
+ // Allow options to override CLI args for public mode
963
+ if (isPublicOverride != null) {
964
+ args.public = isPublicOverride;
965
+ }
966
+
912
967
  // Allow options to override CLI args (for bin/agent-canvas.mjs)
913
968
  const useStaticMode =
914
969
  staticModeOverride ??
@@ -1041,12 +1096,13 @@ function startStaticFrontend(config, staticDir) {
1041
1096
  "0.0.0.0",
1042
1097
  "--port",
1043
1098
  String(config.vitePort),
1044
- // Inject the runtime session key so the pre-built frontend can
1045
- // authenticate to agent-server without VITE_SESSION_API_KEY being baked
1046
- // into the bundle at publish time.
1047
- ...(config.sessionApiKey
1099
+ // In local mode, inject the API key so the pre-built frontend can
1100
+ // authenticate transparently. In public mode, pass --auth-required
1101
+ // so the frontend shows the API key entry screen instead.
1102
+ ...(!config.isPublic && config.sessionApiKey
1048
1103
  ? ["--session-api-key", config.sessionApiKey]
1049
1104
  : []),
1105
+ ...(config.isPublic ? ["--auth-required"] : []),
1050
1106
  // Proxy routes to backends (same as ingress but for direct access to vitePort)
1051
1107
  "--route",
1052
1108
  `/api/automation=http://localhost:${config.autoBackendPort}`,
@@ -73,6 +73,7 @@ export function parseArgs(argv = process.argv.slice(2)) {
73
73
  dir: "build",
74
74
  routes: {},
75
75
  sessionApiKey: null,
76
+ authRequired: false,
76
77
  };
77
78
 
78
79
  for (let i = 0; i < argv.length; i++) {
@@ -108,6 +109,9 @@ export function parseArgs(argv = process.argv.slice(2)) {
108
109
  case "--session-api-key":
109
110
  config.sessionApiKey = argv[++i] || null;
110
111
  break;
112
+ case "--auth-required":
113
+ config.authRequired = true;
114
+ break;
111
115
  case "-h":
112
116
  case "--help":
113
117
  showHelp();
@@ -117,6 +121,19 @@ export function parseArgs(argv = process.argv.slice(2)) {
117
121
  }
118
122
  }
119
123
 
124
+ // Guard: --session-api-key and --auth-required are semantically
125
+ // mutually exclusive. The first auto-injects the key (local mode);
126
+ // the second forces the user to paste it (public mode). Combining
127
+ // both is a misconfiguration.
128
+ if (config.sessionApiKey && config.authRequired) {
129
+ console.error(
130
+ "ERROR: --session-api-key and --auth-required are mutually exclusive.\n" +
131
+ " Use --session-api-key for local mode (key auto-injected).\n" +
132
+ " Use --auth-required for public mode (user pastes key).",
133
+ );
134
+ process.exit(1);
135
+ }
136
+
120
137
  return config;
121
138
  }
122
139
 
@@ -136,6 +153,9 @@ OPTIONS:
136
153
  --session-api-key <key> Inject session API key into index.html so the
137
154
  pre-built frontend authenticates to agent-server
138
155
  without needing VITE_SESSION_API_KEY baked in.
156
+ --auth-required Inject authRequired flag into index.html so the
157
+ pre-built frontend shows the API key entry screen
158
+ (public mode) without VITE_AUTH_REQUIRED baked in.
139
159
  -h, --help Show this help
140
160
 
141
161
  ROUTING:
@@ -152,39 +172,55 @@ ROUTING:
152
172
  // ─────────────────────────────────────────────────────────────────────────────
153
173
 
154
174
  /**
155
- * Build a tiny inline script that seeds the session API key into the
156
- * `openhands-agent-server-config` localStorage entry the first time the page
157
- * loads. Only writes if no key is already stored — explicit user overrides
158
- * (set via Settings > Agent Server in the UI) are always preserved.
175
+ * Build a tiny inline script that seeds runtime config into the page.
176
+ *
177
+ * - `sessionApiKey`: written to `openhands-agent-server-config` in localStorage
178
+ * so the pre-built frontend authenticates without VITE_SESSION_API_KEY baked in.
179
+ * Only writes if no key is already stored — explicit user overrides are preserved.
159
180
  *
160
- * This lets the pre-built static binary work without needing VITE_SESSION_API_KEY
161
- * baked into the bundle at publish time: the runtime key is injected here instead.
181
+ * - `authRequired`: sets `window.__AGENT_CANVAS_AUTH_REQUIRED__ = true` so the
182
+ * pre-built frontend shows the API key entry screen (public mode) without
183
+ * VITE_AUTH_REQUIRED baked in.
162
184
  */
163
- function makeConfigInjectionScript(sessionApiKey) {
164
- if (!sessionApiKey) return "";
165
- // JSON.stringify produces a properly escaped JS string literal.
166
- const keyLiteral = JSON.stringify(sessionApiKey);
167
- return (
168
- `<script>` +
169
- `(function(){` +
170
- `try{` +
171
- `var _k='openhands-agent-server-config',` +
172
- `_c=JSON.parse(localStorage.getItem(_k)||'{}');` +
173
- `if(!_c.sessionApiKey){` +
174
- `_c.sessionApiKey=${keyLiteral};` +
175
- `localStorage.setItem(_k,JSON.stringify(_c));` +
176
- `}` +
177
- `}catch(e){}` +
178
- `}());` +
179
- `</script>`
180
- );
185
+ function makeConfigInjectionScript(sessionApiKey, authRequired) {
186
+ const parts = [];
187
+
188
+ if (sessionApiKey) {
189
+ const keyLiteral = JSON.stringify(sessionApiKey);
190
+ // Always overwrite when the stored key differs from the runtime key.
191
+ // A previous session may have persisted a now-stale key; the runtime
192
+ // value (from --session-api-key) is the server's truth.
193
+ parts.push(
194
+ `try{` +
195
+ `var _k='openhands-agent-server-config',` +
196
+ `_c=JSON.parse(localStorage.getItem(_k)||'{}');` +
197
+ `if(_c.sessionApiKey!==${keyLiteral}){` +
198
+ `_c.sessionApiKey=${keyLiteral};` +
199
+ `localStorage.setItem(_k,JSON.stringify(_c));` +
200
+ `}` +
201
+ `}catch(e){}`,
202
+ );
203
+ }
204
+
205
+ if (authRequired) {
206
+ parts.push(`window.__AGENT_CANVAS_AUTH_REQUIRED__=true;`);
207
+ }
208
+
209
+ if (parts.length === 0) return "";
210
+
211
+ return `<script>(function(){${parts.join("")}}());</script>`;
181
212
  }
182
213
 
183
214
  /**
184
- * Serve index.html with the runtime session key injected into <head>.
215
+ * Serve index.html with runtime config injected into <head>.
185
216
  * Returns true if the response was written, false if the file was not found.
186
217
  */
187
- async function serveInjectedIndexHtml(req, res, indexPath, sessionApiKey) {
218
+ async function serveInjectedIndexHtml(
219
+ req,
220
+ res,
221
+ indexPath,
222
+ { sessionApiKey, authRequired } = {},
223
+ ) {
188
224
  let content;
189
225
  try {
190
226
  content = await readFile(indexPath, "utf8");
@@ -192,7 +228,7 @@ async function serveInjectedIndexHtml(req, res, indexPath, sessionApiKey) {
192
228
  return false;
193
229
  }
194
230
 
195
- const script = makeConfigInjectionScript(sessionApiKey);
231
+ const script = makeConfigInjectionScript(sessionApiKey, authRequired);
196
232
  // Inject right before </head> so the key is available before any app code runs.
197
233
  // replace() targets the first (and only) </head> in well-formed HTML.
198
234
  const injected = content.includes("</head>")
@@ -393,7 +429,7 @@ async function serveFile(req, res, filePath, urlPath) {
393
429
  return true;
394
430
  }
395
431
 
396
- async function handleStatic(req, res, dirAbs, sessionApiKey = null) {
432
+ async function handleStatic(req, res, dirAbs, injectionOpts = {}) {
397
433
  const rawPath = req.url.split("?")[0];
398
434
  let urlPath;
399
435
  try {
@@ -417,9 +453,12 @@ async function handleStatic(req, res, dirAbs, sessionApiKey = null) {
417
453
  filePath = resolve(filePath, "index.html");
418
454
  }
419
455
 
420
- // Serve index.html with runtime key injection when a session key is configured.
421
- if (sessionApiKey && filePath.endsWith("index.html")) {
422
- if (await serveInjectedIndexHtml(req, res, filePath, sessionApiKey)) return;
456
+ const needsInjection =
457
+ injectionOpts.sessionApiKey || injectionOpts.authRequired;
458
+
459
+ // Serve index.html with runtime config injection when configured.
460
+ if (needsInjection && filePath.endsWith("index.html")) {
461
+ if (await serveInjectedIndexHtml(req, res, filePath, injectionOpts)) return;
423
462
  // Fall through to regular serveFile (handles 404 path correctly).
424
463
  }
425
464
 
@@ -431,8 +470,8 @@ async function handleStatic(req, res, dirAbs, sessionApiKey = null) {
431
470
  !looksLikeAssetRequest(urlPath)
432
471
  ) {
433
472
  const indexPath = resolve(dirAbs, "index.html");
434
- if (sessionApiKey) {
435
- if (await serveInjectedIndexHtml(req, res, indexPath, sessionApiKey))
473
+ if (needsInjection) {
474
+ if (await serveInjectedIndexHtml(req, res, indexPath, injectionOpts))
436
475
  return;
437
476
  } else if (await serveFile(req, res, indexPath, "/")) return;
438
477
  }
@@ -448,7 +487,10 @@ async function handleStatic(req, res, dirAbs, sessionApiKey = null) {
448
487
  export function startStaticServer(config) {
449
488
  const route = createRouter(config.routes);
450
489
  const dirAbs = resolve(config.dir);
451
- const sessionApiKey = config.sessionApiKey || null;
490
+ const injectionOpts = {
491
+ sessionApiKey: config.sessionApiKey || null,
492
+ authRequired: config.authRequired || false,
493
+ };
452
494
 
453
495
  const server = createServer((req, res) => {
454
496
  const backend = route(req.url);
@@ -456,7 +498,7 @@ export function startStaticServer(config) {
456
498
  proxyRequest(req, res, backend);
457
499
  return;
458
500
  }
459
- handleStatic(req, res, dirAbs, sessionApiKey).catch((err) => {
501
+ handleStatic(req, res, dirAbs, injectionOpts).catch((err) => {
460
502
  console.error(`Static handler error for ${req.url}:`, err);
461
503
  if (!res.headersSent) {
462
504
  res.writeHead(500);
@@ -90,7 +90,11 @@ When to call (pick the most specific option that matches your last action):
90
90
  command="open_tab", tab="terminal"
91
91
 
92
92
  * You browsed to a URL the user should see →
93
+ First call browser_get_state(include_screenshot=true) after your final
94
+ browser interaction so Agent Canvas has a screenshot to display, then call
93
95
  command="open_tab", tab="browser"
96
+ (browser_navigate alone only updates the URL; without browser_get_state,
97
+ the Browser tab will open without a screenshot.)
94
98
 
95
99
  Call this BEFORE writing your chat-message summary of the change, so the
96
100
  artifact is visible while the user reads what you did. One canvas_ui call
@@ -1 +0,0 @@
1
- import{t as e}from"./declaration-D378OjpZ.js";import{t}from"./vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-CHrEOFl6.js";var n=`cli-generic`,r=new Set([`default`,`default (recommended)`]);function i(e){if(typeof e!=`string`)return null;let t=e.trim();return!t||r.has(t.toLowerCase())||t===`acp-managed`?null:t}function a(e){for(let t of[e.runtimeName,e.runtimeId,e.configured,e.sdkLlm]){let e=i(t);if(e)return e}return e.providerDefault??null}var o={"claude-code":{icon:`claude-code`,description_key:e.ONBOARDING$AGENT_CLAUDE_CODE_DESCRIPTION},codex:{icon:`codex`,description_key:e.ONBOARDING$AGENT_CODEX_DESCRIPTION},"gemini-cli":{icon:`gemini`,description_key:e.ONBOARDING$AGENT_GEMINI_CLI_DESCRIPTION}},s=Object.entries(o).map(([e,n])=>{let r=t(e);return{key:e,display_name:r?.display_name??e,default_command:r?[...r.default_command]:[],available_models:r?.available_models?.map(e=>({id:e.id,label:e.label})),default_model:r?.default_model??void 0,description_key:n.description_key,icon:n.icon}}),c=`custom`;function l(e){if(e)return s.find(t=>t.key===e)}function u(e){let t=l(e);return t?t.display_name:null}function d(e){return l(e)?.icon??`cli-generic`}function f(e,t){return t?l(e)?.available_models?.find(e=>e.id===t)?.label??t:null}function p(e,t={}){if(e===`openhands`)return{agent_kind:`openhands`};let n=e===c,r=n?void 0:l(e);if(!n&&!r&&!t.allowUnknownServer)return null;let i=t.model===void 0?r?.default_model??null:t.model;return{agent_kind:`acp`,acp_server:e,acp_command:t.command??[],acp_args:[],acp_model:i??null}}export{l as a,d as c,p as i,a as l,s as n,u as o,n as r,f as s,c as t};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-BFRubm34.js";import{o as t}from"./declaration-D378OjpZ.js";import{n}from"./backend-form-modal-DxYjqqAK.js";var r=e({AddBackendModal:()=>a}),i=t();function a({onClose:e}){return(0,i.jsx)(n,{mode:`add`,onClose:e})}export{r as n,a as t};
@@ -1 +0,0 @@
1
- var e=`openhands-agent-server-config`,t=`workspace/project`;function n(){if(typeof window>`u`)return{};try{let t=window.localStorage.getItem(e);return t?JSON.parse(t)??{}:{}}catch{return{}}}function r(e){return e?.trim()||null}function i(e){if(!e)return null;let t=e.trim().replace(/\/$/,``);return t?/^https?:\/\//i.test(t)?t:typeof window<`u`?`${window.location.protocol}//${t}`:`http://${t}`:null}function a(){return i(n().baseUrl)||i(void 0)}function o(){return r(n().sessionApiKey)||r(void 0)}function s(e){if(typeof window>`u`)return!1;try{let t=new URL(e),n=new Set([`127.0.0.1`,`localhost`,`0.0.0.0`]),r=window.location.hostname;return n.has(t.hostname)&&!n.has(r)}catch{return!1}}function c(e){return e?s(e)?window.location.origin:e:null}function l(){return c(a())||(typeof window<`u`?window.location.origin:`http://127.0.0.1:8000`)}function u(){return o()}function d(){return(void 0)?.trim()||n().workingDir?.trim()||t}function f(e){return`${d().replace(/\/+$/,``)}/${e.replace(/-/g,``)}`}function p(){let e=u();return e?{"X-Session-API-Key":e}:{}}function m(){return!0}var h=`default-local`,g=`Local`;function _(){return{id:h,name:g,host:l(),apiKey:u()??``,kind:`local`}}var v=`openhands-backends`,y=`openhands-active-backend`;function b(e){return e===`local`||e===`cloud`}function x(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`&&b(t.kind)}function S(e){try{return new URL(e).origin}catch{return e.replace(/\/+$/,``)}}function C(e){let t=_();return e.id!==t.id||e.kind!==`local`||!t.apiKey||S(e.host)!==S(t.host)||e.apiKey===t.apiKey?e:{...e,apiKey:t.apiKey}}function w(e){if(!(typeof window>`u`))try{window.localStorage.setItem(v,JSON.stringify(e))}catch{}}function T(){if(typeof window>`u`)return[];try{let e=window.localStorage.getItem(v);if(e===null){let e=[_()];return w(e),e}let t=JSON.parse(e);if(!Array.isArray(t))return[];let n=t.filter(x);if(n.length===0){let e=[_()];return w(e),e}let r=n.map(C);return r.some((e,t)=>e!==n[t])&&w(r),r}catch{return[]}}function E(){if(typeof window>`u`)return null;try{let e=window.localStorage.getItem(y);if(!e)return null;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 D(e){if(!(typeof window>`u`))try{if(!e){window.localStorage.removeItem(y);return}window.localStorage.setItem(y,JSON.stringify({backendId:e.backendId,orgId:e.orgId??null}))}catch{}}function O(e){return e.find(e=>e.kind===`local`)??_()}function k(e,t){let n=null,r=null;if(t){let i=e.find(e=>e.id===t.backendId);i&&(n=i,r=t.orgId??null)}return n||(n=O(e),r=null),{backends:e,selection:t,active:{backend:n,orgId:r}}}var A=k(T(),E()),j=new Set;function M(){j.forEach(e=>e())}function N(){return A.active}function P(){let e=A.active.backend;return e.kind===`local`?e:O(A.backends)}function F(){return A.backends}function I(){return A.selection}function L(){return A}function R(e){D(e),A=k(A.backends,e),M()}function z(e){w(e);let t=A.selection;t&&!e.some(e=>e.id===t.backendId)&&(t=null,D(null)),A=k(e,t),M()}function B(e){return j.add(e),()=>{j.delete(e)}}var V=class extends Error{constructor(e,t,n,r){super(r||`HTTP ${e}: ${t}`),this.status=e,this.statusText=t,this.response=n,this.name=`HttpError`}},H=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,``),this.apiKey=e.apiKey,this.timeout=e.timeout||6e4}async request(e){let t=e.url.startsWith(`/`)?e.url.slice(1):e.url,n=new URL(t,this.baseUrl+`/`);e.params&&Object.entries(e.params).forEach(([e,t])=>{t!=null&&(Array.isArray(t)?t.forEach(t=>n.searchParams.append(e,String(t))):n.searchParams.append(e,String(t)))});let r={"Content-Type":`application/json`,...e.headers};this.apiKey&&(r[`X-Session-API-Key`]=this.apiKey);let i={method:e.method,headers:r,signal:AbortSignal.timeout(e.timeout||this.timeout)};e.credentials&&(i.credentials=e.credentials),e.data&&e.method!==`GET`&&(e.data instanceof FormData?(delete r[`Content-Type`],i.body=e.data):i.body=JSON.stringify(e.data));try{let t=await fetch(n.toString(),i);if(!(e.acceptableStatusCodes?.has(t.status)||!e.acceptableStatusCodes&&t.ok)){let e;try{e=t.headers.get(`content-type`)?.includes(`application/json`)?await t.json():await t.text()}catch{e=null}throw new V(t.status,t.statusText,e,`HTTP request failed (${t.status} ${t.statusText}): ${JSON.stringify(e)}`)}let r=await this.parseResponse(t,e.responseType||`auto`),a={};return t.headers.forEach((e,t)=>{a[t]=e}),{data:r,status:t.status,statusText:t.statusText,headers:a}}catch(t){throw t instanceof V?t:t instanceof Error?t.name===`AbortError`?Error(`Request timeout after ${e.timeout||this.timeout}ms`,{cause:t}):Error(`Request failed: ${t.message}`,{cause:t}):Error(`Unknown request error`,{cause:t})}}async parseResponse(e,t){return t===`json`?await e.json():t===`text`?await e.text():t===`blob`?await e.blob():t===`arrayBuffer`?await e.arrayBuffer():e.headers.get(`content-type`)?.includes(`application/json`)?await e.json():await e.text()}async get(e,t){return this.request({method:`GET`,url:e,...t})}async post(e,t,n){return this.request({method:`POST`,url:e,data:t,...n})}async put(e,t,n){return this.request({method:`PUT`,url:e,data:t,...n})}async patch(e,t,n){return this.request({method:`PATCH`,url:e,data:t,...n})}async delete(e,t){return this.request({method:`DELETE`,url:e,...t})}close(){}};function U(e){if(e&&!e.startsWith(`/`))try{let t=new URL(e),n=t.hostname,r=window.location.hostname??window.location.host?.split(`:`)[0];return r&&(n===`localhost`||n===`127.0.0.1`)&&r!==`localhost`&&r!==`127.0.0.1`?`${r}:${t.port}`:t.host}catch{return window.location.host}return window.location.host}function W(e){if(e&&!e.startsWith(`/`))try{return(new URL(e).pathname.split(`/api/conversations`)[0]||``).replace(/\/$/,``)}catch{return``}return``}function G(e){let t=U(e),n=W(e);return`${window.location.protocol===`https:`?`https:`:`http:`}//${t}${n}`}function K(e){if(!e||e.startsWith(`/`))return null;try{return new URL(e).protocol}catch{return null}}function q(e,t){let n=U(e),r=W(e),i=window.location.protocol===`https:`,a=K(e)===`https:`,o=`${i||a?`wss:`:`ws:`}//${n}${r}/sockets/bash-events`;return t?`${o}?session_api_key=${encodeURIComponent(t)}`:o}function J(e,t){if(!e)return null;let n=U(t),r=W(t),i=window.location.protocol===`https:`,a=K(t)===`https:`;return`${i||a?`wss:`:`ws:`}//${n}${r}/sockets/events/${e}`}function Y(e){return e.replace(/\/+$/,``)}function X(e,t){return e.host?Y(e.host):e.conversationUrl?Y(G(e.conversationUrl)):Y(t.host)}function Z(e={}){let t=P(),n=u(),r=t.id===`default-local`?n:null,i=e.sessionApiKey??e.apiKey??r??t.apiKey??void 0;return{host:X(e,t),...i?{apiKey:i}:{},workingDir:e.workingDir??d(),...e.timeout===void 0?{}:{timeout:e.timeout}}}function Q(e){let{host:t,apiKey:n,timeout:r}=Z(e);return{baseUrl:t,...n?{apiKey:n}:{},timeout:r??6e4}}export{m as C,d as S,_,J as a,p as b,N as c,F as d,L as f,h as g,B as h,G as i,I as l,z as m,Q as n,H as o,R as p,q as r,V as s,Z as t,P as u,t as v,u as x,f as y};
@@ -1 +0,0 @@
1
- import{t as e,u as t}from"./agent-server-client-options-DT2GP6VJ.js";import{t as n}from"./server-client-C3mC8Hl3.js";var r=5e3,i=null,a=e=>Array.isArray(e?.usable_tools)?e.usable_tools:null,o=class extends Error{details;constructor(e){super(`Agent server not found. Could not connect to the configured agent server. Start a compatible agent server and reload the page.`),this.name=`AgentServerUnavailableError`,this.details=e??null}},s=e=>e instanceof o||typeof e==`object`&&!!e&&`name`in e&&e.name===`AgentServerUnavailableError`;function c(){i=null}function l(e){let t=a(i);return Array.isArray(t)?t.includes(e):!0}function u(e){return e instanceof Error&&e.name===`HttpError`&&`status`in e&&typeof e.status==`number`}async function d(){let a=t(),s;try{s=await new n(e({host:a.host,sessionApiKey:a.apiKey||null,timeout:r})).getServerInfo()}catch(e){throw c(),u(e)?e:new o(e instanceof Error?e.message:null)}return i=s,s}export{s as n,d as r,l as t};
@@ -1,5 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/secrets-service-Bwd5DeUs.js","assets/rolldown-runtime-BFRubm34.js","assets/agent-server-client-options-DT2GP6VJ.js","assets/settings-client-CwjfwoiB.js","assets/proxy-CurRmrqf.js","assets/vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~pfbaerbd-zhv9fooy.js"])))=>i.map(i=>d[i]);
2
- import{t as e}from"./preload-helper-CT1Z6Pdu.js";import{C as t,S as n,c as r,i,o as a,s as o,t as s,u as c,y as l}from"./agent-server-client-options-DT2GP6VJ.js";import{n as u,s as d,u as f}from"./vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-CHrEOFl6.js";import{t as p}from"./profiles-client-BGkKEV9j.js";import{t as m}from"./agent-server-compatibility-2aOx5iWd.js";import{n as h,t as g}from"./proxy-CurRmrqf.js";import{t as _}from"./settings-D5am1n6X.js";import{t as ee}from"./common-SMkEaBSr.js";import{a as v,l as y}from"./acp-providers-DauuOsW9.js";import{t as b}from"./settings-service.api-FvJGK45W.js";var x=class{constructor(e){this.host=e.host.replace(/\/$/,``),this.apiKey=e.apiKey,this.client=new a({baseUrl:this.host,apiKey:this.apiKey,timeout:e.timeout||6e4})}async createConversation(e){return(await this.client.post(`/api/conversations`,e)).data}async searchConversations(e={}){return(await this.client.get(`/api/conversations/search`,{params:e})).data}async countConversations(e={}){return(await this.client.get(`/api/conversations/count`,{params:e})).data}async getConversations(e){return(await this.client.get(`/api/conversations`,{params:{ids:e}})).data}async getConversation(e){return(await this.client.get(`/api/conversations/${e}`)).data}async searchEvents(e,t={}){return(await this.client.get(`/api/conversations/${e}/events/search`,{params:t})).data}async getEvent(e,t){return(await this.client.get(`/api/conversations/${e}/events/${t}`)).data}async getEvents(e,t){return Promise.all(t.map(async t=>{try{return await this.getEvent(e,t)}catch(e){if(e instanceof o&&e.status===404)return null;throw e}}))}async sendEvent(e,t,n={}){await this.client.post(`/api/conversations/${e}/events`,{...t,...n.run===void 0?{}:{run:n.run}})}async pauseConversation(e){return(await this.client.post(`/api/conversations/${e}/pause`,{})).data}async interruptConversation(e){return(await this.client.post(`/api/conversations/${e}/interrupt`,{})).data}async runConversation(e){return(await this.client.post(`/api/conversations/${e}/run`,{})).data}async askAgent(e,t){return(await this.client.post(`/api/conversations/${e}/ask_agent`,{question:t})).data}async getEventCount(e,t={}){return(await this.client.get(`/api/conversations/${e}/events/count`,{params:t})).data}async respondToConfirmation(e,t){return(await this.client.post(`/api/conversations/${e}/events/respond_to_confirmation`,t)).data}async getAgentFinalResponse(e){return(await this.client.get(`/api/conversations/${e}/agent_final_response`)).data}async setConfirmationPolicy(e,t){let n=`policy`in t?t:{policy:t};return(await this.client.post(`/api/conversations/${e}/confirmation_policy`,n)).data}async condenseConversation(e){return(await this.client.post(`/api/conversations/${e}/condense`,{})).data}async setSecurityAnalyzer(e,t){let n=te(t)?t:{security_analyzer:t};return(await this.client.post(`/api/conversations/${e}/security_analyzer`,n)).data}async updateSecrets(e,t){return(await this.client.post(`/api/conversations/${e}/secrets`,t)).data}async forkConversation(e,t={},n={}){return(await this.client.post(`/api/conversations/${e}/fork`,t,{params:n.includeSkills===void 0?void 0:{include_skills:n.includeSkills}})).data}async switchProfile(e,t){await this.client.post(`/api/conversations/${e}/switch_profile`,{profile_name:t})}async switchLLM(e,t){await this.client.post(`/api/conversations/${e}/switch_llm`,{llm:t})}async switchAcpModel(e,t){await this.client.post(`/api/conversations/${e}/switch_acp_model`,{model:t})}async deleteConversation(e){await this.client.delete(`/api/conversations/${e}`)}async updateConversation(e,t){return(await this.client.patch(`/api/conversations/${e}`,t)).data}close(){this.client.close()}};function te(e){return typeof e==`object`&&!!e&&`security_analyzer`in e}var S=[];for(let e=0;e<256;++e)S.push((e+256).toString(16).slice(1));function ne(e,t=0){return(S[e[t+0]]+S[e[t+1]]+S[e[t+2]]+S[e[t+3]]+`-`+S[e[t+4]]+S[e[t+5]]+`-`+S[e[t+6]]+S[e[t+7]]+`-`+S[e[t+8]]+S[e[t+9]]+`-`+S[e[t+10]]+S[e[t+11]]+S[e[t+12]]+S[e[t+13]]+S[e[t+14]]+S[e[t+15]]).toLowerCase()}var re=new Uint8Array(16);function ie(){return crypto.getRandomValues(re)}function ae(e,t,n){return!t&&!e&&crypto.randomUUID?crypto.randomUUID():oe(e,t,n)}function oe(e,t,n){e||={};let r=e.random??e.rng?.()??ie();if(r.length<16)throw Error(`Random bytes length must be >= 16`);if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,t){if(n||=0,n<0||n+16>t.length)throw RangeError(`UUID byte range ${n}:${n+15} is out of buffer bounds`);for(let e=0;e<16;++e)t[n+e]=r[e];return t}return ne(r)}var C=`openhands-agent-server-conversation-metadata`,w=()=>{if(typeof window>`u`)return{};try{let e=window.localStorage.getItem(C);if(!e)return{};let t=JSON.parse(e);return!t||typeof t!=`object`?{}:t}catch{return{}}},T=e=>{if(!(typeof window>`u`)){if(Object.keys(e).length===0){window.localStorage.removeItem(C);return}window.localStorage.setItem(C,JSON.stringify(e))}},E=e=>w()[e]??null,D=(e,t)=>{let n=w();n[e]=t,T(n)},O=e=>{let t=w();e in t&&(delete t[e],T(t))};function k(e){if(!e?.id)return e;let t=E(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 e=r().backend;if(e.kind!==`cloud`)throw Error(`Cloud conversations call requires a cloud backend.`);return e}async function se(e=20,t){let n=A(),r=new URLSearchParams;r.set(`limit`,String(e)),t&&r.set(`page_id`,t),r.set(`sort_order`,`UPDATED_AT_DESC`);let i=await g({backend:n,method:`GET`,path:`/api/v1/app-conversations/search?${r.toString()}`});return{items:(i?.items??[]).map(e=>k(e)),next_page_id:i?.next_page_id??null}}async function j(e){if(e.length===0)return[];let t=A(),n=new URLSearchParams;for(let t of e)n.append(`ids`,t);return(await g({backend:t,method:`GET`,path:`/api/v1/app-conversations?${n.toString()}`})??[]).map(k)}async function ce(e){return await g({backend:A(),method:`POST`,path:`/api/v1/app-conversations`,body:e})}async function le(e){return g({backend:A(),method:`GET`,path:`/api/v1/app-conversations/${e}/download`,responseType:`blob`})}async function ue(e){await g({backend:A(),method:`DELETE`,path:`/api/v1/app-conversations/${e}`})}async function de(e,t){return await g({backend:A(),method:`PATCH`,path:`/api/v1/app-conversations/${e}`,body:{public:t}})}async function fe(e){await g({backend:A(),method:`POST`,path:`/api/v1/sandboxes/${e}/pause`})}async function pe(e){await g({backend:A(),method:`POST`,path:`/api/v1/sandboxes/${e}/resume`})}async function me(e,t){let n=A(),r=new URLSearchParams;return r.append(`file_path`,t),await g({backend:n,method:`GET`,path:`/api/v1/app-conversations/${e}/file?${r.toString()}`})??``}async function he(e){let t=A(),n=new URLSearchParams;return n.set(`ids`,e),(await g({backend:t,method:`GET`,path:`/api/v1/app-conversations/start-tasks?${n.toString()}`}))?.[0]??null}var M=`canvas_ui`,ge=`canvas_ui_tool`,_e=[`terminal`,`file_editor`,`task_tracker`,M],N=`browser_tool_set`,P=`task_tool_set`;function ve(){return!0}function ye(){let e=(void 0)?.trim();if(!e)return null;try{let t=JSON.parse(e);return!t||typeof t!=`object`?null:t}catch{return null}}function be(){let e=ye();if(!e?.services)return;let t=[];t.push(`<RUNTIME_SERVICES>`),e.mode?t.push(`You are running inside an agent-canvas dev stack started in '${e.mode}' mode.`):t.push(`You are running inside an agent-canvas dev stack.`),t.push(`The following services are reachable from your sandbox. URLs are written`,`from your point of view (i.e., as you should curl/fetch them).`,``);let{agent_server:n,ingress:r,automation:i}=e.services,a=e.services.frontend??e.services.vite;n?.url_from_agent&&t.push(`* Agent Server (you): ${n.url_from_agent}`,` ${n.description??`The agent-server hosting your tool calls.`}`),r?.url_from_agent&&t.push(`* Ingress: ${r.url_from_agent}`,` ${r.description??`Unified entry point for browser-facing traffic.`}`),a?.url_from_agent&&t.push(`* Frontend: ${a.url_from_agent}`,` ${a.description??`Frontend dev server.`}`),i?.url_from_agent?(t.push(`* Automation backend: ${i.url_from_agent}`,` ${i.description??`OpenHands Automations service.`}`),i.docs_url&&t.push(` Docs: ${i.docs_url}`),i.openapi_url&&t.push(` OpenAPI: ${i.openapi_url}`),i.auth_env_var&&t.push(` Auth: header 'X-API-Key: $${i.auth_env_var}'`)):t.push(`* Automation backend: not running in this dev mode (skip /api/automation calls).`);let o=n?.url_from_agent;return t.push(``,`Trust this block over guessing: do not assume any other URLs are running.`),o&&t.push(`In particular, ${o} inside your sandbox is the Agent Server`,`you are running inside of — NOT the automation backend.`),t.push(`</RUNTIME_SERVICES>`),t.join(`
3
- `)}function xe(e){let{host:t}=s();return`${t}/api/conversations/${e}`}function F(e){return`Conversation ${e.slice(0,5)}`}function I(e){let t=E(e.id),r=e.agent?.kind===`ACPAgent`,i=r?e.tags?.acpserver??null:null;return{id:e.id,created_by_user_id:null,selected_repository:t?.selected_repository??null,selected_branch:t?.selected_branch??null,git_provider:t?.git_provider??null,selected_workspace:t?.selected_workspace??null,title:e.title?.trim()?e.title:F(e.id),trigger:null,pr_number:[],agent_kind:r?`acp`:`openhands`,acp_server:i,llm_model:r?y({runtimeName:e.current_model_name,runtimeId:e.current_model_id,configured:e.agent?.acp_model,sdkLlm:e.agent?.llm?.model}):e.agent?.llm?.model??_.llm_model,metrics:e.metrics?{accumulated_cost:e.metrics.accumulated_cost??null,max_budget_per_task:e.metrics.max_budget_per_task??null,accumulated_token_usage:e.metrics.accumulated_token_usage?{prompt_tokens:e.metrics.accumulated_token_usage.prompt_tokens??0,completion_tokens:e.metrics.accumulated_token_usage.completion_tokens??0,cache_read_tokens:e.metrics.accumulated_token_usage.cache_read_tokens??0,cache_write_tokens:e.metrics.accumulated_token_usage.cache_write_tokens??0,context_window:e.metrics.accumulated_token_usage.context_window??0,per_turn_token:e.metrics.accumulated_token_usage.per_turn_token??0}:null}:null,created_at:e.created_at,updated_at:e.updated_at,execution_status:e.execution_status??ee.IDLE,sandbox_status:e.sandbox_status??null,conversation_url:xe(e.id),session_api_key:s().apiKey??null,sandbox_id:null,workspace:{working_dir:e.workspace?.working_dir??n()},public:!1,sub_conversation_ids:[]}}function Se(e){return{items:e.items.map(I),next_page_id:e.next_page_id??null}}var L=[`acp_command`,`acp_args`,`acp_env`,`acp_model`,`acp_session_mode`,`acp_prompt_timeout`],Ce=`acpserver`,we=new Set([`schema_version`,`agent_settings`,`workspace`,`conversation_id`,`initial_message`,`plugins`]);function R(e){return!e||typeof e!=`object`||Array.isArray(e)?{}:structuredClone(e)}function z(e){if(typeof e!=`string`)return;let t=e.trim();return t.length>0?t:void 0}function Te(e){return e.confirmation_mode===!0?e.security_analyzer===`llm`?{kind:`ConfirmRisky`,threshold:`HIGH`,confirm_unknown:!0}:{kind:`AlwaysConfirm`}:{kind:`NeverConfirm`}}function Ee(e){switch(e.security_analyzer){case`llm`:return{kind:`LLMSecurityAnalyzer`};case`pattern`:return{kind:`PatternSecurityAnalyzer`};case`policy_rail`:return{kind:`PolicyRailSecurityAnalyzer`};default:return}}function De(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&typeof e.name==`string`}function B(e,t){return e===N?ve()&&m(e):e===P?t.enable_sub_agents===!0&&m(e):!0}function Oe(e){let t=new Map;for(let e of _e)t.set(e,{name:e,params:{}});for(let n of[N,P])B(n,e)&&t.set(n,{name:n,params:{}});let n=e.tools;if(Array.isArray(n)&&n.every(e=>De(e)))for(let r of n)B(r.name,e)&&t.set(r.name,{name:r.name,params:R(r.params)});return Array.from(t.values())}function ke(e,t){let n=[e?.trim(),t?.trim()].filter(Boolean);return n.length===0?null:{role:`user`,content:[{type:`text`,text:n.join(`
4
-
5
- `)}],run:!0}}function V(e){let n=be();return{...R(e.agent_context),load_public_skills:t(),load_user_skills:!0,load_project_skills:!0,...n?{system_message_suffix:n}:{}}}function H(e){return R(e.agent_settings).agent_kind===`acp`}function Ae(e){let t=R(e.agent_settings).acp_server;return typeof t==`string`&&t.length>0?t:void 0}function je(e){let t=e.acp_command;if(!(Array.isArray(t)&&t.length===0)&&t!==void 0)return t;let n=v(typeof e.acp_server==`string`?e.acp_server:void 0);return n?[...n.default_command]:t}function Me(e){let t=R(e.agent_settings),n={agent_kind:`acp`,agent_context:V(t)};for(let e of L){if(e===`acp_model`)continue;let r=e===`acp_command`?je(t):t[e];r!=null&&(n[e]=r)}let r=v(typeof t.acp_server==`string`?t.acp_server:void 0),i=y({configured:t.acp_model,providerDefault:r?.default_model});return i&&(n.acp_model=i),n}function Ne(e){let t=R(e.agent_settings),n=R(t.llm);n.model=typeof n.model==`string`?n.model:_.llm_model;let r=z(n.api_key);r?n.api_key=r:delete n.api_key;let i=z(n.base_url);i?n.base_url=i:delete n.base_url;let a=R(t.mcp_config);(Object.keys(a).length===0||!(`mcpServers`in a))&&delete t.mcp_config,delete t.acp_server;for(let e of L)delete t[e];return{...t,llm:n,agent_context:V(t),tools:Oe(t)}}function Pe(e){return H(e)?Me(e):Ne(e)}function Fe(e){let{settings:t,query:r,conversationInstructions:i,plugins:a,workingDir:o}=e,s=R(t.conversation_settings),c=ke(r,i);return we.forEach(e=>delete s[e]),{...s,workspace:{kind:`LocalWorkspace`,working_dir:o??n()},...c?{initial_message:c}:{},...a?.length?{plugins:a.map(e=>({source:e.source,...e.ref?{ref:e.ref}:{},...e.repo_path?{repo_path:e.repo_path}:{}}))}:{}}}function Ie(e){let t=e.encryptedAgentSettings?{...e.settings,agent_settings:e.encryptedAgentSettings}:e.settings,n=H(t),r=Pe(t),i=n?Ae(t):void 0,a=Fe(e.encryptedConversationSettings?{...e,settings:{...e.settings,conversation_settings:e.encryptedConversationSettings}}:e),o={agent_settings:r,workspace:a.workspace,confirmation_policy:Te(a),max_iterations:typeof a.max_iterations==`number`?a.max_iterations:500,stuck_detection:!0,autotitle:!0,worktree:!0};i&&(o.tags={[Ce]:i}),e.secretsEncrypted&&(o.secrets_encrypted=!0),e.conversationId&&(o.conversation_id=e.conversationId);let s=Ee(a);if(s&&(o.security_analyzer=s),a.initial_message&&(o.initial_message=a.initial_message),a.plugins&&(o.plugins=a.plugins),a.hook_config&&(o.hook_config=a.hook_config),o.tool_module_qualnames={[M]:ge,...a.tool_module_qualnames??{}},a.agent_definitions&&(o.agent_definitions=a.agent_definitions),e.customSecrets&&e.customSecrets.length>0){let t=h(c()),r={};for(let n of e.customSecrets){let e={kind:`LookupSecret`,url:`/api/settings/secrets/${encodeURIComponent(n.name)}`,description:n.description};Object.keys(t).length>0&&(e.headers=t),r[n.name]=e}o.secrets=r,n&&(o.agent_settings.agent_context={...o.agent_settings.agent_context,secrets:r})}return o}async function Le(t){let{SecretsService:n}=await e(async()=>{let{SecretsService:e}=await import(`./secrets-service-Bwd5DeUs.js`).then(e=>e.n);return{SecretsService:e}},__vite__mapDeps([0,1,2,3,4,5])),[r,i]=await Promise.all([b.getSettingsForConversation(),n.getSecrets()]),{agentSettings:a,conversationSettings:o,secretsEncrypted:s}=r;return Ie({...t,encryptedAgentSettings:a,encryptedConversationSettings:o,secretsEncrypted:s,customSecrets:i})}function Re(){return{hooks:[]}}var ze=`1970-01-01T00:00:00.000Z`,Be=`Unable to load conversations because the selected agent server returned data this UI does not understand. Check the backend URL/session key and update the agent server if needed.`,Ve=`Unable to switch LLM profiles because the selected agent server returned profile data this UI does not understand. Check the backend URL/session key and update the agent server if needed.`;function U(){return Error(Be)}function W(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function He(e){return W(e)&&typeof e.model==`string`}function G(e){return typeof e==`number`?e:null}function K(e){return typeof e==`number`?e:0}function q(e){return typeof e==`string`?e:null}function J(e,t,n){let r=e[t]??e[n];return typeof r==`string`&&r.trim()?r:ze}function Ue(e){return W(e)?{prompt_tokens:K(e.prompt_tokens),completion_tokens:K(e.completion_tokens),cache_read_tokens:K(e.cache_read_tokens),cache_write_tokens:K(e.cache_write_tokens),context_window:K(e.context_window),per_turn_token:K(e.per_turn_token)}:null}function Y(e){return W(e)?{accumulated_cost:G(e.accumulated_cost),max_budget_per_task:G(e.max_budget_per_task),accumulated_token_usage:Ue(e.accumulated_token_usage)}:null}function We(e){if(!W(e))return null;let t=W(e.llm)?{model:q(e.llm.model)}:null;return{kind:q(e.kind),acp_model:q(e.acp_model),llm:t}}function Ge(e){return W(e)?{working_dir:q(e.working_dir)}:null}function Ke(e){if(!W(e))return null;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function X(e){if(!e.startsWith(`/`))return null;let t=[];for(let n of e.split(`/`))if(n&&n!==`.`)if(n===`..`){if(!t.length)return null;t.pop()}else t.push(n);return`/${t.join(`/`)}`}function Z(e,t){let n=X(e),r=X(t);if(!n||!r||n!==r&&!n.startsWith(`${r}/`))throw Error(`Conversation file path must stay inside the workspace`);return n}function Q(e){if(!W(e)||typeof e.id!=`string`||!e.id.trim())throw U();return{id:e.id.trim(),title:q(e.title),created_at:J(e,`created_at`,`createdAt`),updated_at:J(e,`updated_at`,`updatedAt`),execution_status:q(e.execution_status),sandbox_status:q(e.sandbox_status),metrics:Y(e.metrics),agent:We(e.agent),workspace:Ge(e.workspace),tags:Ke(e.tags),current_model_id:q(e.current_model_id),current_model_name:q(e.current_model_name)}}function $(e){if(!Array.isArray(e))throw U();return e.map(Q)}function qe(e){if(Array.isArray(e))return{items:$(e),next_page_id:null};if(!W(e))throw U();return{items:$(e.items),next_page_id:typeof e.next_page_id==`string`?e.next_page_id:null}}var Je=new Set([`idle`,`running`,`paused`,`waiting_for_confirmation`,`finished`,`error`,`stuck`]);function Ye(e){let t=e??`idle`;return Je.has(t)?t:`idle`}function Xe(e,t){if(!e)throw Error(`Conversation ${t} was not found`);return e}var Ze=class{static async sendMessage(e,t,n){let a=r().backend,o=n?.conversationUrl??null,c=n?.sessionApiKey??null;if(a.kind===`cloud`){if(!o||!c){let[t]=await j([e]);o=t?.conversation_url?.trim()??null,c=t?.session_api_key?.trim()??null}if(!o||!c)throw Error(`Conversation sandbox is still starting. Wait for it to finish, then try again.`);return await g({backend:a,method:`POST`,hostOverride:i(o),path:`/api/conversations/${e}/events`,body:{...t,run:!0},authMode:`session-api-key`,sessionApiKey:c}),t}return await new x(s({conversationUrl:o,sessionApiKey:c})).sendEvent(e,t,{run:!0}),t}static async createConversation(e,t,n,i,a,o,u,d){if(r().backend.kind===`cloud`)return ce({initial_message:e?{role:`user`,content:[{type:`text`,text:e}]}:null,title:t??null,selected_repository:i?.selected_repository??null,selected_branch:i?.selected_branch??null,git_provider:i?.git_provider??null,plugins:n??null,parent_conversation_id:o??null,agent_type:u,sandbox_id:d??null});let f=await b.getSettings(),p=ae(),m=await Le({settings:f,query:e,conversationInstructions:t,plugins:n,conversationId:p,workingDir:a??l(p)}),h=await new x(s()).createConversation(m);return(i?.selected_repository||a)&&D(h.id,{selected_repository:i?.selected_repository??null,selected_branch:i?.selected_branch??null,git_provider:i?.git_provider??null,selected_workspace:a??null}),{id:h.id,created_by_user_id:null,status:`READY`,detail:null,app_conversation_id:h.id,agent_server_url:c().host,request:{initial_message:m.initial_message,plugins:n??null},created_at:h.created_at,updated_at:h.updated_at}}static async getStartTask(e){return r().backend.kind===`cloud`?he(e):null}static async getVSCodeUrl(e,t,n){let r=await this.resolveConversationWorkingDir(e);return{vscode_url:await new d(s({conversationUrl:t,sessionApiKey:n})).getUrl({baseUrl:typeof window<`u`?window.location.origin:void 0,workspaceDir:r})}}static async resolveConversationWorkingDir(e){let[t]=await this.batchGetAppConversations([e]);return t?.workspace?.working_dir??n()}static async batchGetAppConversations(e){return e.length===0?[]:r().backend.kind===`cloud`?j(e):$(await new x(s()).getConversations(e)).map(e=>I(e))}static async updateConversationPublicFlag(e,t){if(r().backend.kind!==`cloud`)throw Error(`Public sharing requires a cloud backend.`);return de(e,t)}static async updateConversationRepository(e,t,n,r){t?D(e,{...E(e)??{},selected_repository:t,selected_branch:n??null,git_provider:r??null}):O(e);let[i]=await this.batchGetAppConversations([e]);return Xe(i,e)}static async readConversationFile(e,t){if(r().backend.kind===`cloud`)return me(e,Z(t??`/workspace/project/.agents_tmp/PLAN.md`,`/workspace/project`));let n=await this.resolveConversationWorkingDir(e),i=Z(t??`${n}/.agents_tmp/PLAN.md`,n);return new f(s()).downloadTextFile(i)}static async downloadConversation(e){return r().backend.kind===`cloud`?le(e):new f(s()).downloadTrajectory(e)}static async getHooks(e){return Re()}static async getRuntimeConversation(e,t,n){let a=r().backend,o=a.kind===`cloud`&&t?await g({backend:a,method:`GET`,hostOverride:i(t),path:`/api/conversations/${e}`,authMode:`session-api-key`,sessionApiKey:n}):await new x(s({conversationUrl:t,sessionApiKey:n})).getConversation(e),c=Q(o),l=W(o)?o.stats:null;return{id:c.id,title:c.title?.trim()?c.title:F(c.id),metrics:Y(c.metrics),created_at:c.created_at,updated_at:c.updated_at,status:Ye(c.execution_status),stats:W(l)?l:{usage_to_metrics:{}}}}static async searchConversations(e=20,t){return r().backend.kind===`cloud`?se(e,t):Se(qe(await new x(s()).searchConversations({limit:e,page_id:t,sort_order:u.UPDATED_AT_DESC})))}static async deleteConversation(e){r().backend.kind===`cloud`?await ue(e):await new x(s()).deleteConversation(e),O(e)}static async updateConversationTitle(e,t){await new x(s()).updateConversation(e,{title:t});let[n]=await this.batchGetAppConversations([e]);return Xe(n,e)}static async switchProfile(e,t){if(r().backend.kind===`cloud`)throw Error(`LLM profile switching is only supported for local agent-server backends.`);let n=new p(s());if(!e){await n.activateProfile(t);return}let i=await n.getProfile(t,{exposeSecrets:`encrypted`});if(!He(i.config))throw Error(Ve);await new x(s()).switchLLM(e,i.config)}static async switchAcpModel(e,t){if(r().backend.kind===`cloud`)throw Error(`ACP model switching is only supported for local agent-server backends.`);await new x(s()).switchAcpModel(e,t)}};export{E as a,pe as i,j as n,ae as o,fe as r,x as s,Ze as t};
@@ -1 +0,0 @@
1
- import{t as e}from"./react-Do0CT17Y.js";var t={url:`https://github.com/OpenHands/OpenHands`,screenshotSrc:``},n=e(e=>({...t,setUrl:t=>e({url:t}),setScreenshotSrc:t=>e({screenshotSrc:t}),reset:()=>e(t)}));export{n as t};
@@ -1 +0,0 @@
1
- import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{o as n,t as r}from"./declaration-D378OjpZ.js";import{t as i}from"./useTranslation-CpIcQBq6.js";import{t as a}from"./use-conversation-id-DajhCn2A.js";import{t as o}from"./browser-store-C3AqxAO7.js";import{t as s}from"./vendor~browser-tab-BiVxfjJo.js";import{t as c}from"./conversation-tab-empty-state-D8dNvo-V.js";var l=e(t(),1),u=n();function d({src:e}){let{t}=i(`openhands`);return(0,u.jsx)(`img`,{src:e,className:`rounded-xl object-contain w-full h-auto`,alt:t(r.BROWSER$SCREENSHOT_ALT)})}function f(){let{t:e}=i(`openhands`);return(0,u.jsx)(c,{icon:(0,u.jsx)(s,{}),children:e(r.BROWSER$NO_PAGE_LOADED)})}function p(){let{url:e,screenshotSrc:t,reset:n}=o(),{conversationId:r}=a();(0,l.useEffect)(()=>{n()},[r,n]);let i=t?.startsWith(`data:image/png;base64,`)?t:`data:image/png;base64,${t??``}`;return(0,u.jsxs)(`div`,{className:`h-full w-full flex flex-col text-[var(--oh-muted)]`,children:[(0,u.jsx)(`div`,{className:`w-full p-2 truncate border-b border-[var(--oh-border)]`,children:e}),(0,u.jsx)(`div`,{className:`overflow-y-auto grow scrollbar-hide rounded-xl`,children:t?(0,u.jsx)(d,{src:i}):(0,u.jsx)(f,{})})]})}function m(){return(0,u.jsx)(p,{})}export{m as default};