@openhands/agent-canvas 1.13.0 → 1.14.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 (437) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{acp-providers-D1PORKc0.js → acp-providers-CYy8qA2z.js} +1 -1
  4. package/build/assets/active-backend-context-BZDG15C0.js +2 -0
  5. package/build/assets/{agent-context-settings-DMrObcIS.js → agent-context-settings-DGWBBbcp.js} +1 -1
  6. package/build/assets/{agent-profiles-settings-DororXN5.js → agent-profiles-settings-DrkGdf4_.js} +1 -1
  7. package/build/assets/{agent-server-conversation-service.api-DWBe0rbX.js → agent-server-conversation-service.api-DK56YPTs.js} +7 -7
  8. package/build/assets/{agent-settings-BJVk92PU.js → agent-settings-DfcSgkLD.js} +2 -2
  9. package/build/assets/agent-settings-Lrc5-twS.js +1 -0
  10. package/build/assets/{alert-banner-CzZsm7ms.js → alert-banner-BgDHhL7b.js} +1 -1
  11. package/build/assets/api-error-message-BEIE_yD1.js +1 -0
  12. package/build/assets/{api-key-entry-screen-D8Fade_-.js → api-key-entry-screen-DaZnOlVo.js} +1 -1
  13. package/build/assets/{app-settings-CpyGB3AT.js → app-settings-BG5NAUbC.js} +1 -1
  14. package/build/assets/automation-detail-D4Hs831Z.js +3 -0
  15. package/build/assets/automation-export-n0X6FB0C.js +2 -0
  16. package/build/assets/automation-git-sync-CDrm8WV7.js +1 -0
  17. package/build/assets/automation-setup-route-CZCl4ONs.js +1 -0
  18. package/build/assets/{automation-templates-DgpCGOJV.js → automation-templates-DFF96AdL.js} +1 -1
  19. package/build/assets/automations-list-Bl-oGOrV.js +1 -0
  20. package/build/assets/{back-nav-button-HHEneWMw.js → back-nav-button-H_ThtDA0.js} +1 -1
  21. package/build/assets/{backend-form-modal-DiVrD4Cm.js → backend-form-modal-CbCemvHt.js} +1 -1
  22. package/build/assets/backend-not-configured-DP8KLNq_.js +1 -0
  23. package/build/assets/{backend-synced-settings-badge-7MIjpr8M.js → backend-synced-settings-badge-BBASWqsb.js} +1 -1
  24. package/build/assets/{badge-CpYmcVZV.js → badge-B-51h-SW.js} +1 -1
  25. package/build/assets/{base-modal-Fnh6Uln9.js → base-modal-BbjycA8X.js} +1 -1
  26. package/build/assets/{bot-BQZx8e2i.js → bot-CGPCg03p.js} +1 -1
  27. package/build/assets/{brand-button-swT1RyO0.js → brand-button-Blxv5nww.js} +1 -1
  28. package/build/assets/browser-CuW0nWvh.js +7 -0
  29. package/build/assets/{browser-tab-zAY12m_i.js → browser-tab-D5G0ORwt.js} +1 -1
  30. package/build/assets/{chat-send-button-DsJtivmL.js → chat-send-button-BD2tii1r.js} +1 -1
  31. package/build/assets/check-DSuS-lyr.js +1 -0
  32. package/build/assets/chevron-down-CgGcmtE2.js +1 -0
  33. package/build/assets/circle-check-CG5-NPw7.js +1 -0
  34. package/build/assets/{circle-plus-check-toggle-Cuzx55bo.js → circle-plus-check-toggle-ASbpB8vN.js} +1 -1
  35. package/build/assets/{cloud-funnel-analytics-86CwNdSh.js → cloud-funnel-analytics-GlCUG0gk.js} +1 -1
  36. package/build/assets/cog-CZiR80uT.js +1 -0
  37. package/build/assets/{combobox-caret-D0fRotFi.js → combobox-caret-DvpEsh2O.js} +1 -1
  38. package/build/assets/{command-menu-BXy03FBl.js → command-menu-DwUQzjYP.js} +1 -1
  39. package/build/assets/{condenser-settings-BmZa0ui_.js → condenser-settings-BptcoiLA.js} +1 -1
  40. package/build/assets/{confirmation-modal-BgoN6lbN.js → confirmation-modal-CiEwxZAA.js} +1 -1
  41. package/build/assets/{context-menu-list-item-Bq02tc-P.js → context-menu-list-item-CdcamfM1.js} +1 -1
  42. package/build/assets/conversation-DREHj4nT.js +1 -0
  43. package/build/assets/conversation-DotRfiDz.js +90 -0
  44. package/build/assets/conversation-panel-DREHj4nT.js +1 -0
  45. package/build/assets/conversation-state-store-DMLtlHbE.js +1 -0
  46. package/build/assets/{conversation-tab-empty-state-CMqo_0Bd.js → conversation-tab-empty-state-D-puECpY.js} +1 -1
  47. package/build/assets/{copy-to-clipboard-button-Cg1pF0xn.js → copy-to-clipboard-button-BGxcUbgy.js} +1 -1
  48. package/build/assets/{device-verify-BfQLgNyq.js → device-verify-CZJfWaJf.js} +1 -1
  49. package/build/assets/{dropdown-classes-BIqQr5mx.js → dropdown-classes-tLhpwtxS.js} +1 -1
  50. package/build/assets/{entry.client-CxFjRYqH.js → entry.client-D8GnI6GZ.js} +2 -2
  51. package/build/assets/{enum-filter-dropdown-C_yV4_bo.js → enum-filter-dropdown-Fk8k60nk.js} +1 -1
  52. package/build/assets/{environment-switch-overlay-Bi4qbh2g.js → environment-switch-overlay-DeztVYuL.js} +1 -1
  53. package/build/assets/{extensions-hub-BqUINAhp.js → extensions-hub-Cd6GCYzq.js} +1 -1
  54. package/build/assets/{extensions-navigation-lraj88Wk.js → extensions-navigation-C4sgZg-y.js} +1 -1
  55. package/build/assets/{external-link-CgtpA_a1.js → external-link-C0UpBgsE.js} +1 -1
  56. package/build/assets/{file-text-DEK4LSVw.js → file-text-C6WYtNdV.js} +1 -1
  57. package/build/assets/files-tab-BW_qzyAm.js +1 -0
  58. package/build/assets/{form-control-classes-7yFSQJq_.js → form-control-classes-CGXBLcn1.js} +1 -1
  59. package/build/assets/format-model-name-BNPKVsIq.js +1 -0
  60. package/build/assets/format-relative-time-ZhQD4rsl.js +1 -0
  61. package/build/assets/git-provider-icon-CaQ1yLPi.js +1 -0
  62. package/build/assets/{git-repo-dropdown-ByMzpNko.js → git-repo-dropdown-CgXR6M_E.js} +1 -1
  63. package/build/assets/git-repo-dropdown-D2Uei3CO.js +1 -0
  64. package/build/assets/{highlighted-source-view-C_sfncLZ.js → highlighted-source-view-C_YOp8Fo.js} +1 -1
  65. package/build/assets/home-DNzzJcMP.js +1 -0
  66. package/build/assets/home-aCos-5vc.js +1 -0
  67. package/build/assets/{home-store-CxqsY9Fi.js → home-store-DgzViC3f.js} +1 -1
  68. package/build/assets/index-home-DNzzJcMP.js +1 -0
  69. package/build/assets/info-CLoC1LRo.js +1 -0
  70. package/build/assets/install-server-modal-D7zIqNKz.js +1 -0
  71. package/build/assets/kebab-menu-item-content-DERMdnDv.js +1 -0
  72. package/build/assets/{launch-CkqiSCqi.js → launch-5PjKeLak.js} +1 -1
  73. package/build/assets/{list-todo-DNWlzfaM.js → list-todo-BF049YaY.js} +1 -1
  74. package/build/assets/llm-not-configured-banner-BK9z5eS0.js +27 -0
  75. package/build/assets/llm-settings-BLAMK2tR.js +1 -0
  76. package/build/assets/llm-settings-BWsbarGM.js +1 -0
  77. package/build/assets/{llm-subscription-service-BAdOl5Xx.js → llm-subscription-service-SfnEV9Uc.js} +1 -1
  78. package/build/assets/loader-circle-D7IagAyF.js +1 -0
  79. package/build/assets/{loading-spinner-xhnrGP4Y.js → loading-spinner-DBgXgra0.js} +1 -1
  80. package/build/assets/{manage-backends-modal-DhGk5mJt.js → manage-backends-modal-BTqNPhzc.js} +1 -1
  81. package/build/assets/manifest-abebca3c.js +1 -0
  82. package/build/assets/manifest-subpage-layout-Rn-glaxV.js +1 -0
  83. package/build/assets/{map-provider-Mx8mZuE-.js → map-provider-BK4HnqYz.js} +1 -1
  84. package/build/assets/markdown-renderer-Cp6DlHQN.js +8 -0
  85. package/build/assets/{mcp-DCkvl6K0.js → mcp-BC-Ixn4T.js} +2 -2
  86. package/build/assets/{mcp-marketplace-utils-DEbMXlQr.js → mcp-marketplace-utils-BJWJgbB6.js} +1 -1
  87. package/build/assets/{messages-DSXvyc21.js → messages-CzFKrzPG.js} +5 -5
  88. package/build/assets/{modal-body-gIe21fDv.js → modal-body-BdKfD3Hl.js} +1 -1
  89. package/build/assets/{modal-classes-D66dlgZ7.js → modal-classes-D5_b5vMi.js} +1 -1
  90. package/build/assets/{modal-close-button-B6iOGYpI.js → modal-close-button-objukxk_.js} +1 -1
  91. package/build/assets/{mouse-pointer-click-BYX1Pw5W.js → mouse-pointer-click-C_gXyLyD.js} +1 -1
  92. package/build/assets/{npm-DLckoeJc.js → npm-CHVHV1MC.js} +1 -1
  93. package/build/assets/{onboarding-D7WDG66N.js → onboarding-Diw0V51A.js} +1 -1
  94. package/build/assets/onboarding-modal-Da4yHzsA.js +1 -0
  95. package/build/assets/{organization-service.api-D-s9z18a.js → organization-service.api-BztSy69u.js} +1 -1
  96. package/build/assets/parse-git-remote-url-BkXN9jzl.js +1 -0
  97. package/build/assets/{pencil-BGOCPRyu.js → pencil-49avMHlD.js} +1 -1
  98. package/build/assets/{planner-tab-AKaXIIfg.js → planner-tab-CJiSpNax.js} +1 -1
  99. package/build/assets/{plugins-management-service-wtmY4QQw.js → plugins-management-service-lHdNKWNU.js} +1 -1
  100. package/build/assets/plus-C0BagBpV.js +1 -0
  101. package/build/assets/profiles-service.api-BLr7FXec.js +1 -0
  102. package/build/assets/providers-CWXnb7S3.js +1 -0
  103. package/build/assets/{proxy-9Z_WZggZ.js → proxy-DYDXxtje.js} +1 -1
  104. package/build/assets/{puzzle-BWLmN8z4.js → puzzle-Bt2B1rzf.js} +1 -1
  105. package/build/assets/recommended-automations-launcher-CcFMfJRR.js +1 -0
  106. package/build/assets/{refresh-cw-CXtFWpwv.js → refresh-cw-nmcesifB.js} +1 -1
  107. package/build/assets/root-CT4t7apy.css +1 -0
  108. package/build/assets/root-DnRgLKpU.js +2 -0
  109. package/build/assets/root-layout-2L9tr-BN.js +2 -0
  110. package/build/assets/{schema-field-OnM5Uob_.js → schema-field-C59lVZTA.js} +1 -1
  111. package/build/assets/{sdk-section-page-m5WQm2sy.js → sdk-section-page-BbBEQQjq.js} +1 -1
  112. package/build/assets/search-CYSDBczG.js +1 -0
  113. package/build/assets/secrets-service-BtsgYSlj.js +1 -0
  114. package/build/assets/secrets-settings-DJ0OKa4_.js +1 -0
  115. package/build/assets/{segmented-toggle-DCspm2U5.js → segmented-toggle-DiVfTZuN.js} +1 -1
  116. package/build/assets/{settings-BJQI_iBM.js → settings-CDqL_Uqh.js} +1 -1
  117. package/build/assets/{settings-CWFxymAf.js → settings-DcNPxz0v.js} +1 -1
  118. package/build/assets/{settings-dropdown-input-BI8V_Nov.js → settings-dropdown-input-Ba1UN5Du.js} +1 -1
  119. package/build/assets/{settings-index-BiTqJoH7.js → settings-index-Cz2cKt2K.js} +1 -1
  120. package/build/assets/{settings-input-Cz62hWVW.js → settings-input-CWUEHHvS.js} +1 -1
  121. package/build/assets/{settings-list-classes-z_3FW5H3.js → settings-list-classes-DdcLXDGn.js} +1 -1
  122. package/build/assets/{settings-modal-BIrIVn97.js → settings-modal-nEEK1Kh1.js} +1 -1
  123. package/build/assets/{settings-service.api--rJmnuLa.js → settings-service.api-3yAUFcaP.js} +1 -1
  124. package/build/assets/{settings-switch-BRsSI8Vs.js → settings-switch-Dk9hChx1.js} +1 -1
  125. package/build/assets/{settings-utils-Ba7vel6T.js → settings-utils-CxjtCSB3.js} +1 -1
  126. package/build/assets/{shared-conversation-CQK_PqHx.js → shared-conversation-DbAcrx3s.js} +1 -1
  127. package/build/assets/{shield-check-T3JsDJiM.js → shield-check-CiOTXxV2.js} +1 -1
  128. package/build/assets/{sidebar-layout-Bhi3hVcu.js → sidebar-layout-lrfPooIB.js} +1 -1
  129. package/build/assets/{sidebar-mobile-menu-toggle-YWJNRN4p.js → sidebar-mobile-menu-toggle-KERXfNu1.js} +1 -1
  130. package/build/assets/{sidebar-nav-link-BSUlY5Ml.js → sidebar-nav-link-B8lFD6Cb.js} +1 -1
  131. package/build/assets/{sidebar-store-Cl1cUv_F.js → sidebar-store-u6pUpxJ7.js} +1 -1
  132. package/build/assets/{skill-card-pill-row-BXz8L8Rn.js → skill-card-pill-row-dGIUzr_b.js} +1 -1
  133. package/build/assets/{skill-icon-badge-QgfKv31M.js → skill-icon-badge-kkOWZ89w.js} +1 -1
  134. package/build/assets/{skill-scope-Dc3JPW-8.js → skill-scope-DWN1PBPH.js} +1 -1
  135. package/build/assets/{skills-plugins-CpTV27n3.js → skills-plugins-DFjH2Nq6.js} +1 -1
  136. package/build/assets/{skills-settings-CSW__IW4.js → skills-settings-DIHpl3ol.js} +2 -2
  137. package/build/assets/{sparkles-TJ0mdECe.js → sparkles-ntyMLnbj.js} +1 -1
  138. package/build/assets/{styled-tooltip-BUMSbgrF.js → styled-tooltip-B6JXcsmL.js} +1 -1
  139. package/build/assets/{task-list-tab-mAHMOkUz.js → task-list-tab-aEJzEcHD.js} +1 -1
  140. package/build/assets/{terminal-BzxBaHx2.js → terminal-Dch7Ty5K.js} +1 -1
  141. package/build/assets/{toggle-switch-O5v1FgxW.js → toggle-switch-B2MLKsgt.js} +1 -1
  142. package/build/assets/{trash-2-C0xNVp9c.js → trash-2-yZnDM4Ji.js} +1 -1
  143. package/build/assets/{typography-NOKSk9_R.js → typography-DB5HoCk0.js} +1 -1
  144. package/build/assets/usage-tab-DrEtBmBT.js +1 -0
  145. package/build/assets/use-acp-credential-form-c8KXAa8A.js +1 -0
  146. package/build/assets/{use-activate-agent-profile-D9YRQPTF.js → use-activate-agent-profile-B0p34N3q.js} +1 -1
  147. package/build/assets/use-agent-profiles-CPIc6wLH.js +1 -0
  148. package/build/assets/{use-can-manage-org-profiles-Dxzq2AEd.js → use-can-manage-org-profiles-Dz_8Eqkv.js} +1 -1
  149. package/build/assets/{use-cloud-current-user-id-Co2eJk2A.js → use-cloud-current-user-id-DvUVqCle.js} +1 -1
  150. package/build/assets/use-config-C3PO4TBw.js +1 -0
  151. package/build/assets/{use-create-conversation-CoHTiCbI.js → use-create-conversation-DVrA_uLD.js} +1 -1
  152. package/build/assets/use-create-secret-DbBIpaCR.js +1 -0
  153. package/build/assets/use-get-secrets-6PBitf54.js +1 -0
  154. package/build/assets/use-has-permission-CQ31Cl8j.js +1 -0
  155. package/build/assets/use-is-authed-2UrDIziV.js +1 -0
  156. package/build/assets/use-is-creating-conversation-BvYpmb3v.js +1 -0
  157. package/build/assets/use-llm-profiles-diZS4FiN.js +1 -0
  158. package/build/assets/use-manifest-capabilities-HIWCtIUm.js +1 -0
  159. package/build/assets/{use-onboarding-completion-CCE8OQgV.js → use-onboarding-completion-Bs8PcXik.js} +1 -1
  160. package/build/assets/{use-plugins-marketplace-CEiak69h.js → use-plugins-marketplace-BCuNLFsr.js} +1 -1
  161. package/build/assets/use-save-agent-profile-BaMNSpBV.js +1 -0
  162. package/build/assets/{use-save-settings-DNmnbG6f.js → use-save-settings-BahvC2Gw.js} +1 -1
  163. package/build/assets/{use-settings-wCwPaSIv.js → use-settings-C6ZxpBDX.js} +1 -1
  164. package/build/assets/{use-settings-nav-items-BlFL7YhM.js → use-settings-nav-items-Bqn69Ggw.js} +2 -2
  165. package/build/assets/use-tracking-Bhu7gk2y.js +3 -0
  166. package/build/assets/{use-user-conversation-DVtfg0B_.js → use-user-conversation-BkNXpXrd.js} +1 -1
  167. package/build/assets/{useInfiniteQuery-p1xq35r2.js → useInfiniteQuery-c_OmS3lK.js} +1 -1
  168. package/build/assets/{useMutation-BFDQmgk9.js → useMutation-6ZsQCqAn.js} +1 -1
  169. package/build/assets/{useQueries-DF1NAAeC.js → useQueries-xDrGlTO_.js} +1 -1
  170. package/build/assets/{useQuery-DRv--6bK.js → useQuery-Bs5NFz2s.js} +1 -1
  171. package/build/assets/{utils-zxEjKE70.js → utils-DUD5ScdA.js} +1 -1
  172. package/build/assets/{vendor~entry.client-CgNUwtQL.js → vendor~entry.client-BFE7Llz9.js} +1 -1
  173. package/build/assets/{vendor~entry.client-zSIea5EO.js → vendor~entry.client-BaKt_PIp.js} +1 -1
  174. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kv3pap4j-B8i84bh4.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kepq2zme-D87mAf6K.js} +1 -1
  175. package/build/assets/{vendor~files-tab-D9wR9yM2.js → vendor~files-tab-B6POTS66.js} +1 -1
  176. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-Ipoe6hvY.js → vendor~index-home~home~conversation-panel~conversation-53Q_U6uP.js} +1 -1
  177. package/build/assets/{vendor~root-layout-C-IgVx6e.js → vendor~root-layout-DeQACFVA.js} +1 -1
  178. package/build/assets/{vendor~root-layout~conversation-panel~conversation-Dhd_I4H4.js → vendor~root-layout~conversation-panel~conversation-bv7ooVgH.js} +1 -1
  179. package/build/assets/{vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-Cc0f9kPP.js → vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-e8pX05xf.js} +1 -1
  180. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-d7svw-BB.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-BvS6PCK2.js} +1 -1
  181. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hjcjabwg-4WsUP-tz.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hjcjabwg-DOPLJMH9.js} +1 -1
  182. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gxu4j2ea-D5DWZVc7.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iw7io29p-Dz8NQve5.js} +1 -1
  183. package/build/assets/{verification-settings-B8UMQ7MG.js → verification-settings-COueVXmM.js} +1 -1
  184. package/build/assets/{wrench-DIka3hCq.js → wrench-C95ujnYo.js} +1 -1
  185. package/build/assets/x-86ZCfxKY.js +1 -0
  186. package/build/assets/{zap-DHddTPc0.js → zap-DRa-r-Tf.js} +1 -1
  187. package/build/index.html +4 -4
  188. package/build/locales/ar/openhands.json +60 -2
  189. package/build/locales/ca/openhands.json +60 -2
  190. package/build/locales/de/openhands.json +60 -2
  191. package/build/locales/en/openhands.json +60 -2
  192. package/build/locales/es/openhands.json +60 -2
  193. package/build/locales/fr/openhands.json +60 -2
  194. package/build/locales/it/openhands.json +60 -2
  195. package/build/locales/ja/openhands.json +60 -2
  196. package/build/locales/ko-KR/openhands.json +60 -2
  197. package/build/locales/no/openhands.json +60 -2
  198. package/build/locales/pt/openhands.json +60 -2
  199. package/build/locales/tr/openhands.json +60 -2
  200. package/build/locales/uk/openhands.json +60 -2
  201. package/build/locales/zh-CN/openhands.json +60 -2
  202. package/build/locales/zh-TW/openhands.json +60 -2
  203. package/config/defaults.json +1 -1
  204. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  205. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  206. package/dist/api/automation-service/automation-service.api.d.ts +10 -0
  207. package/dist/api/automation-service/automation-service.api.js +42 -0
  208. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  209. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  210. package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
  211. package/dist/api/cloud/conversation-service.api.d.ts +9 -0
  212. package/dist/api/cloud/conversation-service.api.js +11 -1
  213. package/dist/api/cloud/conversation-service.api.js.map +1 -1
  214. package/dist/api/profiles-service/profiles-service.api.cjs +1 -1
  215. package/dist/api/profiles-service/profiles-service.api.cjs.map +1 -1
  216. package/dist/api/profiles-service/profiles-service.api.d.ts +15 -2
  217. package/dist/api/profiles-service/profiles-service.api.js +25 -2
  218. package/dist/api/profiles-service/profiles-service.api.js.map +1 -1
  219. package/dist/api/secrets-service.cjs +1 -1
  220. package/dist/api/secrets-service.cjs.map +1 -1
  221. package/dist/api/secrets-service.d.ts +5 -0
  222. package/dist/api/secrets-service.js +12 -6
  223. package/dist/api/secrets-service.js.map +1 -1
  224. package/dist/components/conversation-events/chat/event-message-components/index.d.ts +0 -1
  225. package/dist/components/features/automations/git-sync/git-sync-activity-row.d.ts +15 -0
  226. package/dist/components/features/automations/git-sync/git-sync-config-form.d.ts +13 -0
  227. package/dist/components/features/automations/git-sync/git-sync-error-banner.d.ts +6 -0
  228. package/dist/components/features/automations/git-sync/git-sync-not-local-state.d.ts +1 -0
  229. package/dist/components/features/automations/git-sync/git-sync-overview-section.d.ts +12 -0
  230. package/dist/components/features/automations/git-sync/git-sync-skeleton.d.ts +1 -0
  231. package/dist/components/features/automations/git-sync/git-sync-status-pill.d.ts +7 -0
  232. package/dist/components/features/automations/git-sync/git-sync-unsupported-state.d.ts +7 -0
  233. package/dist/components/features/automations/responder-deployment-modal.d.ts +2 -1
  234. package/dist/components/features/chat/chat-interface.cjs +2 -2
  235. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  236. package/dist/components/features/chat/chat-interface.js +177 -176
  237. package/dist/components/features/chat/chat-interface.js.map +1 -1
  238. package/dist/components/features/chat/error-message-banner.cjs +1 -1
  239. package/dist/components/features/chat/error-message-banner.cjs.map +1 -1
  240. package/dist/components/features/chat/error-message-banner.d.ts +3 -1
  241. package/dist/components/features/chat/error-message-banner.js +64 -58
  242. package/dist/components/features/chat/error-message-banner.js.map +1 -1
  243. package/dist/components/features/conversation-panel/compact-conversation-row.cjs +1 -1
  244. package/dist/components/features/conversation-panel/compact-conversation-row.js +6 -6
  245. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  246. package/dist/components/features/conversation-panel/conversation-panel.js +19 -19
  247. package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +10 -7
  248. package/dist/components/shared/buttons/conversation-confirmation-buttons.cjs +1 -1
  249. package/dist/components/shared/buttons/conversation-confirmation-buttons.cjs.map +1 -1
  250. package/dist/components/shared/buttons/conversation-confirmation-buttons.js +1 -1
  251. package/dist/components/shared/buttons/conversation-confirmation-buttons.js.map +1 -1
  252. package/dist/config/defaults.cjs +1 -1
  253. package/dist/config/defaults.cjs.map +1 -1
  254. package/dist/config/defaults.js +1 -1
  255. package/dist/config/defaults.js.map +1 -1
  256. package/dist/contexts/conversation-websocket-context.cjs +2 -2
  257. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  258. package/dist/contexts/conversation-websocket-context.js +12 -12
  259. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  260. package/dist/hooks/query/use-commit-changes.cjs +1 -1
  261. package/dist/hooks/query/use-commit-changes.js +4 -4
  262. package/dist/hooks/query/use-git-sync.d.ts +19 -0
  263. package/dist/hooks/query/use-task-polling.cjs +1 -1
  264. package/dist/hooks/query/use-task-polling.cjs.map +1 -1
  265. package/dist/hooks/query/use-task-polling.js +12 -10
  266. package/dist/hooks/query/use-task-polling.js.map +1 -1
  267. package/dist/hooks/query/use-unified-get-git-changes.cjs +1 -1
  268. package/dist/hooks/query/use-unified-get-git-changes.js +4 -4
  269. package/dist/hooks/query/use-unified-git-commits.cjs +1 -1
  270. package/dist/hooks/query/use-unified-git-commits.js +4 -4
  271. package/dist/hooks/query/use-unified-git-diff.cjs +1 -1
  272. package/dist/hooks/query/use-unified-git-diff.js +4 -4
  273. package/dist/hooks/query/use-workspace-files.cjs +1 -1
  274. package/dist/hooks/query/use-workspace-files.cjs.map +1 -1
  275. package/dist/hooks/query/use-workspace-files.d.ts +14 -4
  276. package/dist/hooks/query/use-workspace-files.js +45 -32
  277. package/dist/hooks/query/use-workspace-files.js.map +1 -1
  278. package/dist/hooks/use-responder-url-secret.d.ts +5 -0
  279. package/dist/hooks/use-tracking.cjs +1 -1
  280. package/dist/hooks/use-tracking.cjs.map +1 -1
  281. package/dist/hooks/use-tracking.d.ts +6 -0
  282. package/dist/hooks/use-tracking.js +6 -0
  283. package/dist/hooks/use-tracking.js.map +1 -1
  284. package/dist/i18n/declaration.cjs +1 -1
  285. package/dist/i18n/declaration.cjs.map +1 -1
  286. package/dist/i18n/declaration.d.ts +59 -1
  287. package/dist/i18n/declaration.js +1 -1
  288. package/dist/i18n/declaration.js.map +1 -1
  289. package/dist/i18n/translation.cjs +1 -1
  290. package/dist/i18n/translation.cjs.map +1 -1
  291. package/dist/i18n/translation.js +1001 -15
  292. package/dist/i18n/translation.js.map +1 -1
  293. package/dist/locales/ar/openhands.json +60 -2
  294. package/dist/locales/ca/openhands.json +60 -2
  295. package/dist/locales/de/openhands.json +60 -2
  296. package/dist/locales/en/openhands.json +60 -2
  297. package/dist/locales/es/openhands.json +60 -2
  298. package/dist/locales/fr/openhands.json +60 -2
  299. package/dist/locales/it/openhands.json +60 -2
  300. package/dist/locales/ja/openhands.json +60 -2
  301. package/dist/locales/ko-KR/openhands.json +60 -2
  302. package/dist/locales/no/openhands.json +60 -2
  303. package/dist/locales/pt/openhands.json +60 -2
  304. package/dist/locales/tr/openhands.json +60 -2
  305. package/dist/locales/uk/openhands.json +60 -2
  306. package/dist/locales/zh-CN/openhands.json +60 -2
  307. package/dist/locales/zh-TW/openhands.json +60 -2
  308. package/dist/node_modules/lucide-react/dist/esm/icons/circle-alert.cjs +2 -0
  309. package/dist/node_modules/lucide-react/dist/esm/icons/circle-alert.cjs.map +1 -0
  310. package/dist/node_modules/lucide-react/dist/esm/icons/circle-alert.js +27 -0
  311. package/dist/node_modules/lucide-react/dist/esm/icons/circle-alert.js.map +1 -0
  312. package/dist/package.cjs +1 -1
  313. package/dist/package.cjs.map +1 -1
  314. package/dist/package.js +1 -1
  315. package/dist/package.js.map +1 -1
  316. package/dist/routes/files-tab.cjs +1 -1
  317. package/dist/routes/files-tab.js +11 -11
  318. package/dist/routes/files-tab.js.map +1 -1
  319. package/dist/services/settings.cjs +1 -1
  320. package/dist/services/settings.cjs.map +1 -1
  321. package/dist/services/settings.js +2 -2
  322. package/dist/services/settings.js.map +1 -1
  323. package/dist/services/telemetry.cjs +1 -1
  324. package/dist/services/telemetry.cjs.map +1 -1
  325. package/dist/services/telemetry.js +47 -51
  326. package/dist/services/telemetry.js.map +1 -1
  327. package/dist/stores/error-message-store.cjs +1 -1
  328. package/dist/stores/error-message-store.cjs.map +1 -1
  329. package/dist/stores/error-message-store.d.ts +3 -1
  330. package/dist/stores/error-message-store.js +5 -3
  331. package/dist/stores/error-message-store.js.map +1 -1
  332. package/dist/types/git-sync.d.ts +51 -0
  333. package/dist/utils/error-handler.cjs +1 -1
  334. package/dist/utils/error-handler.cjs.map +1 -1
  335. package/dist/utils/error-handler.d.ts +3 -2
  336. package/dist/utils/error-handler.js +18 -5
  337. package/dist/utils/error-handler.js.map +1 -1
  338. package/dist/utils/format-model-name.cjs +1 -1
  339. package/dist/utils/format-model-name.cjs.map +1 -1
  340. package/dist/utils/format-model-name.d.ts +1 -0
  341. package/dist/utils/format-model-name.js +1 -0
  342. package/dist/utils/format-model-name.js.map +1 -1
  343. package/dist/utils/transcript-export/load-complete-events.cjs +1 -1
  344. package/dist/utils/transcript-export/load-complete-events.cjs.map +1 -1
  345. package/dist/utils/transcript-export/load-complete-events.js +24 -16
  346. package/dist/utils/transcript-export/load-complete-events.js.map +1 -1
  347. package/package.json +1 -1
  348. package/scripts/check-translation-completeness.cjs +3 -0
  349. package/scripts/dev-with-automation.mjs +98 -9
  350. package/build/assets/active-backend-context-IqOjobNK.js +0 -2
  351. package/build/assets/agent-settings-COfJsQ1d.js +0 -1
  352. package/build/assets/automation-detail-B-jQ39Mm.js +0 -3
  353. package/build/assets/automation-export-B1dywoqk.js +0 -2
  354. package/build/assets/automation-setup-route-C-bWUZBi.js +0 -1
  355. package/build/assets/automations-list-DnMxlxsL.js +0 -1
  356. package/build/assets/browser-B9AbV6kG.js +0 -7
  357. package/build/assets/check-WAFXrrs_.js +0 -1
  358. package/build/assets/chevron-down-CifNWzme.js +0 -1
  359. package/build/assets/circle-check-CtnimJa8.js +0 -1
  360. package/build/assets/conversation-BPo8SvLN.js +0 -1
  361. package/build/assets/conversation-CPCVsCUY.js +0 -90
  362. package/build/assets/conversation-panel-BPo8SvLN.js +0 -1
  363. package/build/assets/conversation-state-store-C5YpjMNy.js +0 -1
  364. package/build/assets/files-tab-DV0L-lFE.js +0 -1
  365. package/build/assets/format-model-name-BN_rx1Y3.js +0 -1
  366. package/build/assets/format-relative-time-DSErAuVr.js +0 -1
  367. package/build/assets/git-provider-icon-BvlLAche.js +0 -1
  368. package/build/assets/git-repo-dropdown-C6R7hgM8.js +0 -1
  369. package/build/assets/home-BOrlwLqG.js +0 -1
  370. package/build/assets/home-BvMNC6E-.js +0 -1
  371. package/build/assets/index-home-BvMNC6E-.js +0 -1
  372. package/build/assets/info-BRVcJAUg.js +0 -1
  373. package/build/assets/install-server-modal-Bl4G1zF4.js +0 -1
  374. package/build/assets/kebab-menu-item-content-BGoGFEAg.js +0 -1
  375. package/build/assets/llm-not-configured-banner-DLw_tu-G.js +0 -27
  376. package/build/assets/llm-settings-B-pkVCrt.js +0 -1
  377. package/build/assets/llm-settings-DSC0-IQ7.js +0 -1
  378. package/build/assets/loader-circle-B47W9XqT.js +0 -1
  379. package/build/assets/manifest-653b89aa.js +0 -1
  380. package/build/assets/manifest-subpage-layout-CKWvL2ig.js +0 -1
  381. package/build/assets/markdown-renderer-DUmk7pFc.js +0 -8
  382. package/build/assets/onboarding-modal-C_xVrFNv.js +0 -1
  383. package/build/assets/plus-zNEL8rcX.js +0 -1
  384. package/build/assets/profiles-service.api-DCMYxHMi.js +0 -1
  385. package/build/assets/providers-BjrtjX4L.js +0 -1
  386. package/build/assets/recommended-automations-launcher-CFlzhu1o.js +0 -1
  387. package/build/assets/root-CanxKlNV.css +0 -1
  388. package/build/assets/root-DkfG_UWR.js +0 -2
  389. package/build/assets/root-layout-D75LHYhh.js +0 -2
  390. package/build/assets/search-CycosyjN.js +0 -1
  391. package/build/assets/secrets-service-B26R61C1.js +0 -1
  392. package/build/assets/secrets-settings-CbLYCKOX.js +0 -1
  393. package/build/assets/usage-tab-tEmVN0KD.js +0 -1
  394. package/build/assets/use-acp-credential-form-BPNi0Zbm.js +0 -1
  395. package/build/assets/use-agent-profiles-Cb2zUW3l.js +0 -1
  396. package/build/assets/use-config-DKAMiI5R.js +0 -1
  397. package/build/assets/use-create-secret-2zBlCDsF.js +0 -1
  398. package/build/assets/use-is-authed-C52-ivnB.js +0 -1
  399. package/build/assets/use-is-creating-conversation-DdaAE6jV.js +0 -1
  400. package/build/assets/use-llm-profiles-C_BHue65.js +0 -1
  401. package/build/assets/use-manifest-capabilities-DPrQsaPP.js +0 -1
  402. package/build/assets/use-save-agent-profile-DK9idD6a.js +0 -1
  403. package/build/assets/use-tracking-CVwPmhlX.js +0 -3
  404. package/build/assets/x-BWKA2Ver.js +0 -1
  405. package/dist/api/cloud/suggestions-service.api.d.ts +0 -8
  406. package/dist/api/suggestions-service/suggestions-service.api.d.ts +0 -11
  407. package/dist/components/conversation-events/chat/event-message-components/observation-pair-event-message.d.ts +0 -7
  408. package/dist/components/conversation-events/index.d.ts +0 -1
  409. package/dist/components/features/automations/metadata-chip.d.ts +0 -6
  410. package/dist/components/features/chat/task-tracking/status-badge.d.ts +0 -5
  411. package/dist/components/features/chat/task-tracking/status-icon.d.ts +0 -5
  412. package/dist/components/features/chat/task-tracking/task-list-section.d.ts +0 -10
  413. package/dist/components/features/controls/tools.d.ts +0 -2
  414. package/dist/components/features/conversation-panel/new-conversation-button.d.ts +0 -23
  415. package/dist/components/features/home/home-header/guide-message.d.ts +0 -1
  416. package/dist/components/features/home/home-header/home-header.d.ts +0 -1
  417. package/dist/components/features/home/new-conversation/create-conversation-button.d.ts +0 -1
  418. package/dist/components/features/home/new-conversation/new-conversation.d.ts +0 -1
  419. package/dist/components/features/home/new-conversation.d.ts +0 -1
  420. package/dist/components/features/home/tasks/task-card.d.ts +0 -6
  421. package/dist/components/features/home/tasks/task-group.d.ts +0 -7
  422. package/dist/components/features/home/tasks/task-issue-number.d.ts +0 -6
  423. package/dist/components/features/home/tasks/task-item-title.d.ts +0 -1
  424. package/dist/components/features/home/tasks/task-suggestions-skeleton.d.ts +0 -1
  425. package/dist/components/features/home/tasks/task-suggestions.d.ts +0 -6
  426. package/dist/components/features/settings/agent-server-onboarding.d.ts +0 -10
  427. package/dist/components/features/settings/mcp-settings/mcp-server-list-item.d.ts +0 -6
  428. package/dist/components/features/settings/mcp-settings/mcp-server-list.d.ts +0 -8
  429. package/dist/hooks/query/use-suggested-tasks.d.ts +0 -1
  430. package/dist/hooks/use-should-show-user-features.d.ts +0 -1
  431. package/dist/ui/card-title.d.ts +0 -16
  432. package/dist/ui/card.d.ts +0 -14
  433. package/dist/utils/group-suggested-tasks.d.ts +0 -7
  434. /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dh9v73sa-rfV8mQ9m.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dcc51rps-rfV8mQ9m.js} +0 -0
  435. /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~lq5hicxx-cHFhpUBq.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ox0jfsa0-cHFhpUBq.js} +0 -0
  436. /package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~9pstowjp-BOVIFA_g.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-BOVIFA_g.js} +0 -0
  437. /package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~ht43enc2-C0JXQb_q.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-C0JXQb_q.js} +0 -0
@@ -91,6 +91,15 @@ export declare function resumeCloudSandbox(sandboxId: string): Promise<void>;
91
91
  * and returns the file content as a string.
92
92
  */
93
93
  export declare function readCloudConversationFile(conversationId: string, filePath: string): Promise<string>;
94
+ /**
95
+ * List every file in a cloud conversation's sandbox workspace. Hits
96
+ * `GET /api/v1/app-conversations/{id}/files?path=...` on the cloud backend,
97
+ * which resolves the conversation's runtime and runs a bounded `find`
98
+ * server-side (see enterprise `list_conversation_files`). Unlike the
99
+ * git-changes source, this returns the full tree so the Files tab matches the
100
+ * local-backend experience. Paths come back relative to `path`.
101
+ */
102
+ export declare function listCloudConversationFiles(conversationId: string, path: string): Promise<string[]>;
94
103
  /**
95
104
  * Fetch a single v1 app-conversation start task. Mirrors OpenHands'
96
105
  * `AgentServerConversationService.getStartTask` — uses the batch search endpoint
@@ -101,6 +101,16 @@ async function g(e, t) {
101
101
  }) ?? "";
102
102
  }
103
103
  async function _(e, t) {
104
+ let n = o(), r = new URLSearchParams();
105
+ r.append("path", t);
106
+ let a = await i({
107
+ backend: n,
108
+ method: "GET",
109
+ path: `/api/v1/app-conversations/${e}/files?${r.toString()}`
110
+ });
111
+ return Array.isArray(a) ? a : [];
112
+ }
113
+ async function v(e, t) {
104
114
  let n = t ?? o(), r = new URLSearchParams();
105
115
  return r.set("ids", e), (await i({
106
116
  backend: n,
@@ -109,6 +119,6 @@ async function _(e, t) {
109
119
  }))?.[0] ?? null;
110
120
  }
111
121
  //#endregion
112
- export { l as batchGetCloudConversations, u as createCloudAppConversation, f as deleteCloudConversation, d as downloadCloudConversation, _ as getCloudAppConversationStartTask, m as pauseCloudSandbox, s as pickCloudBackendForLaunch, g as readCloudConversationFile, h as resumeCloudSandbox, c as searchCloudConversations, p as updateCloudConversationPublicFlag };
122
+ export { l as batchGetCloudConversations, u as createCloudAppConversation, f as deleteCloudConversation, d as downloadCloudConversation, v as getCloudAppConversationStartTask, _ as listCloudConversationFiles, m as pauseCloudSandbox, s as pickCloudBackendForLaunch, g as readCloudConversationFile, h as resumeCloudSandbox, c as searchCloudConversations, p as updateCloudConversationPublicFlag };
113
123
 
114
124
  //# sourceMappingURL=conversation-service.api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-service.api.js","names":[],"sources":["../../../src/api/cloud/conversation-service.api.ts"],"sourcesContent":["import {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport type { Backend } from \"../backend-registry/types\";\nimport { getStoredConversationMetadata } from \"../conversation-metadata-store\";\nimport type {\n AppConversation,\n AppConversationPage,\n AppConversationStartRequest,\n AppConversationStartTask,\n} from \"../conversation-service/agent-server-conversation-service.types\";\nimport { AGENT_CANVAS_CLIENT_HEADERS } from \"../client-source\";\nimport { callCloudProxy } from \"./proxy\";\n\n/**\n * The cloud backend does not always echo `selected_repository` /\n * `selected_branch` / `git_provider` back from\n * `GET /api/v1/app-conversations` until its own background hydration\n * completes. We persist the selection to local storage at connect time\n * (see `AgentServerConversationService.updateConversationRepository`)\n * and overlay it here so the chat-page git control bar reflects the\n * connection immediately, instead of snapping back to the empty\n * \"Connect Repo\" state on every refetch.\n *\n * Server values take precedence whenever they're populated; the\n * local-storage fallback only fills in fields the server returned as\n * `null`/`undefined`.\n */\nfunction overlayStoredRepoSelection(\n conversation: AppConversation | null,\n): AppConversation | null {\n if (!conversation?.id) return conversation;\n const stored = getStoredConversationMetadata(conversation.id);\n if (!stored) return conversation;\n\n return {\n ...conversation,\n selected_repository:\n conversation.selected_repository ?? stored.selected_repository ?? null,\n selected_branch:\n conversation.selected_branch ?? stored.selected_branch ?? null,\n git_provider: conversation.git_provider ?? stored.git_provider ?? null,\n selected_workspace:\n conversation.selected_workspace ?? stored.selected_workspace ?? null,\n };\n}\n\nfunction getActiveCloudBackend(): Backend {\n const active = getActiveBackend().backend;\n if (active.kind !== \"cloud\") {\n throw new Error(\"Cloud conversations call requires a cloud backend.\");\n }\n return active;\n}\n\n/**\n * Resolve the cloud backend a Cloud conversation should be launched against\n * when the active backend may not be a cloud one. Cloud conversations cannot\n * register client tools, so the typed launch action always runs from a local\n * parent and has to reach a registered-but-inactive cloud backend.\n *\n * Prefers the active backend when it is already cloud, then the first\n * registered cloud backend that carries credentials. Returns `null` when the\n * user has no cloud backend connected, so callers can give the agent\n * corrective guidance instead of failing opaquely.\n *\n * Note: `createCloudClient` only sends `X-Org-Id` for the *active* backend, so\n * a conversation launched against an inactive backend lands in the API key's\n * own organization.\n */\nexport function pickCloudBackendForLaunch(): Backend | null {\n const active = getActiveBackend().backend;\n if (active.kind === \"cloud\") return active;\n return (\n getRegisteredBackends().find(\n (backend) => backend.kind === \"cloud\" && !!backend.apiKey,\n ) ?? null\n );\n}\n\n/**\n * Search the cloud app-conversations list. Mirrors the local\n * `AgentServerConversationService.searchConversations` interface but calls\n * the cloud endpoint `/api/v1/app-conversations/search`.\n */\nexport async function searchCloudConversations(\n limit: number = 20,\n pageId?: string,\n): Promise<AppConversationPage> {\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n params.set(\"limit\", String(limit));\n if (pageId) params.set(\"page_id\", pageId);\n params.set(\"sort_order\", \"UPDATED_AT_DESC\");\n\n const data = await callCloudProxy<{\n items: AppConversation[];\n next_page_id: string | null;\n }>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/search?${params.toString()}`,\n });\n\n return {\n items: (data?.items ?? []).map(\n (item) => overlayStoredRepoSelection(item) as AppConversation,\n ),\n next_page_id: data?.next_page_id ?? null,\n };\n}\n\n/**\n * Batch-fetch cloud app-conversations by id. Mirrors the local\n * `AgentServerConversationService.batchGetAppConversations` interface.\n */\nexport async function batchGetCloudConversations(\n ids: string[],\n): Promise<(AppConversation | null)[]> {\n if (ids.length === 0) return [];\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n for (const id of ids) params.append(\"ids\", id);\n const data = await callCloudProxy<(AppConversation | null)[]>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations?${params.toString()}`,\n });\n return (data ?? []).map(overlayStoredRepoSelection);\n}\n\n/**\n * Create a v1 app-conversation on the cloud backend.\n *\n * Mirrors OpenHands' cloud flow: POST /api/v1/app-conversations with the\n * `AppConversationStartRequest` payload, returning a\n * `AppConversationStartTask`. The task is initially WORKING; the caller\n * polls `getCloudAppConversationStartTask` (3s cadence per OpenHands)\n * until status is READY (then `app_conversation_id`, `agent_server_url`,\n * and `session_api_key` are populated) or ERROR.\n *\n * This path does NOT use encrypted-settings round-tripping. Secrets stay\n * server-side on the cloud backend — the only auth carried is the cloud bearer\n * token, and the conversation runtime is\n * provisioned with its own ephemeral session_api_key returned in the\n * task.\n */\nexport async function createCloudAppConversation(\n request: AppConversationStartRequest,\n // Defaults to the active backend. The typed launch action passes an explicit\n // backend because it always runs from a *local* parent conversation.\n backendOverride?: Backend,\n): Promise<AppConversationStartTask> {\n const backend = backendOverride ?? getActiveCloudBackend();\n const data = await callCloudProxy<AppConversationStartTask>({\n backend,\n method: \"POST\",\n path: \"/api/v1/app-conversations\",\n body: request as unknown as Record<string, unknown>,\n headers: AGENT_CANVAS_CLIENT_HEADERS,\n });\n return data;\n}\n\n/**\n * Download a v1 app-conversation as a ZIP from the cloud backend. Mirrors\n * the local `AgentServerConversationService.downloadConversation` interface but\n * calls\n * `GET /api/v1/app-conversations/{id}/download`, which returns\n * `application/zip` with `Content-Disposition` set by the cloud backend.\n */\nexport async function downloadCloudConversation(\n conversationId: string,\n): Promise<Blob> {\n const backend = getActiveCloudBackend();\n return callCloudProxy<Blob>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/${conversationId}/download`,\n responseType: \"blob\",\n });\n}\n\n/**\n * Delete a v1 app-conversation on the cloud backend. Mirrors the local\n * `AgentServerConversationService.deleteConversation` interface but calls\n * `DELETE /api/v1/app-conversations/{id}`, which returns a JSON\n * `Success` envelope (discarded here — the caller only needs to know\n * the request didn't error).\n */\nexport async function deleteCloudConversation(\n conversationId: string,\n): Promise<void> {\n const backend = getActiveCloudBackend();\n await callCloudProxy<unknown>({\n backend,\n method: \"DELETE\",\n path: `/api/v1/app-conversations/${conversationId}`,\n });\n}\n\n/**\n * Toggle the public-sharing flag on a cloud v1 app-conversation. Mirrors\n * OpenHands' `AgentServerConversationService.updateConversationPublicFlag`:\n * `PATCH /api/v1/app-conversations/{id}` with `{ public }`, returning\n * the updated conversation.\n */\nexport async function updateCloudConversationPublicFlag(\n conversationId: string,\n isPublic: boolean,\n): Promise<AppConversation> {\n const backend = getActiveCloudBackend();\n const data = await callCloudProxy<AppConversation>({\n backend,\n method: \"PATCH\",\n path: `/api/v1/app-conversations/${conversationId}`,\n body: { public: isPublic },\n });\n return data;\n}\n\n/**\n * Pause the cloud sandbox backing a v1 app-conversation. Mirrors\n * OpenHands' `SandboxService.pauseSandbox`:\n * `POST /api/v1/sandboxes/{sandboxId}/pause` on the cloud backend, which stops\n * the runtime owning the conversation.\n */\nexport async function pauseCloudSandbox(sandboxId: string): Promise<void> {\n const backend = getActiveCloudBackend();\n await callCloudProxy<unknown>({\n backend,\n method: \"POST\",\n path: `/api/v1/sandboxes/${sandboxId}/pause`,\n });\n}\n\n/**\n * Resume a paused cloud sandbox. Mirrors OpenHands' `SandboxService.resumeSandbox`\n * by calling `POST /api/v1/sandboxes/{sandboxId}/resume` on the SaaS.\n *\n * This is the correct endpoint for waking a PAUSED sandbox. It is a\n * lightweight unpause — NOT the same as creating a new start task via\n * `POST /api/v1/app-conversations`, which provisions a fresh conversation\n * and is subject to the 120-second sandbox-start timeout.\n */\nexport async function resumeCloudSandbox(sandboxId: string): Promise<void> {\n const backend = getActiveCloudBackend();\n await callCloudProxy<unknown>({\n backend,\n method: \"POST\",\n path: `/api/v1/sandboxes/${sandboxId}/resume`,\n });\n}\n\n/**\n * Read a file from a cloud conversation's sandbox workspace. Mirrors\n * OpenHands' `AgentServerConversationService.readConversationFile` — hits\n * `GET /api/v1/app-conversations/{id}/file?file_path=...` on the cloud backend\n * and returns the file content as a string.\n */\nexport async function readCloudConversationFile(\n conversationId: string,\n filePath: string,\n): Promise<string> {\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n params.append(\"file_path\", filePath);\n const data = await callCloudProxy<string>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/${conversationId}/file?${params.toString()}`,\n });\n return data ?? \"\";\n}\n\n/**\n * Fetch a single v1 app-conversation start task. Mirrors OpenHands'\n * `AgentServerConversationService.getStartTask` — uses the batch search endpoint\n * with a single id and unwraps the first result.\n */\nexport async function getCloudAppConversationStartTask(\n taskId: string,\n backendOverride?: Backend,\n): Promise<AppConversationStartTask | null> {\n const backend = backendOverride ?? getActiveCloudBackend();\n const params = new URLSearchParams();\n params.set(\"ids\", taskId);\n const data = await callCloudProxy<(AppConversationStartTask | null)[]>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/start-tasks?${params.toString()}`,\n });\n return data?.[0] ?? null;\n}\n"],"mappings":";;;;;AA6BA,SAAS,EACP,GACwB;CACxB,IAAI,CAAC,GAAc,IAAI,OAAO;CAC9B,IAAM,IAAS,EAA8B,EAAa,EAAE;CAG5D,OAFK,IAEE;EACL,GAAG;EACH,qBACE,EAAa,uBAAuB,EAAO,uBAAuB;EACpE,iBACE,EAAa,mBAAmB,EAAO,mBAAmB;EAC5D,cAAc,EAAa,gBAAgB,EAAO,gBAAgB;EAClE,oBACE,EAAa,sBAAsB,EAAO,sBAAsB;CACpE,IAXoB;AAYtB;AAEA,SAAS,IAAiC;CACxC,IAAM,IAAS,EAAiB,EAAE;CAClC,IAAI,EAAO,SAAS,SAClB,MAAU,MAAM,oDAAoD;CAEtE,OAAO;AACT;AAiBA,SAAgB,IAA4C;CAC1D,IAAM,IAAS,EAAiB,EAAE;CAElC,OADI,EAAO,SAAS,UAAgB,IAElC,EAAsB,EAAE,MACrB,MAAY,EAAQ,SAAS,WAAW,CAAC,CAAC,EAAQ,MACrD,KAAK;AAET;AAOA,eAAsB,EACpB,IAAgB,IAChB,GAC8B;CAC9B,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CAGnC,AAFA,EAAO,IAAI,SAAS,OAAO,CAAK,CAAC,GAC7B,KAAQ,EAAO,IAAI,WAAW,CAAM,GACxC,EAAO,IAAI,cAAc,iBAAiB;CAE1C,IAAM,IAAO,MAAM,EAGhB;EACD;EACA,QAAQ;EACR,MAAM,oCAAoC,EAAO,SAAS;CAC5D,CAAC;CAED,OAAO;EACL,QAAQ,GAAM,SAAS,CAAC,GAAG,KACxB,MAAS,EAA2B,CAAI,CAC3C;EACA,cAAc,GAAM,gBAAgB;CACtC;AACF;AAMA,eAAsB,EACpB,GACqC;CACrC,IAAI,EAAI,WAAW,GAAG,OAAO,CAAC;CAC9B,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CACnC,KAAK,IAAM,KAAM,GAAK,EAAO,OAAO,OAAO,CAAE;CAM7C,QAAQ,MALW,EAA2C;EAC5D;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAO,SAAS;CACrD,CAAC,KACe,CAAC,GAAG,IAAI,CAA0B;AACpD;AAkBA,eAAsB,EACpB,GAGA,GACmC;CASnC,OAAO,MAPY,EAAyC;EAC1D,SAFc,KAAmB,EAAsB;EAGvD,QAAQ;EACR,MAAM;EACN,MAAM;EACN,SAAS;CACX,CAAC;AAEH;AASA,eAAsB,EACpB,GACe;CAEf,OAAO,EAAqB;EAC1B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAe;EAClD,cAAc;CAChB,CAAC;AACH;AASA,eAAsB,EACpB,GACe;CAEf,MAAM,EAAwB;EAC5B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,6BAA6B;CACrC,CAAC;AACH;AAQA,eAAsB,EACpB,GACA,GAC0B;CAQ1B,OAAO,MANY,EAAgC;EACjD,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,6BAA6B;EACnC,MAAM,EAAE,QAAQ,EAAS;CAC3B,CAAC;AAEH;AAQA,eAAsB,EAAkB,GAAkC;CAExE,MAAM,EAAwB;EAC5B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,qBAAqB,EAAU;CACvC,CAAC;AACH;AAWA,eAAsB,EAAmB,GAAkC;CAEzE,MAAM,EAAwB;EAC5B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,qBAAqB,EAAU;CACvC,CAAC;AACH;AAQA,eAAsB,EACpB,GACA,GACiB;CACjB,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CAOnC,OANA,EAAO,OAAO,aAAa,CAAQ,GAM5B,MALY,EAAuB;EACxC;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAe,QAAQ,EAAO,SAAS;CAC5E,CAAC,KACc;AACjB;AAOA,eAAsB,EACpB,GACA,GAC0C;CAC1C,IAAM,IAAU,KAAmB,EAAsB,GACnD,IAAS,IAAI,gBAAgB;CAOnC,OANA,EAAO,IAAI,OAAO,CAAM,IAMjB,MALY,EAAoD;EACrE;EACA,QAAQ;EACR,MAAM,yCAAyC,EAAO,SAAS;CACjE,CAAC,KACa,MAAM;AACtB"}
1
+ {"version":3,"file":"conversation-service.api.js","names":[],"sources":["../../../src/api/cloud/conversation-service.api.ts"],"sourcesContent":["import {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport type { Backend } from \"../backend-registry/types\";\nimport { getStoredConversationMetadata } from \"../conversation-metadata-store\";\nimport type {\n AppConversation,\n AppConversationPage,\n AppConversationStartRequest,\n AppConversationStartTask,\n} from \"../conversation-service/agent-server-conversation-service.types\";\nimport { AGENT_CANVAS_CLIENT_HEADERS } from \"../client-source\";\nimport { callCloudProxy } from \"./proxy\";\n\n/**\n * The cloud backend does not always echo `selected_repository` /\n * `selected_branch` / `git_provider` back from\n * `GET /api/v1/app-conversations` until its own background hydration\n * completes. We persist the selection to local storage at connect time\n * (see `AgentServerConversationService.updateConversationRepository`)\n * and overlay it here so the chat-page git control bar reflects the\n * connection immediately, instead of snapping back to the empty\n * \"Connect Repo\" state on every refetch.\n *\n * Server values take precedence whenever they're populated; the\n * local-storage fallback only fills in fields the server returned as\n * `null`/`undefined`.\n */\nfunction overlayStoredRepoSelection(\n conversation: AppConversation | null,\n): AppConversation | null {\n if (!conversation?.id) return conversation;\n const stored = getStoredConversationMetadata(conversation.id);\n if (!stored) return conversation;\n\n return {\n ...conversation,\n selected_repository:\n conversation.selected_repository ?? stored.selected_repository ?? null,\n selected_branch:\n conversation.selected_branch ?? stored.selected_branch ?? null,\n git_provider: conversation.git_provider ?? stored.git_provider ?? null,\n selected_workspace:\n conversation.selected_workspace ?? stored.selected_workspace ?? null,\n };\n}\n\nfunction getActiveCloudBackend(): Backend {\n const active = getActiveBackend().backend;\n if (active.kind !== \"cloud\") {\n throw new Error(\"Cloud conversations call requires a cloud backend.\");\n }\n return active;\n}\n\n/**\n * Resolve the cloud backend a Cloud conversation should be launched against\n * when the active backend may not be a cloud one. Cloud conversations cannot\n * register client tools, so the typed launch action always runs from a local\n * parent and has to reach a registered-but-inactive cloud backend.\n *\n * Prefers the active backend when it is already cloud, then the first\n * registered cloud backend that carries credentials. Returns `null` when the\n * user has no cloud backend connected, so callers can give the agent\n * corrective guidance instead of failing opaquely.\n *\n * Note: `createCloudClient` only sends `X-Org-Id` for the *active* backend, so\n * a conversation launched against an inactive backend lands in the API key's\n * own organization.\n */\nexport function pickCloudBackendForLaunch(): Backend | null {\n const active = getActiveBackend().backend;\n if (active.kind === \"cloud\") return active;\n return (\n getRegisteredBackends().find(\n (backend) => backend.kind === \"cloud\" && !!backend.apiKey,\n ) ?? null\n );\n}\n\n/**\n * Search the cloud app-conversations list. Mirrors the local\n * `AgentServerConversationService.searchConversations` interface but calls\n * the cloud endpoint `/api/v1/app-conversations/search`.\n */\nexport async function searchCloudConversations(\n limit: number = 20,\n pageId?: string,\n): Promise<AppConversationPage> {\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n params.set(\"limit\", String(limit));\n if (pageId) params.set(\"page_id\", pageId);\n params.set(\"sort_order\", \"UPDATED_AT_DESC\");\n\n const data = await callCloudProxy<{\n items: AppConversation[];\n next_page_id: string | null;\n }>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/search?${params.toString()}`,\n });\n\n return {\n items: (data?.items ?? []).map(\n (item) => overlayStoredRepoSelection(item) as AppConversation,\n ),\n next_page_id: data?.next_page_id ?? null,\n };\n}\n\n/**\n * Batch-fetch cloud app-conversations by id. Mirrors the local\n * `AgentServerConversationService.batchGetAppConversations` interface.\n */\nexport async function batchGetCloudConversations(\n ids: string[],\n): Promise<(AppConversation | null)[]> {\n if (ids.length === 0) return [];\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n for (const id of ids) params.append(\"ids\", id);\n const data = await callCloudProxy<(AppConversation | null)[]>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations?${params.toString()}`,\n });\n return (data ?? []).map(overlayStoredRepoSelection);\n}\n\n/**\n * Create a v1 app-conversation on the cloud backend.\n *\n * Mirrors OpenHands' cloud flow: POST /api/v1/app-conversations with the\n * `AppConversationStartRequest` payload, returning a\n * `AppConversationStartTask`. The task is initially WORKING; the caller\n * polls `getCloudAppConversationStartTask` (3s cadence per OpenHands)\n * until status is READY (then `app_conversation_id`, `agent_server_url`,\n * and `session_api_key` are populated) or ERROR.\n *\n * This path does NOT use encrypted-settings round-tripping. Secrets stay\n * server-side on the cloud backend — the only auth carried is the cloud bearer\n * token, and the conversation runtime is\n * provisioned with its own ephemeral session_api_key returned in the\n * task.\n */\nexport async function createCloudAppConversation(\n request: AppConversationStartRequest,\n // Defaults to the active backend. The typed launch action passes an explicit\n // backend because it always runs from a *local* parent conversation.\n backendOverride?: Backend,\n): Promise<AppConversationStartTask> {\n const backend = backendOverride ?? getActiveCloudBackend();\n const data = await callCloudProxy<AppConversationStartTask>({\n backend,\n method: \"POST\",\n path: \"/api/v1/app-conversations\",\n body: request as unknown as Record<string, unknown>,\n headers: AGENT_CANVAS_CLIENT_HEADERS,\n });\n return data;\n}\n\n/**\n * Download a v1 app-conversation as a ZIP from the cloud backend. Mirrors\n * the local `AgentServerConversationService.downloadConversation` interface but\n * calls\n * `GET /api/v1/app-conversations/{id}/download`, which returns\n * `application/zip` with `Content-Disposition` set by the cloud backend.\n */\nexport async function downloadCloudConversation(\n conversationId: string,\n): Promise<Blob> {\n const backend = getActiveCloudBackend();\n return callCloudProxy<Blob>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/${conversationId}/download`,\n responseType: \"blob\",\n });\n}\n\n/**\n * Delete a v1 app-conversation on the cloud backend. Mirrors the local\n * `AgentServerConversationService.deleteConversation` interface but calls\n * `DELETE /api/v1/app-conversations/{id}`, which returns a JSON\n * `Success` envelope (discarded here — the caller only needs to know\n * the request didn't error).\n */\nexport async function deleteCloudConversation(\n conversationId: string,\n): Promise<void> {\n const backend = getActiveCloudBackend();\n await callCloudProxy<unknown>({\n backend,\n method: \"DELETE\",\n path: `/api/v1/app-conversations/${conversationId}`,\n });\n}\n\n/**\n * Toggle the public-sharing flag on a cloud v1 app-conversation. Mirrors\n * OpenHands' `AgentServerConversationService.updateConversationPublicFlag`:\n * `PATCH /api/v1/app-conversations/{id}` with `{ public }`, returning\n * the updated conversation.\n */\nexport async function updateCloudConversationPublicFlag(\n conversationId: string,\n isPublic: boolean,\n): Promise<AppConversation> {\n const backend = getActiveCloudBackend();\n const data = await callCloudProxy<AppConversation>({\n backend,\n method: \"PATCH\",\n path: `/api/v1/app-conversations/${conversationId}`,\n body: { public: isPublic },\n });\n return data;\n}\n\n/**\n * Pause the cloud sandbox backing a v1 app-conversation. Mirrors\n * OpenHands' `SandboxService.pauseSandbox`:\n * `POST /api/v1/sandboxes/{sandboxId}/pause` on the cloud backend, which stops\n * the runtime owning the conversation.\n */\nexport async function pauseCloudSandbox(sandboxId: string): Promise<void> {\n const backend = getActiveCloudBackend();\n await callCloudProxy<unknown>({\n backend,\n method: \"POST\",\n path: `/api/v1/sandboxes/${sandboxId}/pause`,\n });\n}\n\n/**\n * Resume a paused cloud sandbox. Mirrors OpenHands' `SandboxService.resumeSandbox`\n * by calling `POST /api/v1/sandboxes/{sandboxId}/resume` on the SaaS.\n *\n * This is the correct endpoint for waking a PAUSED sandbox. It is a\n * lightweight unpause — NOT the same as creating a new start task via\n * `POST /api/v1/app-conversations`, which provisions a fresh conversation\n * and is subject to the 120-second sandbox-start timeout.\n */\nexport async function resumeCloudSandbox(sandboxId: string): Promise<void> {\n const backend = getActiveCloudBackend();\n await callCloudProxy<unknown>({\n backend,\n method: \"POST\",\n path: `/api/v1/sandboxes/${sandboxId}/resume`,\n });\n}\n\n/**\n * Read a file from a cloud conversation's sandbox workspace. Mirrors\n * OpenHands' `AgentServerConversationService.readConversationFile` — hits\n * `GET /api/v1/app-conversations/{id}/file?file_path=...` on the cloud backend\n * and returns the file content as a string.\n */\nexport async function readCloudConversationFile(\n conversationId: string,\n filePath: string,\n): Promise<string> {\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n params.append(\"file_path\", filePath);\n const data = await callCloudProxy<string>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/${conversationId}/file?${params.toString()}`,\n });\n return data ?? \"\";\n}\n\n/**\n * List every file in a cloud conversation's sandbox workspace. Hits\n * `GET /api/v1/app-conversations/{id}/files?path=...` on the cloud backend,\n * which resolves the conversation's runtime and runs a bounded `find`\n * server-side (see enterprise `list_conversation_files`). Unlike the\n * git-changes source, this returns the full tree so the Files tab matches the\n * local-backend experience. Paths come back relative to `path`.\n */\nexport async function listCloudConversationFiles(\n conversationId: string,\n path: string,\n): Promise<string[]> {\n const backend = getActiveCloudBackend();\n const params = new URLSearchParams();\n params.append(\"path\", path);\n const data = await callCloudProxy<string[]>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/${conversationId}/files?${params.toString()}`,\n });\n return Array.isArray(data) ? data : [];\n}\n\n/**\n * Fetch a single v1 app-conversation start task. Mirrors OpenHands'\n * `AgentServerConversationService.getStartTask` — uses the batch search endpoint\n * with a single id and unwraps the first result.\n */\nexport async function getCloudAppConversationStartTask(\n taskId: string,\n backendOverride?: Backend,\n): Promise<AppConversationStartTask | null> {\n const backend = backendOverride ?? getActiveCloudBackend();\n const params = new URLSearchParams();\n params.set(\"ids\", taskId);\n const data = await callCloudProxy<(AppConversationStartTask | null)[]>({\n backend,\n method: \"GET\",\n path: `/api/v1/app-conversations/start-tasks?${params.toString()}`,\n });\n return data?.[0] ?? null;\n}\n"],"mappings":";;;;;AA6BA,SAAS,EACP,GACwB;CACxB,IAAI,CAAC,GAAc,IAAI,OAAO;CAC9B,IAAM,IAAS,EAA8B,EAAa,EAAE;CAG5D,OAFK,IAEE;EACL,GAAG;EACH,qBACE,EAAa,uBAAuB,EAAO,uBAAuB;EACpE,iBACE,EAAa,mBAAmB,EAAO,mBAAmB;EAC5D,cAAc,EAAa,gBAAgB,EAAO,gBAAgB;EAClE,oBACE,EAAa,sBAAsB,EAAO,sBAAsB;CACpE,IAXoB;AAYtB;AAEA,SAAS,IAAiC;CACxC,IAAM,IAAS,EAAiB,EAAE;CAClC,IAAI,EAAO,SAAS,SAClB,MAAU,MAAM,oDAAoD;CAEtE,OAAO;AACT;AAiBA,SAAgB,IAA4C;CAC1D,IAAM,IAAS,EAAiB,EAAE;CAElC,OADI,EAAO,SAAS,UAAgB,IAElC,EAAsB,EAAE,MACrB,MAAY,EAAQ,SAAS,WAAW,CAAC,CAAC,EAAQ,MACrD,KAAK;AAET;AAOA,eAAsB,EACpB,IAAgB,IAChB,GAC8B;CAC9B,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CAGnC,AAFA,EAAO,IAAI,SAAS,OAAO,CAAK,CAAC,GAC7B,KAAQ,EAAO,IAAI,WAAW,CAAM,GACxC,EAAO,IAAI,cAAc,iBAAiB;CAE1C,IAAM,IAAO,MAAM,EAGhB;EACD;EACA,QAAQ;EACR,MAAM,oCAAoC,EAAO,SAAS;CAC5D,CAAC;CAED,OAAO;EACL,QAAQ,GAAM,SAAS,CAAC,GAAG,KACxB,MAAS,EAA2B,CAAI,CAC3C;EACA,cAAc,GAAM,gBAAgB;CACtC;AACF;AAMA,eAAsB,EACpB,GACqC;CACrC,IAAI,EAAI,WAAW,GAAG,OAAO,CAAC;CAC9B,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CACnC,KAAK,IAAM,KAAM,GAAK,EAAO,OAAO,OAAO,CAAE;CAM7C,QAAQ,MALW,EAA2C;EAC5D;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAO,SAAS;CACrD,CAAC,KACe,CAAC,GAAG,IAAI,CAA0B;AACpD;AAkBA,eAAsB,EACpB,GAGA,GACmC;CASnC,OAAO,MAPY,EAAyC;EAC1D,SAFc,KAAmB,EAAsB;EAGvD,QAAQ;EACR,MAAM;EACN,MAAM;EACN,SAAS;CACX,CAAC;AAEH;AASA,eAAsB,EACpB,GACe;CAEf,OAAO,EAAqB;EAC1B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAe;EAClD,cAAc;CAChB,CAAC;AACH;AASA,eAAsB,EACpB,GACe;CAEf,MAAM,EAAwB;EAC5B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,6BAA6B;CACrC,CAAC;AACH;AAQA,eAAsB,EACpB,GACA,GAC0B;CAQ1B,OAAO,MANY,EAAgC;EACjD,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,6BAA6B;EACnC,MAAM,EAAE,QAAQ,EAAS;CAC3B,CAAC;AAEH;AAQA,eAAsB,EAAkB,GAAkC;CAExE,MAAM,EAAwB;EAC5B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,qBAAqB,EAAU;CACvC,CAAC;AACH;AAWA,eAAsB,EAAmB,GAAkC;CAEzE,MAAM,EAAwB;EAC5B,SAFc,EAEd;EACA,QAAQ;EACR,MAAM,qBAAqB,EAAU;CACvC,CAAC;AACH;AAQA,eAAsB,EACpB,GACA,GACiB;CACjB,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CAOnC,OANA,EAAO,OAAO,aAAa,CAAQ,GAM5B,MALY,EAAuB;EACxC;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAe,QAAQ,EAAO,SAAS;CAC5E,CAAC,KACc;AACjB;AAUA,eAAsB,EACpB,GACA,GACmB;CACnB,IAAM,IAAU,EAAsB,GAChC,IAAS,IAAI,gBAAgB;CACnC,EAAO,OAAO,QAAQ,CAAI;CAC1B,IAAM,IAAO,MAAM,EAAyB;EAC1C;EACA,QAAQ;EACR,MAAM,6BAA6B,EAAe,SAAS,EAAO,SAAS;CAC7E,CAAC;CACD,OAAO,MAAM,QAAQ,CAAI,IAAI,IAAO,CAAC;AACvC;AAOA,eAAsB,EACpB,GACA,GAC0C;CAC1C,IAAM,IAAU,KAAmB,EAAsB,GACnD,IAAS,IAAI,gBAAgB;CAOnC,OANA,EAAO,IAAI,OAAO,CAAM,IAMjB,MALY,EAAoD;EACrE;EACA,QAAQ;EACR,MAAM,yCAAyC,EAAO,SAAS;CACjE,CAAC,KACa,MAAM;AACtB"}
@@ -1,2 +1,2 @@
1
- require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/profiles-client.cjs");require("../../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("../backend-registry/active-store.cjs"),n=require("../agent-server-client-options.cjs"),r=require("../cloud/profiles-service.api.cjs");function i(){return t.getActiveBackend().backend.kind===`cloud`}var a=class{static async listProfiles(){return i()?r.fetchCloudProfiles():new e.ProfilesClient(n.getAgentServerClientOptions()).listProfiles()}static async getProfile(t,a){if(i())return r.fetchCloudProfile(t);let o=a?{exposeSecrets:a}:{};return new e.ProfilesClient(n.getAgentServerClientOptions()).getProfile(t,o)}static async saveProfile(t,a){return i()?r.saveCloudProfile(t,a):new e.ProfilesClient(n.getAgentServerClientOptions()).saveProfile(t,a)}static async deleteProfile(t){return i()?r.deleteCloudProfile(t):new e.ProfilesClient(n.getAgentServerClientOptions()).deleteProfile(t)}static async renameProfile(t,a){return i()?r.renameCloudProfile(t,a):new e.ProfilesClient(n.getAgentServerClientOptions()).renameProfile(t,a)}static async activateProfile(t){return i()?r.activateCloudProfile(t):new e.ProfilesClient(n.getAgentServerClientOptions()).activateProfile(t)}};exports.default=a;
1
+ require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/profiles-client.cjs");require("../../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("../backend-registry/active-store.cjs"),n=require("../agent-server-client-options.cjs"),r=require("../cloud/profiles-service.api.cjs");function i(){return t.getActiveBackend().backend.kind===`cloud`}function a(e){if(!e||typeof e!=`object`)return!1;let t=`name`in e?e.name:void 0;if(t===`AbortError`||t===`TimeoutError`)return!0;let n=`cause`in e?e.cause:void 0;return!!n&&typeof n==`object`&&`name`in n&&(n.name===`AbortError`||n.name===`TimeoutError`)}var o=class{static async listProfiles(){return i()?r.fetchCloudProfiles():new e.ProfilesClient(n.getAgentServerClientOptions()).listProfiles()}static async getProfile(t,a){if(i())return r.fetchCloudProfile(t);let o=a?{exposeSecrets:a}:{};return new e.ProfilesClient(n.getAgentServerClientOptions()).getProfile(t,o)}static async saveProfile(t,a){return i()?r.saveCloudProfile(t,a):new e.ProfilesClient(n.getAgentServerClientOptions()).saveProfile(t,a)}static async deleteProfile(t){return i()?r.deleteCloudProfile(t):new e.ProfilesClient(n.getAgentServerClientOptions()).deleteProfile(t)}static async renameProfile(t,a){return i()?r.renameCloudProfile(t,a):new e.ProfilesClient(n.getAgentServerClientOptions()).renameProfile(t,a)}static async activateProfile(t){return i()?r.activateCloudProfile(t):new e.ProfilesClient(n.getAgentServerClientOptions()).activateProfile(t)}static async validateProfile(t,r){if(i())return null;let o=new e.ProfilesClient({...n.getAgentServerClientOptions(),timeout:3e4});try{return await o.validateProfile(t,r)}catch(e){let t=e&&typeof e==`object`&&`status`in e?e.status:void 0;if(t===404||t===429||typeof t==`number`&&t>=500||a(e))return null;throw e}finally{o.close()}}};exports.default=o;
2
2
  //# sourceMappingURL=profiles-service.api.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"profiles-service.api.cjs","names":[],"sources":["../../../src/api/profiles-service/profiles-service.api.ts"],"sourcesContent":["/**\n * ProfilesService is the single entry point for LLM-profile CRUD, routing per\n * active backend so callers (hooks, the settings manager) stay backend-agnostic:\n * - local agent-server: the SDK's ProfilesClient (`/api/profiles`), created\n * per-call to pick up current backend configuration;\n * - cloud app-server: `src/api/cloud/profiles-service.api.ts` (the org-gated\n * `/api/organizations/{orgId}/profiles` routes, or the per-user settings\n * route as a fallback) via the org-scoped cloud proxy.\n * This mirrors how SettingsService branches to fetchCloudSettings().\n *\n * Uses ProfilesClient from @openhands/typescript-client v0.2.0+.\n * All types are re-exported from the SDK for consumer convenience.\n *\n * Note: Unlike some SDK clients, we don't call client.close() here for\n * consistency with other services (SettingsService, SecretsService) that\n * also create SDK clients without explicit cleanup. The SDK clients use\n * fetch-based HTTP which doesn't require connection cleanup.\n */\nimport {\n ProfilesClient,\n type GetProfileOptions,\n} from \"@openhands/typescript-client/clients\";\nimport type {\n ProfileInfo,\n ProfileListResponse,\n ProfileDetailResponse,\n ProfileMutationResponse,\n ActivateProfileResponse,\n SaveProfileRequest,\n ExposeSecretsMode,\n} from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport { getActiveBackend } from \"../backend-registry/active-store\";\nimport {\n activateCloudProfile,\n deleteCloudProfile,\n fetchCloudProfile,\n fetchCloudProfiles,\n renameCloudProfile,\n saveCloudProfile,\n} from \"../cloud/profiles-service.api\";\n\n// Re-export SDK types for consumers\nexport type {\n ProfileInfo,\n ProfileListResponse,\n ProfileDetailResponse,\n ProfileMutationResponse,\n ActivateProfileResponse,\n SaveProfileRequest,\n ExposeSecretsMode,\n};\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nclass ProfilesService {\n static async listProfiles(): Promise<ProfileListResponse> {\n if (isCloudBackend()) return fetchCloudProfiles();\n return new ProfilesClient(getAgentServerClientOptions()).listProfiles();\n }\n\n static async getProfile(\n name: string,\n exposeSecrets?: ExposeSecretsMode,\n ): Promise<ProfileDetailResponse> {\n // Cloud never exposes profile secrets (api_key is always nulled with an\n // api_key_set flag), so `exposeSecrets` is local-only.\n if (isCloudBackend()) return fetchCloudProfile(name);\n const options: GetProfileOptions = exposeSecrets ? { exposeSecrets } : {};\n return new ProfilesClient(getAgentServerClientOptions()).getProfile(\n name,\n options,\n );\n }\n\n static async saveProfile(\n name: string,\n request: SaveProfileRequest,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return saveCloudProfile(name, request);\n return new ProfilesClient(getAgentServerClientOptions()).saveProfile(\n name,\n request,\n );\n }\n\n static async deleteProfile(name: string): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return deleteCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).deleteProfile(\n name,\n );\n }\n\n static async renameProfile(\n name: string,\n newName: string,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return renameCloudProfile(name, newName);\n return new ProfilesClient(getAgentServerClientOptions()).renameProfile(\n name,\n newName,\n );\n }\n\n static async activateProfile(name: string): Promise<ActivateProfileResponse> {\n if (isCloudBackend()) return activateCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).activateProfile(\n name,\n );\n }\n}\n\nexport default ProfilesService;\n"],"mappings":"sXAqDA,SAAS,GAA0B,CACjC,OAAO,EAAA,iBAAiB,EAAE,QAAQ,OAAS,OAC7C,CAEA,IAAM,EAAN,KAAsB,CACpB,aAAa,cAA6C,CAExD,OADI,EAAe,EAAU,EAAA,mBAAmB,EACzC,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,aAAa,CACxE,CAEA,aAAa,WACX,EACA,EACgC,CAGhC,GAAI,EAAe,EAAG,OAAO,EAAA,kBAAkB,CAAI,EACnD,IAAM,EAA6B,EAAgB,CAAE,eAAc,EAAI,CAAC,EACxE,OAAO,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,WACvD,EACA,CACF,CACF,CAEA,aAAa,YACX,EACA,EACkC,CAElC,OADI,EAAe,EAAU,EAAA,iBAAiB,EAAM,CAAO,EACpD,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,YACvD,EACA,CACF,CACF,CAEA,aAAa,cAAc,EAAgD,CAEzE,OADI,EAAe,EAAU,EAAA,mBAAmB,CAAI,EAC7C,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,cACvD,CACF,CACF,CAEA,aAAa,cACX,EACA,EACkC,CAElC,OADI,EAAe,EAAU,EAAA,mBAAmB,EAAM,CAAO,EACtD,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,cACvD,EACA,CACF,CACF,CAEA,aAAa,gBAAgB,EAAgD,CAE3E,OADI,EAAe,EAAU,EAAA,qBAAqB,CAAI,EAC/C,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,gBACvD,CACF,CACF,CACF"}
1
+ {"version":3,"file":"profiles-service.api.cjs","names":[],"sources":["../../../src/api/profiles-service/profiles-service.api.ts"],"sourcesContent":["/**\n * ProfilesService is the single entry point for LLM-profile CRUD, routing per\n * active backend so callers (hooks, the settings manager) stay backend-agnostic:\n * - local agent-server: the SDK's ProfilesClient (`/api/profiles`), created\n * per-call to pick up current backend configuration;\n * - cloud app-server: `src/api/cloud/profiles-service.api.ts` (the org-gated\n * `/api/organizations/{orgId}/profiles` routes, or the per-user settings\n * route as a fallback) via the org-scoped cloud proxy.\n * This mirrors how SettingsService branches to fetchCloudSettings().\n *\n * Uses ProfilesClient from @openhands/typescript-client v0.2.0+.\n * All types are re-exported from the SDK for consumer convenience.\n *\n * Note: Unlike some SDK clients, we don't call client.close() here for\n * consistency with other services (SettingsService, SecretsService) that\n * also create SDK clients without explicit cleanup. The SDK clients use\n * fetch-based HTTP which doesn't require connection cleanup.\n */\nimport {\n ProfilesClient,\n type GetProfileOptions,\n} from \"@openhands/typescript-client/clients\";\nimport {\n type ProfileInfo,\n type ProfileListResponse,\n type ProfileDetailResponse,\n type ProfileMutationResponse,\n type ActivateProfileResponse,\n type SaveProfileRequest,\n type ExposeSecretsMode,\n type ValidateProfileResponse,\n} from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport { getActiveBackend } from \"../backend-registry/active-store\";\nimport {\n activateCloudProfile,\n deleteCloudProfile,\n fetchCloudProfile,\n fetchCloudProfiles,\n renameCloudProfile,\n saveCloudProfile,\n} from \"../cloud/profiles-service.api\";\n\n// Re-export SDK types for consumers\nexport type {\n ProfileInfo,\n ProfileListResponse,\n ProfileDetailResponse,\n ProfileMutationResponse,\n ActivateProfileResponse,\n SaveProfileRequest,\n ExposeSecretsMode,\n ValidateProfileResponse,\n};\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nfunction isAbortLike(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const name = \"name\" in error ? error.name : undefined;\n if (name === \"AbortError\" || name === \"TimeoutError\") return true;\n const cause = \"cause\" in error ? error.cause : undefined;\n return (\n !!cause &&\n typeof cause === \"object\" &&\n \"name\" in cause &&\n (cause.name === \"AbortError\" || cause.name === \"TimeoutError\")\n );\n}\n\nclass ProfilesService {\n static async listProfiles(): Promise<ProfileListResponse> {\n if (isCloudBackend()) return fetchCloudProfiles();\n return new ProfilesClient(getAgentServerClientOptions()).listProfiles();\n }\n\n static async getProfile(\n name: string,\n exposeSecrets?: ExposeSecretsMode,\n ): Promise<ProfileDetailResponse> {\n // Cloud never exposes profile secrets (api_key is always nulled with an\n // api_key_set flag), so `exposeSecrets` is local-only.\n if (isCloudBackend()) return fetchCloudProfile(name);\n const options: GetProfileOptions = exposeSecrets ? { exposeSecrets } : {};\n return new ProfilesClient(getAgentServerClientOptions()).getProfile(\n name,\n options,\n );\n }\n\n static async saveProfile(\n name: string,\n request: SaveProfileRequest,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return saveCloudProfile(name, request);\n return new ProfilesClient(getAgentServerClientOptions()).saveProfile(\n name,\n request,\n );\n }\n\n static async deleteProfile(name: string): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return deleteCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).deleteProfile(\n name,\n );\n }\n\n static async renameProfile(\n name: string,\n newName: string,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return renameCloudProfile(name, newName);\n return new ProfilesClient(getAgentServerClientOptions()).renameProfile(\n name,\n newName,\n );\n }\n\n static async activateProfile(name: string): Promise<ActivateProfileResponse> {\n if (isCloudBackend()) return activateCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).activateProfile(\n name,\n );\n }\n\n /**\n * Pre-flight check: fire a minimal LLM completion to catch misconfigurations\n * (invalid model names, missing provider prefixes, bad base URLs, invalid\n * API keys) before a profile is saved.\n *\n * Returns `{ valid: true }` when the LLM responds, or\n * `{ valid: false, error: { type, message } }` on a blocking error.\n * Transient errors (rate limits, timeouts) are non-blocking.\n *\n * Cloud backends do not implement this endpoint; `null` signals\n * \"no verdict\" so callers fall through to the normal save path.\n */\n static async validateProfile(\n name: string,\n request: SaveProfileRequest,\n ): Promise<ValidateProfileResponse | null> {\n if (isCloudBackend()) return null;\n const client = new ProfilesClient({\n ...getAgentServerClientOptions(),\n timeout: 30000,\n });\n try {\n return await client.validateProfile(name, request);\n } catch (error) {\n // Older agent-server versions don't have the endpoint → 404\n // Treat as \"no verdict\" rather than blocking the save.\n const status =\n error && typeof error === \"object\" && \"status\" in error\n ? (error as { status?: unknown }).status\n : undefined;\n if (\n status === 404 ||\n status === 429 ||\n (typeof status === \"number\" && status >= 500) ||\n isAbortLike(error)\n ) {\n return null;\n }\n throw error;\n } finally {\n client.close();\n }\n }\n}\n\nexport default ProfilesService;\n"],"mappings":"sXAuDA,SAAS,GAA0B,CACjC,OAAO,EAAA,iBAAiB,EAAE,QAAQ,OAAS,OAC7C,CAEA,SAAS,EAAY,EAAyB,CAC5C,GAAI,CAAC,GAAS,OAAO,GAAU,SAAU,MAAO,GAChD,IAAM,EAAO,SAAU,EAAQ,EAAM,KAAO,IAAA,GAC5C,GAAI,IAAS,cAAgB,IAAS,eAAgB,MAAO,GAC7D,IAAM,EAAQ,UAAW,EAAQ,EAAM,MAAQ,IAAA,GAC/C,MACE,CAAC,CAAC,GACF,OAAO,GAAU,UACjB,SAAU,IACT,EAAM,OAAS,cAAgB,EAAM,OAAS,eAEnD,CAEA,IAAM,EAAN,KAAsB,CACpB,aAAa,cAA6C,CAExD,OADI,EAAe,EAAU,EAAA,mBAAmB,EACzC,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,aAAa,CACxE,CAEA,aAAa,WACX,EACA,EACgC,CAGhC,GAAI,EAAe,EAAG,OAAO,EAAA,kBAAkB,CAAI,EACnD,IAAM,EAA6B,EAAgB,CAAE,eAAc,EAAI,CAAC,EACxE,OAAO,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,WACvD,EACA,CACF,CACF,CAEA,aAAa,YACX,EACA,EACkC,CAElC,OADI,EAAe,EAAU,EAAA,iBAAiB,EAAM,CAAO,EACpD,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,YACvD,EACA,CACF,CACF,CAEA,aAAa,cAAc,EAAgD,CAEzE,OADI,EAAe,EAAU,EAAA,mBAAmB,CAAI,EAC7C,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,cACvD,CACF,CACF,CAEA,aAAa,cACX,EACA,EACkC,CAElC,OADI,EAAe,EAAU,EAAA,mBAAmB,EAAM,CAAO,EACtD,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,cACvD,EACA,CACF,CACF,CAEA,aAAa,gBAAgB,EAAgD,CAE3E,OADI,EAAe,EAAU,EAAA,qBAAqB,CAAI,EAC/C,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,gBACvD,CACF,CACF,CAcA,aAAa,gBACX,EACA,EACyC,CACzC,GAAI,EAAe,EAAG,OAAO,KAC7B,IAAM,EAAS,IAAI,EAAA,eAAe,CAChC,GAAG,EAAA,4BAA4B,EAC/B,QAAS,GACX,CAAC,EACD,GAAI,CACF,OAAO,MAAM,EAAO,gBAAgB,EAAM,CAAO,CACnD,OAAS,EAAO,CAGd,IAAM,EACJ,GAAS,OAAO,GAAU,UAAY,WAAY,EAC7C,EAA+B,OAChC,IAAA,GACN,GACE,IAAW,KACX,IAAW,KACV,OAAO,GAAW,UAAY,GAAU,KACzC,EAAY,CAAK,EAEjB,OAAO,KAET,MAAM,CACR,QAAU,CACR,EAAO,MAAM,CACf,CACF,CACF"}
@@ -1,5 +1,5 @@
1
- import type { ProfileInfo, ProfileListResponse, ProfileDetailResponse, ProfileMutationResponse, ActivateProfileResponse, SaveProfileRequest, ExposeSecretsMode } from "@openhands/typescript-client";
2
- export type { ProfileInfo, ProfileListResponse, ProfileDetailResponse, ProfileMutationResponse, ActivateProfileResponse, SaveProfileRequest, ExposeSecretsMode, };
1
+ import { type ProfileInfo, type ProfileListResponse, type ProfileDetailResponse, type ProfileMutationResponse, type ActivateProfileResponse, type SaveProfileRequest, type ExposeSecretsMode, type ValidateProfileResponse } from "@openhands/typescript-client";
2
+ export type { ProfileInfo, ProfileListResponse, ProfileDetailResponse, ProfileMutationResponse, ActivateProfileResponse, SaveProfileRequest, ExposeSecretsMode, ValidateProfileResponse, };
3
3
  declare class ProfilesService {
4
4
  static listProfiles(): Promise<ProfileListResponse>;
5
5
  static getProfile(name: string, exposeSecrets?: ExposeSecretsMode): Promise<ProfileDetailResponse>;
@@ -7,5 +7,18 @@ declare class ProfilesService {
7
7
  static deleteProfile(name: string): Promise<ProfileMutationResponse>;
8
8
  static renameProfile(name: string, newName: string): Promise<ProfileMutationResponse>;
9
9
  static activateProfile(name: string): Promise<ActivateProfileResponse>;
10
+ /**
11
+ * Pre-flight check: fire a minimal LLM completion to catch misconfigurations
12
+ * (invalid model names, missing provider prefixes, bad base URLs, invalid
13
+ * API keys) before a profile is saved.
14
+ *
15
+ * Returns `{ valid: true }` when the LLM responds, or
16
+ * `{ valid: false, error: { type, message } }` on a blocking error.
17
+ * Transient errors (rate limits, timeouts) are non-blocking.
18
+ *
19
+ * Cloud backends do not implement this endpoint; `null` signals
20
+ * "no verdict" so callers fall through to the normal save path.
21
+ */
22
+ static validateProfile(name: string, request: SaveProfileRequest): Promise<ValidateProfileResponse | null>;
10
23
  }
11
24
  export default ProfilesService;
@@ -7,7 +7,14 @@ import { activateCloudProfile as r, deleteCloudProfile as i, fetchCloudProfile a
7
7
  function l() {
8
8
  return t().backend.kind === "cloud";
9
9
  }
10
- var u = class {
10
+ function u(e) {
11
+ if (!e || typeof e != "object") return !1;
12
+ let t = "name" in e ? e.name : void 0;
13
+ if (t === "AbortError" || t === "TimeoutError") return !0;
14
+ let n = "cause" in e ? e.cause : void 0;
15
+ return !!n && typeof n == "object" && "name" in n && (n.name === "AbortError" || n.name === "TimeoutError");
16
+ }
17
+ var d = class {
11
18
  static async listProfiles() {
12
19
  return l() ? o() : new e(n()).listProfiles();
13
20
  }
@@ -28,8 +35,24 @@ var u = class {
28
35
  static async activateProfile(t) {
29
36
  return l() ? r(t) : new e(n()).activateProfile(t);
30
37
  }
38
+ static async validateProfile(t, r) {
39
+ if (l()) return null;
40
+ let i = new e({
41
+ ...n(),
42
+ timeout: 3e4
43
+ });
44
+ try {
45
+ return await i.validateProfile(t, r);
46
+ } catch (e) {
47
+ let t = e && typeof e == "object" && "status" in e ? e.status : void 0;
48
+ if (t === 404 || t === 429 || typeof t == "number" && t >= 500 || u(e)) return null;
49
+ throw e;
50
+ } finally {
51
+ i.close();
52
+ }
53
+ }
31
54
  };
32
55
  //#endregion
33
- export { u as default };
56
+ export { d as default };
34
57
 
35
58
  //# sourceMappingURL=profiles-service.api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"profiles-service.api.js","names":[],"sources":["../../../src/api/profiles-service/profiles-service.api.ts"],"sourcesContent":["/**\n * ProfilesService is the single entry point for LLM-profile CRUD, routing per\n * active backend so callers (hooks, the settings manager) stay backend-agnostic:\n * - local agent-server: the SDK's ProfilesClient (`/api/profiles`), created\n * per-call to pick up current backend configuration;\n * - cloud app-server: `src/api/cloud/profiles-service.api.ts` (the org-gated\n * `/api/organizations/{orgId}/profiles` routes, or the per-user settings\n * route as a fallback) via the org-scoped cloud proxy.\n * This mirrors how SettingsService branches to fetchCloudSettings().\n *\n * Uses ProfilesClient from @openhands/typescript-client v0.2.0+.\n * All types are re-exported from the SDK for consumer convenience.\n *\n * Note: Unlike some SDK clients, we don't call client.close() here for\n * consistency with other services (SettingsService, SecretsService) that\n * also create SDK clients without explicit cleanup. The SDK clients use\n * fetch-based HTTP which doesn't require connection cleanup.\n */\nimport {\n ProfilesClient,\n type GetProfileOptions,\n} from \"@openhands/typescript-client/clients\";\nimport type {\n ProfileInfo,\n ProfileListResponse,\n ProfileDetailResponse,\n ProfileMutationResponse,\n ActivateProfileResponse,\n SaveProfileRequest,\n ExposeSecretsMode,\n} from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport { getActiveBackend } from \"../backend-registry/active-store\";\nimport {\n activateCloudProfile,\n deleteCloudProfile,\n fetchCloudProfile,\n fetchCloudProfiles,\n renameCloudProfile,\n saveCloudProfile,\n} from \"../cloud/profiles-service.api\";\n\n// Re-export SDK types for consumers\nexport type {\n ProfileInfo,\n ProfileListResponse,\n ProfileDetailResponse,\n ProfileMutationResponse,\n ActivateProfileResponse,\n SaveProfileRequest,\n ExposeSecretsMode,\n};\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nclass ProfilesService {\n static async listProfiles(): Promise<ProfileListResponse> {\n if (isCloudBackend()) return fetchCloudProfiles();\n return new ProfilesClient(getAgentServerClientOptions()).listProfiles();\n }\n\n static async getProfile(\n name: string,\n exposeSecrets?: ExposeSecretsMode,\n ): Promise<ProfileDetailResponse> {\n // Cloud never exposes profile secrets (api_key is always nulled with an\n // api_key_set flag), so `exposeSecrets` is local-only.\n if (isCloudBackend()) return fetchCloudProfile(name);\n const options: GetProfileOptions = exposeSecrets ? { exposeSecrets } : {};\n return new ProfilesClient(getAgentServerClientOptions()).getProfile(\n name,\n options,\n );\n }\n\n static async saveProfile(\n name: string,\n request: SaveProfileRequest,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return saveCloudProfile(name, request);\n return new ProfilesClient(getAgentServerClientOptions()).saveProfile(\n name,\n request,\n );\n }\n\n static async deleteProfile(name: string): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return deleteCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).deleteProfile(\n name,\n );\n }\n\n static async renameProfile(\n name: string,\n newName: string,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return renameCloudProfile(name, newName);\n return new ProfilesClient(getAgentServerClientOptions()).renameProfile(\n name,\n newName,\n );\n }\n\n static async activateProfile(name: string): Promise<ActivateProfileResponse> {\n if (isCloudBackend()) return activateCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).activateProfile(\n name,\n );\n }\n}\n\nexport default ProfilesService;\n"],"mappings":";;;;;;AAqDA,SAAS,IAA0B;CACjC,OAAO,EAAiB,EAAE,QAAQ,SAAS;AAC7C;AAEA,IAAM,IAAN,MAAsB;CACpB,aAAa,eAA6C;EAExD,OADI,EAAe,IAAU,EAAmB,IACzC,IAAI,EAAe,EAA4B,CAAC,EAAE,aAAa;CACxE;CAEA,aAAa,WACX,GACA,GACgC;EAGhC,IAAI,EAAe,GAAG,OAAO,EAAkB,CAAI;EACnD,IAAM,IAA6B,IAAgB,EAAE,iBAAc,IAAI,CAAC;EACxE,OAAO,IAAI,EAAe,EAA4B,CAAC,EAAE,WACvD,GACA,CACF;CACF;CAEA,aAAa,YACX,GACA,GACkC;EAElC,OADI,EAAe,IAAU,EAAiB,GAAM,CAAO,IACpD,IAAI,EAAe,EAA4B,CAAC,EAAE,YACvD,GACA,CACF;CACF;CAEA,aAAa,cAAc,GAAgD;EAEzE,OADI,EAAe,IAAU,EAAmB,CAAI,IAC7C,IAAI,EAAe,EAA4B,CAAC,EAAE,cACvD,CACF;CACF;CAEA,aAAa,cACX,GACA,GACkC;EAElC,OADI,EAAe,IAAU,EAAmB,GAAM,CAAO,IACtD,IAAI,EAAe,EAA4B,CAAC,EAAE,cACvD,GACA,CACF;CACF;CAEA,aAAa,gBAAgB,GAAgD;EAE3E,OADI,EAAe,IAAU,EAAqB,CAAI,IAC/C,IAAI,EAAe,EAA4B,CAAC,EAAE,gBACvD,CACF;CACF;AACF"}
1
+ {"version":3,"file":"profiles-service.api.js","names":[],"sources":["../../../src/api/profiles-service/profiles-service.api.ts"],"sourcesContent":["/**\n * ProfilesService is the single entry point for LLM-profile CRUD, routing per\n * active backend so callers (hooks, the settings manager) stay backend-agnostic:\n * - local agent-server: the SDK's ProfilesClient (`/api/profiles`), created\n * per-call to pick up current backend configuration;\n * - cloud app-server: `src/api/cloud/profiles-service.api.ts` (the org-gated\n * `/api/organizations/{orgId}/profiles` routes, or the per-user settings\n * route as a fallback) via the org-scoped cloud proxy.\n * This mirrors how SettingsService branches to fetchCloudSettings().\n *\n * Uses ProfilesClient from @openhands/typescript-client v0.2.0+.\n * All types are re-exported from the SDK for consumer convenience.\n *\n * Note: Unlike some SDK clients, we don't call client.close() here for\n * consistency with other services (SettingsService, SecretsService) that\n * also create SDK clients without explicit cleanup. The SDK clients use\n * fetch-based HTTP which doesn't require connection cleanup.\n */\nimport {\n ProfilesClient,\n type GetProfileOptions,\n} from \"@openhands/typescript-client/clients\";\nimport {\n type ProfileInfo,\n type ProfileListResponse,\n type ProfileDetailResponse,\n type ProfileMutationResponse,\n type ActivateProfileResponse,\n type SaveProfileRequest,\n type ExposeSecretsMode,\n type ValidateProfileResponse,\n} from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport { getActiveBackend } from \"../backend-registry/active-store\";\nimport {\n activateCloudProfile,\n deleteCloudProfile,\n fetchCloudProfile,\n fetchCloudProfiles,\n renameCloudProfile,\n saveCloudProfile,\n} from \"../cloud/profiles-service.api\";\n\n// Re-export SDK types for consumers\nexport type {\n ProfileInfo,\n ProfileListResponse,\n ProfileDetailResponse,\n ProfileMutationResponse,\n ActivateProfileResponse,\n SaveProfileRequest,\n ExposeSecretsMode,\n ValidateProfileResponse,\n};\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nfunction isAbortLike(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const name = \"name\" in error ? error.name : undefined;\n if (name === \"AbortError\" || name === \"TimeoutError\") return true;\n const cause = \"cause\" in error ? error.cause : undefined;\n return (\n !!cause &&\n typeof cause === \"object\" &&\n \"name\" in cause &&\n (cause.name === \"AbortError\" || cause.name === \"TimeoutError\")\n );\n}\n\nclass ProfilesService {\n static async listProfiles(): Promise<ProfileListResponse> {\n if (isCloudBackend()) return fetchCloudProfiles();\n return new ProfilesClient(getAgentServerClientOptions()).listProfiles();\n }\n\n static async getProfile(\n name: string,\n exposeSecrets?: ExposeSecretsMode,\n ): Promise<ProfileDetailResponse> {\n // Cloud never exposes profile secrets (api_key is always nulled with an\n // api_key_set flag), so `exposeSecrets` is local-only.\n if (isCloudBackend()) return fetchCloudProfile(name);\n const options: GetProfileOptions = exposeSecrets ? { exposeSecrets } : {};\n return new ProfilesClient(getAgentServerClientOptions()).getProfile(\n name,\n options,\n );\n }\n\n static async saveProfile(\n name: string,\n request: SaveProfileRequest,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return saveCloudProfile(name, request);\n return new ProfilesClient(getAgentServerClientOptions()).saveProfile(\n name,\n request,\n );\n }\n\n static async deleteProfile(name: string): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return deleteCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).deleteProfile(\n name,\n );\n }\n\n static async renameProfile(\n name: string,\n newName: string,\n ): Promise<ProfileMutationResponse> {\n if (isCloudBackend()) return renameCloudProfile(name, newName);\n return new ProfilesClient(getAgentServerClientOptions()).renameProfile(\n name,\n newName,\n );\n }\n\n static async activateProfile(name: string): Promise<ActivateProfileResponse> {\n if (isCloudBackend()) return activateCloudProfile(name);\n return new ProfilesClient(getAgentServerClientOptions()).activateProfile(\n name,\n );\n }\n\n /**\n * Pre-flight check: fire a minimal LLM completion to catch misconfigurations\n * (invalid model names, missing provider prefixes, bad base URLs, invalid\n * API keys) before a profile is saved.\n *\n * Returns `{ valid: true }` when the LLM responds, or\n * `{ valid: false, error: { type, message } }` on a blocking error.\n * Transient errors (rate limits, timeouts) are non-blocking.\n *\n * Cloud backends do not implement this endpoint; `null` signals\n * \"no verdict\" so callers fall through to the normal save path.\n */\n static async validateProfile(\n name: string,\n request: SaveProfileRequest,\n ): Promise<ValidateProfileResponse | null> {\n if (isCloudBackend()) return null;\n const client = new ProfilesClient({\n ...getAgentServerClientOptions(),\n timeout: 30000,\n });\n try {\n return await client.validateProfile(name, request);\n } catch (error) {\n // Older agent-server versions don't have the endpoint → 404\n // Treat as \"no verdict\" rather than blocking the save.\n const status =\n error && typeof error === \"object\" && \"status\" in error\n ? (error as { status?: unknown }).status\n : undefined;\n if (\n status === 404 ||\n status === 429 ||\n (typeof status === \"number\" && status >= 500) ||\n isAbortLike(error)\n ) {\n return null;\n }\n throw error;\n } finally {\n client.close();\n }\n }\n}\n\nexport default ProfilesService;\n"],"mappings":";;;;;;AAuDA,SAAS,IAA0B;CACjC,OAAO,EAAiB,EAAE,QAAQ,SAAS;AAC7C;AAEA,SAAS,EAAY,GAAyB;CAC5C,IAAI,CAAC,KAAS,OAAO,KAAU,UAAU,OAAO;CAChD,IAAM,IAAO,UAAU,IAAQ,EAAM,OAAO,KAAA;CAC5C,IAAI,MAAS,gBAAgB,MAAS,gBAAgB,OAAO;CAC7D,IAAM,IAAQ,WAAW,IAAQ,EAAM,QAAQ,KAAA;CAC/C,OACE,CAAC,CAAC,KACF,OAAO,KAAU,YACjB,UAAU,MACT,EAAM,SAAS,gBAAgB,EAAM,SAAS;AAEnD;AAEA,IAAM,IAAN,MAAsB;CACpB,aAAa,eAA6C;EAExD,OADI,EAAe,IAAU,EAAmB,IACzC,IAAI,EAAe,EAA4B,CAAC,EAAE,aAAa;CACxE;CAEA,aAAa,WACX,GACA,GACgC;EAGhC,IAAI,EAAe,GAAG,OAAO,EAAkB,CAAI;EACnD,IAAM,IAA6B,IAAgB,EAAE,iBAAc,IAAI,CAAC;EACxE,OAAO,IAAI,EAAe,EAA4B,CAAC,EAAE,WACvD,GACA,CACF;CACF;CAEA,aAAa,YACX,GACA,GACkC;EAElC,OADI,EAAe,IAAU,EAAiB,GAAM,CAAO,IACpD,IAAI,EAAe,EAA4B,CAAC,EAAE,YACvD,GACA,CACF;CACF;CAEA,aAAa,cAAc,GAAgD;EAEzE,OADI,EAAe,IAAU,EAAmB,CAAI,IAC7C,IAAI,EAAe,EAA4B,CAAC,EAAE,cACvD,CACF;CACF;CAEA,aAAa,cACX,GACA,GACkC;EAElC,OADI,EAAe,IAAU,EAAmB,GAAM,CAAO,IACtD,IAAI,EAAe,EAA4B,CAAC,EAAE,cACvD,GACA,CACF;CACF;CAEA,aAAa,gBAAgB,GAAgD;EAE3E,OADI,EAAe,IAAU,EAAqB,CAAI,IAC/C,IAAI,EAAe,EAA4B,CAAC,EAAE,gBACvD,CACF;CACF;CAcA,aAAa,gBACX,GACA,GACyC;EACzC,IAAI,EAAe,GAAG,OAAO;EAC7B,IAAM,IAAS,IAAI,EAAe;GAChC,GAAG,EAA4B;GAC/B,SAAS;EACX,CAAC;EACD,IAAI;GACF,OAAO,MAAM,EAAO,gBAAgB,GAAM,CAAO;EACnD,SAAS,GAAO;GAGd,IAAM,IACJ,KAAS,OAAO,KAAU,YAAY,YAAY,IAC7C,EAA+B,SAChC,KAAA;GACN,IACE,MAAW,OACX,MAAW,OACV,OAAO,KAAW,YAAY,KAAU,OACzC,EAAY,CAAK,GAEjB,OAAO;GAET,MAAM;EACR,UAAU;GACR,EAAO,MAAM;EACf;CACF;AACF"}
@@ -1,2 +1,2 @@
1
- require("../_virtual/_rolldown/runtime.cjs");const e=require("../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs");require("../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("./backend-registry/active-store.cjs"),n=require("./agent-server-client-options.cjs"),r=require("./agent-server-compatibility.cjs"),i=require("./with-retry.cjs"),a=require("./cloud/secrets-service.api.cjs");var o=class{static async getSecrets(){try{return t.getActiveBackend().backend.kind===`cloud`?await i.withRetry(()=>a.fetchCloudSecrets()):(await i.withRetry(()=>new e.SettingsClient(n.getAgentServerClientOptions()).listSecrets())).secrets.map(e=>({name:e.name,description:e.description}))}catch(e){return console.error(`Failed to fetch secrets after retries:`,e),[]}}static async createSecret(r,o,s){if(t.getActiveBackend().backend.kind===`cloud`){await a.saveCloudSecret({name:r,value:o,description:s});return}await i.withRetry(()=>new e.SettingsClient(n.getAgentServerClientOptions()).upsertSecret({name:r,value:o,description:s}))}static async updateSecret(r,o,s,c){if(t.getActiveBackend().backend.kind===`cloud`){await a.saveCloudSecret({name:o,value:c,description:s,previousName:r});return}let l=new e.SettingsClient(n.getAgentServerClientOptions()),u=c??await i.withRetry(()=>l.getSecret(r));await i.withRetry(()=>l.upsertSecret({name:o,value:u,description:s})),o!==r&&await this.deleteSecret(r)}static async deleteSecret(o){try{if(t.getActiveBackend().backend.kind===`cloud`){await i.withRetry(()=>a.deleteCloudSecret(o));return}await i.withRetry(()=>new e.SettingsClient(n.getAgentServerClientOptions()).deleteSecret(o))}catch(e){if(r.isSdkHttpStatusError(e,404)||e&&typeof e==`object`&&`response`in e&&e.response?.status===404)return;throw e}}};exports.SecretsService=o;
1
+ require("../_virtual/_rolldown/runtime.cjs");const e=require("../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs");require("../node_modules/@openhands/typescript-client/dist/clients.cjs");const t=require("./backend-registry/active-store.cjs"),n=require("./agent-server-client-options.cjs"),r=require("./agent-server-compatibility.cjs"),i=require("./with-retry.cjs"),a=require("./cloud/secrets-service.api.cjs");async function o(){return t.getActiveBackend().backend.kind===`cloud`?i.withRetry(()=>a.fetchCloudSecrets()):(await i.withRetry(()=>new e.SettingsClient(n.getAgentServerClientOptions()).listSecrets())).secrets.map(e=>({name:e.name,description:e.description}))}var s=class{static async getSecrets(){try{return await o()}catch(e){return console.error(`Failed to fetch secrets after retries:`,e),[]}}static async getSecretsOrThrow(){return o()}static async createSecret(r,o,s){if(t.getActiveBackend().backend.kind===`cloud`){await a.saveCloudSecret({name:r,value:o,description:s});return}await i.withRetry(()=>new e.SettingsClient(n.getAgentServerClientOptions()).upsertSecret({name:r,value:o,description:s}))}static async updateSecret(r,o,s,c){if(t.getActiveBackend().backend.kind===`cloud`){await a.saveCloudSecret({name:o,value:c,description:s,previousName:r});return}let l=new e.SettingsClient(n.getAgentServerClientOptions()),u=c??await i.withRetry(()=>l.getSecret(r));await i.withRetry(()=>l.upsertSecret({name:o,value:u,description:s})),o!==r&&await this.deleteSecret(r)}static async deleteSecret(o){try{if(t.getActiveBackend().backend.kind===`cloud`){await i.withRetry(()=>a.deleteCloudSecret(o));return}await i.withRetry(()=>new e.SettingsClient(n.getAgentServerClientOptions()).deleteSecret(o))}catch(e){if(r.isSdkHttpStatusError(e,404)||e&&typeof e==`object`&&`response`in e&&e.response?.status===404)return;throw e}}};exports.SecretsService=s;
2
2
  //# sourceMappingURL=secrets-service.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"secrets-service.cjs","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n deleteCloudSecret,\n fetchCloudSecrets,\n saveCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\nimport { withRetry } from \"./with-retry\";\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return await withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({ name, value, description });\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's name and/or description, and optionally overwrite its\n * value. When no value is given the existing one is preserved: the\n * agent-server only exposes an upsert endpoint, so we fetch the existing\n * value and re-upsert it under the updated name/description.\n *\n * @param secretToEdit - Existing secret name\n * @param name - New (or same) secret name\n * @param description - Optional new description\n * @param value - Optional new value; when omitted the stored value is kept\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n secretToEdit: string,\n name: string,\n description?: string,\n value?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({\n name,\n value,\n description,\n previousName: secretToEdit,\n });\n return;\n }\n\n const client = new SettingsClient(getAgentServerClientOptions());\n const nextValue =\n value ?? (await withRetry(() => client.getSecret(secretToEdit)));\n\n await withRetry(() =>\n client.upsertSecret({\n name,\n value: nextValue,\n description,\n }),\n );\n\n if (name !== secretToEdit) {\n await this.deleteSecret(secretToEdit);\n }\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":"qbAYA,IAAa,EAAb,KAA4B,CAQ1B,aAAa,YAAkD,CAC7D,GAAI,CAOF,OANI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAC/B,MAAM,EAAA,cAAgB,EAAA,kBAAkB,CAAC,GAK3C,MAHgB,EAAA,cACrB,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,YAAY,CAChE,GACgB,QAAQ,IAAK,IAAO,CAClC,KAAM,EAAE,KACR,YAAa,EAAE,WACjB,EAAE,CACJ,OAAS,EAAO,CAEd,OADA,QAAQ,MAAM,yCAA0C,CAAK,EACtD,CAAC,CACV,CACF,CAWA,aAAa,aACX,EACA,EACA,EACe,CACf,GAAI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAAS,CAC/C,MAAM,EAAA,gBAAgB,CAAE,OAAM,QAAO,aAAY,CAAC,EAClD,MACF,CACA,MAAM,EAAA,cACJ,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,aAAa,CAC7D,OACA,QACA,aACF,CAAC,CACH,CACF,CAcA,aAAa,aACX,EACA,EACA,EACA,EACe,CACf,GAAI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAAS,CAC/C,MAAM,EAAA,gBAAgB,CACpB,OACA,QACA,cACA,aAAc,CAChB,CAAC,EACD,MACF,CAEA,IAAM,EAAS,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EACzD,EACJ,GAAU,MAAM,EAAA,cAAgB,EAAO,UAAU,CAAY,CAAC,EAEhE,MAAM,EAAA,cACJ,EAAO,aAAa,CAClB,OACA,MAAO,EACP,aACF,CAAC,CACH,EAEI,IAAS,GACX,MAAM,KAAK,aAAa,CAAY,CAExC,CASA,aAAa,aAAa,EAA6B,CACrD,GAAI,CACF,GAAI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAAS,CAC/C,MAAM,EAAA,cAAgB,EAAA,kBAAkB,CAAI,CAAC,EAC7C,MACF,CACA,MAAM,EAAA,cACJ,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,aAAa,CAAI,CACrE,CACF,OAAS,EAAO,CAId,GACE,EAAA,qBAAqB,EAAO,GAAG,GAC9B,GACC,OAAO,GAAU,UACjB,aAAc,GACb,EAA6C,UAAU,SACtD,IAEJ,OAEF,MAAM,CACR,CACF,CACF"}
1
+ {"version":3,"file":"secrets-service.cjs","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n deleteCloudSecret,\n fetchCloudSecrets,\n saveCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\nimport { withRetry } from \"./with-retry\";\n\nasync function fetchSecrets(): Promise<CustomSecretWithoutValue[]> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n}\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n return await fetchSecrets();\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * List all custom secrets, surfacing failures to callers that must\n * distinguish an unavailable list from an empty one.\n */\n static async getSecretsOrThrow(): Promise<CustomSecretWithoutValue[]> {\n return fetchSecrets();\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({ name, value, description });\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's name and/or description, and optionally overwrite its\n * value. When no value is given the existing one is preserved: the\n * agent-server only exposes an upsert endpoint, so we fetch the existing\n * value and re-upsert it under the updated name/description.\n *\n * @param secretToEdit - Existing secret name\n * @param name - New (or same) secret name\n * @param description - Optional new description\n * @param value - Optional new value; when omitted the stored value is kept\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n secretToEdit: string,\n name: string,\n description?: string,\n value?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({\n name,\n value,\n description,\n previousName: secretToEdit,\n });\n return;\n }\n\n const client = new SettingsClient(getAgentServerClientOptions());\n const nextValue =\n value ?? (await withRetry(() => client.getSecret(secretToEdit)));\n\n await withRetry(() =>\n client.upsertSecret({\n name,\n value: nextValue,\n description,\n }),\n );\n\n if (name !== secretToEdit) {\n await this.deleteSecret(secretToEdit);\n }\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":"qbAYA,eAAe,GAAoD,CAOjE,OANI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAC/B,EAAA,cAAgB,EAAA,kBAAkB,CAAC,GAKrC,MAHgB,EAAA,cACrB,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,YAAY,CAChE,GACgB,QAAQ,IAAK,IAAO,CAClC,KAAM,EAAE,KACR,YAAa,EAAE,WACjB,EAAE,CACJ,CAEA,IAAa,EAAb,KAA4B,CAQ1B,aAAa,YAAkD,CAC7D,GAAI,CACF,OAAO,MAAM,EAAa,CAC5B,OAAS,EAAO,CAEd,OADA,QAAQ,MAAM,yCAA0C,CAAK,EACtD,CAAC,CACV,CACF,CAMA,aAAa,mBAAyD,CACpE,OAAO,EAAa,CACtB,CAWA,aAAa,aACX,EACA,EACA,EACe,CACf,GAAI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAAS,CAC/C,MAAM,EAAA,gBAAgB,CAAE,OAAM,QAAO,aAAY,CAAC,EAClD,MACF,CACA,MAAM,EAAA,cACJ,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,aAAa,CAC7D,OACA,QACA,aACF,CAAC,CACH,CACF,CAcA,aAAa,aACX,EACA,EACA,EACA,EACe,CACf,GAAI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAAS,CAC/C,MAAM,EAAA,gBAAgB,CACpB,OACA,QACA,cACA,aAAc,CAChB,CAAC,EACD,MACF,CAEA,IAAM,EAAS,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EACzD,EACJ,GAAU,MAAM,EAAA,cAAgB,EAAO,UAAU,CAAY,CAAC,EAEhE,MAAM,EAAA,cACJ,EAAO,aAAa,CAClB,OACA,MAAO,EACP,aACF,CAAC,CACH,EAEI,IAAS,GACX,MAAM,KAAK,aAAa,CAAY,CAExC,CASA,aAAa,aAAa,EAA6B,CACrD,GAAI,CACF,GAAI,EAAA,iBAAiB,EAAE,QAAQ,OAAS,QAAS,CAC/C,MAAM,EAAA,cAAgB,EAAA,kBAAkB,CAAI,CAAC,EAC7C,MACF,CACA,MAAM,EAAA,cACJ,IAAI,EAAA,eAAe,EAAA,4BAA4B,CAAC,EAAE,aAAa,CAAI,CACrE,CACF,OAAS,EAAO,CAId,GACE,EAAA,qBAAqB,EAAO,GAAG,GAC9B,GACC,OAAO,GAAU,UACjB,aAAc,GACb,EAA6C,UAAU,SACtD,IAEJ,OAEF,MAAM,CACR,CACF,CACF"}
@@ -8,6 +8,11 @@ export declare class SecretsService {
8
8
  * All secrets are returned in a single response.
9
9
  */
10
10
  static getSecrets(): Promise<CustomSecretWithoutValue[]>;
11
+ /**
12
+ * List all custom secrets, surfacing failures to callers that must
13
+ * distinguish an unavailable list from an empty one.
14
+ */
15
+ static getSecretsOrThrow(): Promise<CustomSecretWithoutValue[]>;
11
16
  /**
12
17
  * Create or update a custom secret (upsert by name).
13
18
  * Uses the agent-server API endpoint: PUT /api/settings/secrets
@@ -6,17 +6,23 @@ import { isSdkHttpStatusError as r } from "./agent-server-compatibility.js";
6
6
  import { withRetry as i } from "./with-retry.js";
7
7
  import { deleteCloudSecret as a, fetchCloudSecrets as o, saveCloudSecret as s } from "./cloud/secrets-service.api.js";
8
8
  //#region src/api/secrets-service.ts
9
- var c = class {
9
+ async function c() {
10
+ return t().backend.kind === "cloud" ? i(() => o()) : (await i(() => new e(n()).listSecrets())).secrets.map((e) => ({
11
+ name: e.name,
12
+ description: e.description
13
+ }));
14
+ }
15
+ var l = class {
10
16
  static async getSecrets() {
11
17
  try {
12
- return t().backend.kind === "cloud" ? await i(() => o()) : (await i(() => new e(n()).listSecrets())).secrets.map((e) => ({
13
- name: e.name,
14
- description: e.description
15
- }));
18
+ return await c();
16
19
  } catch (e) {
17
20
  return console.error("Failed to fetch secrets after retries:", e), [];
18
21
  }
19
22
  }
23
+ static async getSecretsOrThrow() {
24
+ return c();
25
+ }
20
26
  static async createSecret(r, a, o) {
21
27
  if (t().backend.kind === "cloud") {
22
28
  await s({
@@ -63,6 +69,6 @@ var c = class {
63
69
  }
64
70
  };
65
71
  //#endregion
66
- export { c as SecretsService };
72
+ export { l as SecretsService };
67
73
 
68
74
  //# sourceMappingURL=secrets-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"secrets-service.js","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n deleteCloudSecret,\n fetchCloudSecrets,\n saveCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\nimport { withRetry } from \"./with-retry\";\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return await withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({ name, value, description });\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's name and/or description, and optionally overwrite its\n * value. When no value is given the existing one is preserved: the\n * agent-server only exposes an upsert endpoint, so we fetch the existing\n * value and re-upsert it under the updated name/description.\n *\n * @param secretToEdit - Existing secret name\n * @param name - New (or same) secret name\n * @param description - Optional new description\n * @param value - Optional new value; when omitted the stored value is kept\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n secretToEdit: string,\n name: string,\n description?: string,\n value?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({\n name,\n value,\n description,\n previousName: secretToEdit,\n });\n return;\n }\n\n const client = new SettingsClient(getAgentServerClientOptions());\n const nextValue =\n value ?? (await withRetry(() => client.getSecret(secretToEdit)));\n\n await withRetry(() =>\n client.upsertSecret({\n name,\n value: nextValue,\n description,\n }),\n );\n\n if (name !== secretToEdit) {\n await this.deleteSecret(secretToEdit);\n }\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":";;;;;;;;AAYA,IAAa,IAAb,MAA4B;CAQ1B,aAAa,aAAkD;EAC7D,IAAI;GAOF,OANI,EAAiB,EAAE,QAAQ,SAAS,UAC/B,MAAM,QAAgB,EAAkB,CAAC,KAK3C,MAHgB,QACrB,IAAI,EAAe,EAA4B,CAAC,EAAE,YAAY,CAChE,GACgB,QAAQ,KAAK,OAAO;IAClC,MAAM,EAAE;IACR,aAAa,EAAE;GACjB,EAAE;EACJ,SAAS,GAAO;GAEd,OADA,QAAQ,MAAM,0CAA0C,CAAK,GACtD,CAAC;EACV;CACF;CAWA,aAAa,aACX,GACA,GACA,GACe;EACf,IAAI,EAAiB,EAAE,QAAQ,SAAS,SAAS;GAC/C,MAAM,EAAgB;IAAE;IAAM;IAAO;GAAY,CAAC;GAClD;EACF;EACA,MAAM,QACJ,IAAI,EAAe,EAA4B,CAAC,EAAE,aAAa;GAC7D;GACA;GACA;EACF,CAAC,CACH;CACF;CAcA,aAAa,aACX,GACA,GACA,GACA,GACe;EACf,IAAI,EAAiB,EAAE,QAAQ,SAAS,SAAS;GAC/C,MAAM,EAAgB;IACpB;IACA;IACA;IACA,cAAc;GAChB,CAAC;GACD;EACF;EAEA,IAAM,IAAS,IAAI,EAAe,EAA4B,CAAC,GACzD,IACJ,KAAU,MAAM,QAAgB,EAAO,UAAU,CAAY,CAAC;EAUhE,AARA,MAAM,QACJ,EAAO,aAAa;GAClB;GACA,OAAO;GACP;EACF,CAAC,CACH,GAEI,MAAS,KACX,MAAM,KAAK,aAAa,CAAY;CAExC;CASA,aAAa,aAAa,GAA6B;EACrD,IAAI;GACF,IAAI,EAAiB,EAAE,QAAQ,SAAS,SAAS;IAC/C,MAAM,QAAgB,EAAkB,CAAI,CAAC;IAC7C;GACF;GACA,MAAM,QACJ,IAAI,EAAe,EAA4B,CAAC,EAAE,aAAa,CAAI,CACrE;EACF,SAAS,GAAO;GAId,IACE,EAAqB,GAAO,GAAG,KAC9B,KACC,OAAO,KAAU,YACjB,cAAc,KACb,EAA6C,UAAU,WACtD,KAEJ;GAEF,MAAM;EACR;CACF;AACF"}
1
+ {"version":3,"file":"secrets-service.js","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n deleteCloudSecret,\n fetchCloudSecrets,\n saveCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\nimport { withRetry } from \"./with-retry\";\n\nasync function fetchSecrets(): Promise<CustomSecretWithoutValue[]> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n}\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n return await fetchSecrets();\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * List all custom secrets, surfacing failures to callers that must\n * distinguish an unavailable list from an empty one.\n */\n static async getSecretsOrThrow(): Promise<CustomSecretWithoutValue[]> {\n return fetchSecrets();\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({ name, value, description });\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's name and/or description, and optionally overwrite its\n * value. When no value is given the existing one is preserved: the\n * agent-server only exposes an upsert endpoint, so we fetch the existing\n * value and re-upsert it under the updated name/description.\n *\n * @param secretToEdit - Existing secret name\n * @param name - New (or same) secret name\n * @param description - Optional new description\n * @param value - Optional new value; when omitted the stored value is kept\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n secretToEdit: string,\n name: string,\n description?: string,\n value?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await saveCloudSecret({\n name,\n value,\n description,\n previousName: secretToEdit,\n });\n return;\n }\n\n const client = new SettingsClient(getAgentServerClientOptions());\n const nextValue =\n value ?? (await withRetry(() => client.getSecret(secretToEdit)));\n\n await withRetry(() =>\n client.upsertSecret({\n name,\n value: nextValue,\n description,\n }),\n );\n\n if (name !== secretToEdit) {\n await this.deleteSecret(secretToEdit);\n }\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":";;;;;;;;AAYA,eAAe,IAAoD;CAOjE,OANI,EAAiB,EAAE,QAAQ,SAAS,UAC/B,QAAgB,EAAkB,CAAC,KAKrC,MAHgB,QACrB,IAAI,EAAe,EAA4B,CAAC,EAAE,YAAY,CAChE,GACgB,QAAQ,KAAK,OAAO;EAClC,MAAM,EAAE;EACR,aAAa,EAAE;CACjB,EAAE;AACJ;AAEA,IAAa,IAAb,MAA4B;CAQ1B,aAAa,aAAkD;EAC7D,IAAI;GACF,OAAO,MAAM,EAAa;EAC5B,SAAS,GAAO;GAEd,OADA,QAAQ,MAAM,0CAA0C,CAAK,GACtD,CAAC;EACV;CACF;CAMA,aAAa,oBAAyD;EACpE,OAAO,EAAa;CACtB;CAWA,aAAa,aACX,GACA,GACA,GACe;EACf,IAAI,EAAiB,EAAE,QAAQ,SAAS,SAAS;GAC/C,MAAM,EAAgB;IAAE;IAAM;IAAO;GAAY,CAAC;GAClD;EACF;EACA,MAAM,QACJ,IAAI,EAAe,EAA4B,CAAC,EAAE,aAAa;GAC7D;GACA;GACA;EACF,CAAC,CACH;CACF;CAcA,aAAa,aACX,GACA,GACA,GACA,GACe;EACf,IAAI,EAAiB,EAAE,QAAQ,SAAS,SAAS;GAC/C,MAAM,EAAgB;IACpB;IACA;IACA;IACA,cAAc;GAChB,CAAC;GACD;EACF;EAEA,IAAM,IAAS,IAAI,EAAe,EAA4B,CAAC,GACzD,IACJ,KAAU,MAAM,QAAgB,EAAO,UAAU,CAAY,CAAC;EAUhE,AARA,MAAM,QACJ,EAAO,aAAa;GAClB;GACA,OAAO;GACP;EACF,CAAC,CACH,GAEI,MAAS,KACX,MAAM,KAAK,aAAa,CAAY;CAExC;CASA,aAAa,aAAa,GAA6B;EACrD,IAAI;GACF,IAAI,EAAiB,EAAE,QAAQ,SAAS,SAAS;IAC/C,MAAM,QAAgB,EAAkB,CAAI,CAAC;IAC7C;GACF;GACA,MAAM,QACJ,IAAI,EAAe,EAA4B,CAAC,EAAE,aAAa,CAAI,CACrE;EACF,SAAS,GAAO;GAId,IACE,EAAqB,GAAO,GAAG,KAC9B,KACC,OAAO,KAAU,YACjB,cAAc,KACb,EAA6C,UAAU,WACtD,KAEJ;GAEF,MAAM;EACR;CACF;AACF"}
@@ -1,5 +1,4 @@
1
1
  export { UserAssistantEventMessage } from "./user-assistant-event-message";
2
- export { ObservationPairEventMessage } from "./observation-pair-event-message";
3
2
  export { ErrorEventMessage } from "./error-event-message";
4
3
  export { FinishEventMessage } from "./finish-event-message";
5
4
  export { GenericEventMessageWrapper } from "./generic-event-message-wrapper";
@@ -0,0 +1,15 @@
1
+ export type GitSyncActivityState = "idle" | "running" | "succeeded" | "failed";
2
+ interface GitSyncActivityRowProps {
3
+ state: GitSyncActivityState;
4
+ /** When the running cycle started, for the elapsed-time hint. */
5
+ startedAt: string | null;
6
+ /** Automations still waiting to be pushed, shown while a cycle runs. */
7
+ pendingCount: number;
8
+ }
9
+ /**
10
+ * The page's own account of the sync cycle, in place of the fire-and-forget
11
+ * success toast: the trigger returns as soon as the cycle is scheduled, so a
12
+ * toast said "started" and then never came back with an outcome.
13
+ */
14
+ export declare function GitSyncActivityRow({ state, startedAt, pendingCount, }: GitSyncActivityRowProps): import("react").JSX.Element | null;
15
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { GitSyncStatus } from "#/types/git-sync";
2
+ interface GitSyncConfigFormProps {
3
+ status: GitSyncStatus;
4
+ canManage: boolean;
5
+ /**
6
+ * Runs a sync cycle. The same handler the overview's Sync now button uses,
7
+ * so a save-and-sync is followed by the one activity row rather than
8
+ * starting a cycle nothing on the page is watching.
9
+ */
10
+ onSyncNow: () => void;
11
+ }
12
+ export declare function GitSyncConfigForm({ status, canManage, onSyncNow, }: GitSyncConfigFormProps): import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,6 @@
1
+ interface GitSyncErrorBannerProps {
2
+ error: string;
3
+ errorAt: string | null;
4
+ }
5
+ export declare function GitSyncErrorBanner({ error, errorAt, }: GitSyncErrorBannerProps): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1 @@
1
+ export declare function GitSyncNotLocalState(): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import type { GitSyncStatus } from "#/types/git-sync";
2
+ import { type GitSyncActivityState } from "./git-sync-activity-row";
3
+ interface GitSyncOverviewSectionProps {
4
+ status: GitSyncStatus;
5
+ onSyncNow: () => void;
6
+ isSyncing: boolean;
7
+ syncActivity: GitSyncActivityState;
8
+ syncStartedAt: string | null;
9
+ canManage: boolean;
10
+ }
11
+ export declare function GitSyncOverviewSection({ status, onSyncNow, isSyncing, syncActivity, syncStartedAt, canManage, }: GitSyncOverviewSectionProps): import("react").JSX.Element;
12
+ export {};
@@ -0,0 +1 @@
1
+ export declare function GitSyncSkeleton(): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ interface GitSyncStatusPillProps {
2
+ tone: "success" | "neutral" | "warning";
3
+ label: string;
4
+ testId?: string;
5
+ }
6
+ export declare function GitSyncStatusPill({ tone, label, testId, }: GitSyncStatusPillProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shown when the automation backend answers the git-sync endpoints with 404:
3
+ * it predates the API. Without this the page settles on the generic "something
4
+ * went wrong" panel, which reads as a broken install rather than an old
5
+ * backend.
6
+ */
7
+ export declare function GitSyncUnsupportedState(): import("react").JSX.Element;
@@ -1,10 +1,11 @@
1
1
  interface ResponderDeploymentModalProps {
2
2
  isOpen: boolean;
3
+ isPending: boolean;
3
4
  onClose: () => void;
4
5
  /** Fired for the "Continue with local setup" action. */
5
6
  onContinueLocal: () => void;
6
7
  /** Fired for an external-URL action (e.g. OpenHands Cloud integrations). */
7
8
  onOpenUrl: (url: string) => void;
8
9
  }
9
- export declare function ResponderDeploymentModal({ isOpen, onClose, onContinueLocal, onOpenUrl, }: ResponderDeploymentModalProps): import("react").JSX.Element | null;
10
+ export declare function ResponderDeploymentModal({ isOpen, isPending, onClose, onContinueLocal, onOpenUrl, }: ResponderDeploymentModalProps): import("react").JSX.Element | null;
10
11
  export {};
@@ -1,4 +1,4 @@
1
- const e=require("../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../i18n/declaration.cjs"),r=require("../../../types/agent-state.cjs"),i=require("../../../utils/utils.cjs"),a=require("../../../hooks/use-conversation-id.cjs"),o=require("../../../stores/conversation-store.cjs"),s=require("../../../utils/custom-toast-handlers.cjs");require("../../../constants/server-connection-error.cjs");const c=require("../../../stores/error-message-store.cjs"),l=require("../../../stores/optimistic-user-message-store.cjs"),u=require("../../../stores/goal-store.cjs"),d=require("../../../stores/model-store.cjs"),ee=require("../../../contexts/conversation-websocket-context.cjs"),f=require("../../../hooks/use-send-message.cjs"),te=require("../../../hooks/query/use-active-conversation.cjs"),p=require("../../../hooks/use-agent-state.cjs"),ne=require("../../../utils/convert-image-to-base-64.cjs"),re=require("../../../utils/file-validation.cjs"),m=require("../../../utils/pending-task-message-link.cjs"),ie=require("../../../hooks/query/use-task-polling.cjs"),ae=require("../../../hooks/use-tracking.cjs"),oe=require("../../../utils/acp-error-codes.cjs"),se=require("../../../services/chat-service.cjs"),ce=require("./btw-messages.cjs"),le=require("./goal-status-banner.cjs"),ue=require("./model-messages.cjs"),de=require("./components/resolve-picker-kind.cjs"),fe=require("../../../hooks/use-is-archived-conversation.cjs"),h=require("../../shared/loading-spinner.cjs"),pe=require("../../../hooks/use-scroll-to-bottom.cjs"),me=require("../../../context/scroll-context.cjs"),he=require("./interactive-chat-box.cjs"),ge=require("../../../hooks/use-filtered-events.cjs"),_e=require("../../../hooks/use-load-older-events.cjs"),ve=require("./typing-indicator.cjs"),ye=require("./chat-suggestions.cjs"),be=require("../../../stores/initial-query-store.cjs"),xe=require("../../../hooks/use-handle-build-plan-click.cjs"),Se=require("../../shared/buttons/scroll-to-bottom-button.cjs"),Ce=require("./chat-messages-skeleton.cjs"),we=require("./error-message-banner.cjs"),Te=require("./skill-install-restart-banner.cjs"),Ee=require("../../../hooks/use-llm-configured.cjs"),De=require("../home/llm-not-configured-banner.cjs"),Oe=require("../../conversation-events/chat/messages.cjs"),ke=require("./pending-user-messages.cjs"),Ae=require("../../../hooks/mutation/use-unified-upload-files.cjs"),je=require("./confirmation-mode-enabled.cjs"),Me=require("./chat-status-indicator.cjs"),Ne=require("../../../hooks/mutation/use-new-conversation-command.cjs");let g=require("react");g=e.__toESM(g,1);let _=require("react/jsx-runtime"),Pe=require("react-router");function Fe(e,t){return e?`github`:t?`replay`:`direct`}function v(){let{trackInitialQuerySubmitted:e,trackUserMessageSent:v}=ae.useTracking(),{setMessageToSend:y}=o.useConversationStore(),{errorMessage:b,errorCode:x,removeErrorMessage:Ie,setErrorMessage:S}=c.useErrorMessageStore(),Le=(0,Pe.useNavigate)(),{isTask:C,taskStatus:w,taskDetail:Re}=ie.useTaskPolling(),T=C,E=ee.useConversationWebSocket(),{send:ze}=f.useSendMessage(),{renderableEvents:D,allConversationEvents:O,totalEvents:k,hasSubstantiveAgentActions:A,userEventsExist:j}=ge.useFilteredEvents(),Be=l.useOptimisticUserMessageStore(e=>e.enqueuePendingMessage),Ve=l.useOptimisticUserMessageStore(e=>e.markPendingMessageError),M=l.useOptimisticUserMessageStore(e=>e.pendingMessages),{t:N}=t.useTranslation(`openhands`),P=g.default.useRef(null),{scrollDomToBottom:F,onChatBodyScroll:I,hitBottom:L,autoScroll:R,setAutoScroll:He,setHitBottom:Ue}=pe.useScrollToBottom(P),{mutate:We,isPending:z}=Ne.useNewConversationCommand(),{curAgentState:B}=p.useAgentState(),{handleBuildPlanClick:V}=xe.useHandleBuildPlanClick(),{data:Ge}=te.useActiveConversation(),H=Ge?.sandbox_status??null,U=fe.useIsArchivedConversation(),{isConfigured:Ke,isLoading:qe}=Ee.useLlmConfigured(),W=!qe&&!Ke,Je=B===r.AgentState.RUNNING||B===r.AgentState.LOADING;g.default.useEffect(()=>{if(Je)return;let e=e=>{(e.metaKey||e.ctrlKey)&&e.key===`Enter`&&(e.preventDefault(),e.stopPropagation(),V(e),F())};return document.addEventListener(`keydown`,e),()=>{document.removeEventListener(`keydown`,e)}},[Je,V,F]);let{selectedRepository:Ye,replayJson:Xe}=be.useInitialQueryStore(),{conversationId:G}=a.useOptionalConversationId(),Ze=u.useGoalStore(e=>{let t=G?e.statusByConversation[G]:void 0;return t?.active?`${t.iteration}:${t.status}`:null}),{mutateAsync:Qe}=Ae.useUnifiedUploadFiles(),{isLoading:K,hasMore:q,loadOlder:$e}=_e.useLoadOlderEvents(G),J=g.default.useRef(null),Y=g.default.useCallback(e=>{if(T||K||!q)return;let t=e.scrollTop<=80,r=e.scrollHeight<=e.clientHeight+80;!t&&!r||(J.current={scrollHeight:e.scrollHeight,scrollTop:e.scrollTop},$e().catch(e=>{J.current=null,S(e instanceof Error&&e.message?e.message:N(n.I18nKey.ERROR$GENERIC))}))},[q,K,T,$e,S,N]),et=g.default.useCallback(e=>{e.deltaY<0&&e.currentTarget.scrollTop<=0&&Y(e.currentTarget)},[Y]),X=g.default.useMemo(()=>G?M.some(e=>m.matchesPendingConversationId(G,e.conversationId)):!1,[M,G]),tt=d.useModelStore(e=>G?(e.entriesByConversation[G]?.length??0)>0:!1),nt=de.hasConversationStarted({isLoadingHistory:E?.isLoadingHistory===!0,hasUserEvents:j,hasPendingUserMessages:X,hasSubstantiveAgentActions:A,hasModelEntries:tt}),rt=O.length>0||X||!E?.isLoadingHistory,it=!!G,Z=!rt&&!C,at=async(t,r,i)=>{if(t.trim()===`/new`){if(!G){s.displayErrorToast(N(n.I18nKey.CONVERSATION$CLEAR_NO_ID));return}if(k===0){s.displayErrorToast(N(n.I18nKey.CONVERSATION$CLEAR_EMPTY));return}if(z)return;We();return}let a=[...r],o=[...i];k===0?e({entryPoint:Fe(Ye!==null,Xe!==null),queryCharacterLength:t.length,replayJsonSize:Xe?.length}):v({sessionMessageCount:k,currentMessageLength:t.length});let c=re.validateFiles([...a,...o]);if(!c.isValid){s.displayErrorToast(`Error: ${c.errorMessage}`);return}let l=a.map(e=>ne.convertImageToBase64(e)),u=await Promise.all(l),d=new Date().toISOString(),{skipped_files:ee,uploaded_files:f}=o.length>0?await Qe({conversationId:G,files:o}):{skipped_files:[],uploaded_files:[]};ee.forEach(e=>s.displayErrorToast(e.reason));let te=`${N(n.I18nKey.CHAT_INTERFACE$AUGMENTED_PROMPT_FILES_TITLE)}: ${f.join(`
1
+ const e=require("../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../i18n/declaration.cjs"),r=require("../../../types/agent-state.cjs"),i=require("../../../utils/utils.cjs"),a=require("../../../hooks/use-conversation-id.cjs"),o=require("../../../stores/conversation-store.cjs"),s=require("../../../utils/custom-toast-handlers.cjs");require("../../../constants/server-connection-error.cjs");const c=require("../../../stores/error-message-store.cjs"),l=require("../../../stores/optimistic-user-message-store.cjs"),u=require("../../../stores/goal-store.cjs"),d=require("../../../stores/model-store.cjs"),f=require("../../../contexts/conversation-websocket-context.cjs"),p=require("../../../hooks/use-send-message.cjs"),m=require("../../../hooks/query/use-active-conversation.cjs"),h=require("../../../hooks/use-agent-state.cjs"),ee=require("../../../utils/convert-image-to-base-64.cjs"),te=require("../../../utils/file-validation.cjs"),g=require("../../../utils/pending-task-message-link.cjs"),ne=require("../../../hooks/query/use-task-polling.cjs"),re=require("../../../hooks/use-tracking.cjs"),ie=require("../../../utils/acp-error-codes.cjs"),ae=require("../../../services/chat-service.cjs"),oe=require("./btw-messages.cjs"),se=require("./goal-status-banner.cjs"),ce=require("./model-messages.cjs"),le=require("./components/resolve-picker-kind.cjs"),ue=require("../../../hooks/use-is-archived-conversation.cjs"),de=require("../../shared/loading-spinner.cjs"),fe=require("../../../hooks/use-scroll-to-bottom.cjs"),pe=require("../../../context/scroll-context.cjs"),me=require("./interactive-chat-box.cjs"),he=require("../../../hooks/use-filtered-events.cjs"),ge=require("../../../hooks/use-load-older-events.cjs"),_e=require("./typing-indicator.cjs"),ve=require("./chat-suggestions.cjs"),ye=require("../../../stores/initial-query-store.cjs"),be=require("../../../hooks/use-handle-build-plan-click.cjs"),xe=require("../../shared/buttons/scroll-to-bottom-button.cjs"),Se=require("./chat-messages-skeleton.cjs"),Ce=require("./error-message-banner.cjs"),we=require("./skill-install-restart-banner.cjs"),Te=require("../../../hooks/use-llm-configured.cjs"),Ee=require("../home/llm-not-configured-banner.cjs"),De=require("../../conversation-events/chat/messages.cjs"),Oe=require("./pending-user-messages.cjs"),ke=require("../../../hooks/mutation/use-unified-upload-files.cjs"),Ae=require("./confirmation-mode-enabled.cjs"),je=require("./chat-status-indicator.cjs"),Me=require("../../../hooks/mutation/use-new-conversation-command.cjs");let _=require("react");_=e.__toESM(_,1);let v=require("react/jsx-runtime"),Ne=require("react-router");function Pe(e,t){return e?`github`:t?`replay`:`direct`}function y(){let{trackInitialQuerySubmitted:e,trackUserMessageSent:y}=re.useTracking(),{setMessageToSend:b}=o.useConversationStore(),{errorMessage:x,errorCode:Fe,errorClassification:Ie,removeErrorMessage:Le,setErrorMessage:Re}=c.useErrorMessageStore(),ze=(0,Ne.useNavigate)(),{isTask:S,taskStatus:C,taskDetail:Be}=ne.useTaskPolling(),w=S,T=f.useConversationWebSocket(),{send:Ve}=p.useSendMessage(),{renderableEvents:E,allConversationEvents:D,totalEvents:O,hasSubstantiveAgentActions:k,userEventsExist:A}=he.useFilteredEvents(),He=l.useOptimisticUserMessageStore(e=>e.enqueuePendingMessage),Ue=l.useOptimisticUserMessageStore(e=>e.markPendingMessageError),We=l.useOptimisticUserMessageStore(e=>e.pendingMessages),{t:j}=t.useTranslation(`openhands`),M=_.default.useRef(null),{scrollDomToBottom:N,onChatBodyScroll:Ge,hitBottom:P,autoScroll:F,setAutoScroll:Ke,setHitBottom:qe}=fe.useScrollToBottom(M),{mutate:Je,isPending:I}=Me.useNewConversationCommand(),{curAgentState:L}=h.useAgentState(),{handleBuildPlanClick:R}=be.useHandleBuildPlanClick(),{data:Ye}=m.useActiveConversation(),z=Ye?.sandbox_status??null,B=ue.useIsArchivedConversation(),{isConfigured:Xe,isLoading:Ze}=Te.useLlmConfigured(),V=!Ze&&!Xe,H=L===r.AgentState.RUNNING||L===r.AgentState.LOADING;_.default.useEffect(()=>{if(H)return;let e=e=>{(e.metaKey||e.ctrlKey)&&e.key===`Enter`&&(e.preventDefault(),e.stopPropagation(),R(e),N())};return document.addEventListener(`keydown`,e),()=>{document.removeEventListener(`keydown`,e)}},[H,R,N]);let{selectedRepository:Qe,replayJson:U}=ye.useInitialQueryStore(),{conversationId:W}=a.useOptionalConversationId(),$e=u.useGoalStore(e=>{let t=W?e.statusByConversation[W]:void 0;return t?.active?`${t.iteration}:${t.status}`:null}),{mutateAsync:et}=ke.useUnifiedUploadFiles(),{isLoading:G,hasMore:K,loadOlder:q}=ge.useLoadOlderEvents(W),J=_.default.useRef(null),Y=_.default.useCallback(e=>{if(w||G||!K)return;let t=e.scrollTop<=80,r=e.scrollHeight<=e.clientHeight+80;!t&&!r||(J.current={scrollHeight:e.scrollHeight,scrollTop:e.scrollTop},q().catch(e=>{J.current=null,Re(e instanceof Error&&e.message?e.message:j(n.I18nKey.ERROR$GENERIC))}))},[K,G,w,q,Re,j]),tt=_.default.useCallback(e=>{e.deltaY<0&&e.currentTarget.scrollTop<=0&&Y(e.currentTarget)},[Y]),X=_.default.useMemo(()=>W?We.some(e=>g.matchesPendingConversationId(W,e.conversationId)):!1,[We,W]),nt=d.useModelStore(e=>W?(e.entriesByConversation[W]?.length??0)>0:!1),rt=le.hasConversationStarted({isLoadingHistory:T?.isLoadingHistory===!0,hasUserEvents:A,hasPendingUserMessages:X,hasSubstantiveAgentActions:k,hasModelEntries:nt}),it=D.length>0||X||!T?.isLoadingHistory,at=!!W,Z=!it&&!S,ot=async(t,r,i)=>{if(t.trim()===`/new`){if(!W){s.displayErrorToast(j(n.I18nKey.CONVERSATION$CLEAR_NO_ID));return}if(O===0){s.displayErrorToast(j(n.I18nKey.CONVERSATION$CLEAR_EMPTY));return}if(I)return;Je();return}let a=[...r],o=[...i];O===0?e({entryPoint:Pe(Qe!==null,U!==null),queryCharacterLength:t.length,replayJsonSize:U?.length}):y({sessionMessageCount:O,currentMessageLength:t.length});let c=te.validateFiles([...a,...o]);if(!c.isValid){s.displayErrorToast(`Error: ${c.errorMessage}`);return}let l=a.map(e=>ee.convertImageToBase64(e)),u=await Promise.all(l),d=new Date().toISOString(),{skipped_files:f,uploaded_files:p}=o.length>0?await et({conversationId:W,files:o}):{skipped_files:[],uploaded_files:[]};f.forEach(e=>s.displayErrorToast(e.reason));let m=`${j(n.I18nKey.CHAT_INTERFACE$AUGMENTED_PROMPT_FILES_TITLE)}: ${p.join(`
2
2
 
3
- `)}`,p=f.length>0?`${t}\n\n${te}`:t,m=Be({conversationId:G,text:t,content:p,imageUrls:u,fileUrls:f,timestamp:d});F(),y(``);try{await ze(se.createChatMessage(p,u,f,d))}catch(e){Ve(m,e instanceof Error?e.message:N(n.I18nKey.CHAT_INTERFACE$FAILED_TO_SEND_MESSAGE))}};g.default.useEffect(()=>{if(J.current&&P.current){let{scrollHeight:e,scrollTop:t}=J.current,n=P.current,r=n.scrollHeight-e;r>0&&(n.scrollTop=t+r),J.current=null;return}R&&F()},[D.length,X,Ze,F]);let ot=g.default.useRef(Y);g.default.useEffect(()=>{ot.current=Y}),g.default.useEffect(()=>{let e=P.current;e&&ot.current(e)},[D.length,q]);let st={scrollRef:P,autoScroll:R,setAutoScroll:He,scrollDomToBottom:F,hitBottom:L,setHitBottom:Ue,onChatBodyScroll:I},Q=B===r.AgentState.LOADING||B===r.AgentState.INIT,ct=B===r.AgentState.STOPPED,$=B===r.AgentState.PAUSED,lt=i.getStatusColor({isPausing:$,isTask:C,taskStatus:w,isStartingStatus:Q,isStopStatus:ct,curAgentState:B}),ut=i.getStatusText({isPausing:$,isTask:C,taskStatus:w,taskDetail:Re,isStartingStatus:Q,isStopStatus:ct,curAgentState:B,errorMessage:b,t:N});return(0,_.jsx)(me.ScrollProvider,{value:st,children:(0,_.jsxs)(`div`,{className:`relative flex h-full flex-col justify-between px-4`,"data-testid":`chat-interface`,children:[!A&&!X&&!j&&!tt&&!Z&&!T&&k===0&&!U&&!W&&(0,_.jsx)(ye.ChatSuggestions,{onSuggestionsClick:e=>y(e)}),(0,_.jsxs)(`div`,{ref:P,"data-testid":`chat-scroll-container`,onScroll:e=>{I(e.currentTarget),Y(e.currentTarget)},onWheel:et,className:`custom-scrollbar-always flex min-h-0 grow flex-col gap-2 overflow-x-hidden overflow-y-auto px-0 pt-4 pb-8 md:px-4`,children:[Z&&it&&(0,_.jsx)(Ce.ChatMessagesSkeleton,{}),Z&&!it&&(0,_.jsx)(`div`,{className:`flex justify-center`,"data-testid":`loading-spinner`,children:(0,_.jsx)(h.LoadingSpinner,{size:`small`})}),K&&(0,_.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-3 text-sm text-neutral-400`,"data-testid":`loading-older-events`,children:[(0,_.jsx)(h.LoadingSpinner,{size:`small`}),(0,_.jsx)(`span`,{children:N(n.I18nKey.CHAT_INTERFACE$FETCHING_OLDER_MESSAGES)})]}),(0,_.jsx)(ue.ModelMessages,{conversationId:G,anchorEventId:null}),rt&&D.length>0&&(0,_.jsx)(Oe.Messages,{messages:D,allEvents:O}),(0,_.jsx)(ke.PendingUserMessages,{}),(0,_.jsx)(le.GoalStatusBanner,{conversationId:G})]}),(0,_.jsxs)(`div`,{className:`flex shrink-0 flex-col gap-[6px] pb-4`,children:[(0,_.jsx)(Te.SkillInstallRestartBanner,{conversationId:G}),(0,_.jsx)(ce.BtwMessages,{conversationId:G}),b&&(0,_.jsx)(we.ErrorMessageBanner,{message:b,code:x,onDismiss:Ie,onRetry:b===`Unable to connect to server`?()=>E?.reconnect():void 0,onReauth:oe.isAcpAuthErrorCode(x)?()=>Le(`/settings/agents`):void 0}),W&&!U&&(0,_.jsx)(De.LlmNotConfiguredBanner,{}),U?(0,_.jsxs)(`div`,{"data-testid":`archived-conversation-banner`,className:`mx-1 px-4 py-3 rounded-lg bg-[var(--oh-surface)] border border-[var(--oh-border-subtle)]`,children:[(0,_.jsx)(`p`,{className:`text-xs font-semibold text-[var(--oh-foreground)]`,children:N(H===`ERROR`?n.I18nKey.CHAT_INTERFACE$ERROR_SANDBOX_TITLE:n.I18nKey.CHAT_INTERFACE$ARCHIVED_SANDBOX_TITLE)}),(0,_.jsx)(`p`,{className:`text-xs text-[var(--oh-muted)] mt-0.5`,children:N(H===`ERROR`?n.I18nKey.CHAT_INTERFACE$ERROR_SANDBOX_DESCRIPTION:n.I18nKey.CHAT_INTERFACE$ARCHIVED_SANDBOX_DESCRIPTION)})]}):(0,_.jsxs)(`div`,{className:`relative`,children:[(0,_.jsx)(`div`,{className:`pointer-events-none absolute inset-x-0 bottom-full mb-1 z-20`,children:(0,_.jsxs)(`div`,{className:`flex justify-between relative`,children:[(0,_.jsxs)(`div`,{className:`flex items-end gap-1 pointer-events-auto`,children:[(0,_.jsx)(je.default,{}),Q&&(0,_.jsx)(Me.default,{statusColor:lt,status:ut})]}),L?B===r.AgentState.RUNNING&&(0,_.jsx)(`div`,{className:`pointer-events-none absolute inset-x-9 bottom-0 flex justify-center`,children:(0,_.jsx)(ve.TypingIndicator,{events:O})}):(0,_.jsx)(`div`,{className:`absolute left-1/2 transform -translate-x-1/2 bottom-0 pointer-events-auto`,children:(0,_.jsx)(Se.ScrollToBottomButton,{onClick:F})})]})}),(0,_.jsx)(he.InteractiveChatBox,{onSubmit:at,disabled:z||W,hasStartedConversation:nt})]})]})]})})}exports.ChatInterface=v;
3
+ `)}`,h=p.length>0?`${t}\n\n${m}`:t,g=He({conversationId:W,text:t,content:h,imageUrls:u,fileUrls:p,timestamp:d});N(),b(``);try{await Ve(ae.createChatMessage(h,u,p,d))}catch(e){Ue(g,e instanceof Error?e.message:j(n.I18nKey.CHAT_INTERFACE$FAILED_TO_SEND_MESSAGE))}};_.default.useEffect(()=>{if(J.current&&M.current){let{scrollHeight:e,scrollTop:t}=J.current,n=M.current,r=n.scrollHeight-e;r>0&&(n.scrollTop=t+r),J.current=null;return}F&&N()},[E.length,X,$e,N]);let Q=_.default.useRef(Y);_.default.useEffect(()=>{Q.current=Y}),_.default.useEffect(()=>{let e=M.current;e&&Q.current(e)},[E.length,K]);let st={scrollRef:M,autoScroll:F,setAutoScroll:Ke,scrollDomToBottom:N,hitBottom:P,setHitBottom:qe,onChatBodyScroll:Ge},$=L===r.AgentState.LOADING||L===r.AgentState.INIT,ct=L===r.AgentState.STOPPED,lt=L===r.AgentState.PAUSED,ut=i.getStatusColor({isPausing:lt,isTask:S,taskStatus:C,isStartingStatus:$,isStopStatus:ct,curAgentState:L}),dt=i.getStatusText({isPausing:lt,isTask:S,taskStatus:C,taskDetail:Be,isStartingStatus:$,isStopStatus:ct,curAgentState:L,errorMessage:x,t:j});return(0,v.jsx)(pe.ScrollProvider,{value:st,children:(0,v.jsxs)(`div`,{className:`relative flex h-full flex-col justify-between px-4`,"data-testid":`chat-interface`,children:[!k&&!X&&!A&&!nt&&!Z&&!w&&O===0&&!B&&!V&&(0,v.jsx)(ve.ChatSuggestions,{onSuggestionsClick:e=>b(e)}),(0,v.jsxs)(`div`,{ref:M,"data-testid":`chat-scroll-container`,onScroll:e=>{Ge(e.currentTarget),Y(e.currentTarget)},onWheel:tt,className:`custom-scrollbar-always flex min-h-0 grow flex-col gap-2 overflow-x-hidden overflow-y-auto px-0 pt-4 pb-8 md:px-4`,children:[Z&&at&&(0,v.jsx)(Se.ChatMessagesSkeleton,{}),Z&&!at&&(0,v.jsx)(`div`,{className:`flex justify-center`,"data-testid":`loading-spinner`,children:(0,v.jsx)(de.LoadingSpinner,{size:`small`})}),G&&(0,v.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-3 text-sm text-neutral-400`,"data-testid":`loading-older-events`,children:[(0,v.jsx)(de.LoadingSpinner,{size:`small`}),(0,v.jsx)(`span`,{children:j(n.I18nKey.CHAT_INTERFACE$FETCHING_OLDER_MESSAGES)})]}),(0,v.jsx)(ce.ModelMessages,{conversationId:W,anchorEventId:null}),it&&E.length>0&&(0,v.jsx)(De.Messages,{messages:E,allEvents:D}),(0,v.jsx)(Oe.PendingUserMessages,{}),(0,v.jsx)(se.GoalStatusBanner,{conversationId:W})]}),(0,v.jsxs)(`div`,{className:`flex shrink-0 flex-col gap-[6px] pb-4`,children:[(0,v.jsx)(we.SkillInstallRestartBanner,{conversationId:W}),(0,v.jsx)(oe.BtwMessages,{conversationId:W}),x&&(0,v.jsx)(Ce.ErrorMessageBanner,{message:x,code:Fe,classification:Ie,onDismiss:Le,onRetry:x===`Unable to connect to server`?()=>T?.reconnect():void 0,onReauth:ie.isAcpAuthErrorCode(Fe)?()=>ze(`/settings/agents`):void 0}),V&&!B&&(0,v.jsx)(Ee.LlmNotConfiguredBanner,{}),B?(0,v.jsxs)(`div`,{"data-testid":`archived-conversation-banner`,className:`mx-1 px-4 py-3 rounded-lg bg-[var(--oh-surface)] border border-[var(--oh-border-subtle)]`,children:[(0,v.jsx)(`p`,{className:`text-xs font-semibold text-[var(--oh-foreground)]`,children:j(z===`ERROR`?n.I18nKey.CHAT_INTERFACE$ERROR_SANDBOX_TITLE:n.I18nKey.CHAT_INTERFACE$ARCHIVED_SANDBOX_TITLE)}),(0,v.jsx)(`p`,{className:`text-xs text-[var(--oh-muted)] mt-0.5`,children:j(z===`ERROR`?n.I18nKey.CHAT_INTERFACE$ERROR_SANDBOX_DESCRIPTION:n.I18nKey.CHAT_INTERFACE$ARCHIVED_SANDBOX_DESCRIPTION)})]}):(0,v.jsxs)(`div`,{className:`relative`,children:[(0,v.jsx)(`div`,{className:`pointer-events-none absolute inset-x-0 bottom-full mb-1 z-20`,children:(0,v.jsxs)(`div`,{className:`flex justify-between relative`,children:[(0,v.jsxs)(`div`,{className:`flex items-end gap-1 pointer-events-auto`,children:[(0,v.jsx)(Ae.default,{}),$&&(0,v.jsx)(je.default,{statusColor:ut,status:dt})]}),P?L===r.AgentState.RUNNING&&(0,v.jsx)(`div`,{className:`pointer-events-none absolute inset-x-9 bottom-0 flex justify-center`,children:(0,v.jsx)(_e.TypingIndicator,{events:D})}):(0,v.jsx)(`div`,{className:`absolute left-1/2 transform -translate-x-1/2 bottom-0 pointer-events-auto`,children:(0,v.jsx)(xe.ScrollToBottomButton,{onClick:N})})]})}),(0,v.jsx)(me.InteractiveChatBox,{onSubmit:ot,disabled:I||V,hasStartedConversation:rt})]})]})]})})}exports.ChatInterface=y;
4
4
  //# sourceMappingURL=chat-interface.cjs.map